Updated settings modal layout.
This commit is contained in:
@@ -37,6 +37,11 @@ PROTON_SYNC_LABELS: dict[str, str] = {
|
||||
"Esync": "esync",
|
||||
}
|
||||
|
||||
SETTINGS_STACKED_LAYOUT_WIDTH = 720
|
||||
SETTINGS_STACKED_FOOTER_WIDTH = 640
|
||||
SETTINGS_MINIMUM_WIDTH = 620
|
||||
SETTINGS_MINIMUM_HEIGHT = 520
|
||||
|
||||
|
||||
def open_settings_dialog(
|
||||
root: Any,
|
||||
@@ -74,7 +79,7 @@ def open_settings_dialog(
|
||||
dialog = tk.Toplevel(root)
|
||||
dialog.withdraw()
|
||||
dialog.title("PristonTale EU — Settings")
|
||||
dialog.resizable(False, False)
|
||||
dialog.resizable(True, True)
|
||||
dialog.configure(background="#0c0908")
|
||||
dialog.transient(root)
|
||||
apply_window_icon(dialog)
|
||||
@@ -121,12 +126,50 @@ def open_settings_dialog(
|
||||
font=("Sans", 9),
|
||||
).pack(anchor="w", pady=(2, 0))
|
||||
|
||||
content = ttk.Frame(
|
||||
settings_chrome.content,
|
||||
style="Root.TFrame",
|
||||
padding=(16, 14, 16, 16),
|
||||
body = ttk.Frame(settings_chrome.content, style="Root.TFrame")
|
||||
body.pack(fill="both", expand=True)
|
||||
body.columnconfigure(0, weight=1)
|
||||
body.rowconfigure(0, weight=1)
|
||||
settings_viewport = ttk.Frame(body, name="settings_viewport", style="Root.TFrame")
|
||||
settings_viewport.grid(
|
||||
row=0,
|
||||
column=0,
|
||||
sticky="nsew",
|
||||
padx=(16, 10),
|
||||
pady=(14, 8),
|
||||
)
|
||||
settings_viewport.columnconfigure(0, weight=1)
|
||||
settings_viewport.rowconfigure(0, weight=1)
|
||||
settings_canvas = tk.Canvas(
|
||||
settings_viewport,
|
||||
name="settings_canvas",
|
||||
background="#0c0908",
|
||||
borderwidth=0,
|
||||
highlightthickness=0,
|
||||
takefocus=True,
|
||||
yscrollincrement=max(1, round(24 * launcher_ui_scale)),
|
||||
)
|
||||
settings_canvas.grid(row=0, column=0, sticky="nsew")
|
||||
settings_scrollbar = ttk.Scrollbar(
|
||||
settings_viewport,
|
||||
name="settings_scrollbar",
|
||||
orient="vertical",
|
||||
style="News.Vertical.TScrollbar",
|
||||
command=settings_canvas.yview,
|
||||
)
|
||||
settings_scrollbar.grid(row=0, column=1, sticky="ns", padx=(6, 0))
|
||||
settings_canvas.configure(yscrollcommand=settings_scrollbar.set)
|
||||
content = ttk.Frame(
|
||||
settings_canvas,
|
||||
name="settings_content",
|
||||
style="Root.TFrame",
|
||||
padding=(0, 0, 0, 8),
|
||||
)
|
||||
content_window = settings_canvas.create_window(
|
||||
(0, 0),
|
||||
window=content,
|
||||
anchor="nw",
|
||||
)
|
||||
content.pack(fill="both", expand=True)
|
||||
content.columnconfigure(0, weight=1, uniform="settings-card")
|
||||
content.columnconfigure(1, weight=1, uniform="settings-card")
|
||||
|
||||
@@ -302,7 +345,7 @@ def open_settings_dialog(
|
||||
display_card.grid(row=0, column=0, sticky="nsew", padx=(0, 6))
|
||||
display_card.columnconfigure(0, weight=1)
|
||||
display_card.columnconfigure(1, weight=1)
|
||||
ttk.Label(
|
||||
display_hint = ttk.Label(
|
||||
display_card,
|
||||
text=(
|
||||
"Gamescope can resize the desktop window while keeping the game's 32-bit "
|
||||
@@ -314,7 +357,8 @@ def open_settings_dialog(
|
||||
),
|
||||
style="SettingsHint.TLabel",
|
||||
wraplength=360,
|
||||
).grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 11))
|
||||
)
|
||||
display_hint.grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 11))
|
||||
presentation = ttk.Frame(display_card, style="SettingsCard.TFrame")
|
||||
presentation.grid(row=1, column=0, columnspan=2, sticky="ew")
|
||||
ttk.Checkbutton(
|
||||
@@ -360,12 +404,13 @@ def open_settings_dialog(
|
||||
rendering_card.grid(row=0, column=1, sticky="nsew", padx=(6, 0))
|
||||
rendering_card.columnconfigure(0, weight=1)
|
||||
rendering_card.columnconfigure(1, weight=1)
|
||||
ttk.Label(
|
||||
rendering_hint = ttk.Label(
|
||||
rendering_card,
|
||||
text="Choose which compatibility runtime launches the proven game setup.",
|
||||
style="SettingsHint.TLabel",
|
||||
wraplength=360,
|
||||
).grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 11))
|
||||
)
|
||||
rendering_hint.grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 11))
|
||||
add_choice(
|
||||
rendering_card,
|
||||
1,
|
||||
@@ -511,29 +556,193 @@ def open_settings_dialog(
|
||||
choose_game_source,
|
||||
)
|
||||
|
||||
footer = ttk.Frame(content, style="SettingsFooter.TFrame", padding=(12, 9))
|
||||
footer.grid(row=3, column=0, columnspan=2, sticky="ew", pady=(12, 0))
|
||||
footer = ttk.Frame(
|
||||
body,
|
||||
name="settings_footer",
|
||||
style="SettingsFooter.TFrame",
|
||||
padding=(12, 9),
|
||||
)
|
||||
footer.grid(row=1, column=0, sticky="ew", padx=16, pady=(0, 16))
|
||||
footer.columnconfigure(0, weight=1)
|
||||
ttk.Label(
|
||||
footer_note = ttk.Label(
|
||||
footer,
|
||||
text="Only the settings shown here affect the next launcher operation.",
|
||||
style="SettingsFooter.TLabel",
|
||||
).grid(row=0, column=0, sticky="w")
|
||||
buttons_row = ttk.Frame(footer, style="SettingsFooter.TFrame")
|
||||
)
|
||||
footer_note.grid(row=0, column=0, sticky="w")
|
||||
buttons_row = ttk.Frame(
|
||||
footer,
|
||||
name="settings_buttons",
|
||||
style="SettingsFooter.TFrame",
|
||||
)
|
||||
buttons_row.grid(row=0, column=1, sticky="e")
|
||||
ttk.Button(
|
||||
buttons_row,
|
||||
name="settings_cancel",
|
||||
text="CANCEL",
|
||||
style="Secondary.TButton",
|
||||
command=close_settings,
|
||||
).pack(side="left")
|
||||
ttk.Button(
|
||||
buttons_row,
|
||||
name="settings_save",
|
||||
text="SAVE SETTINGS",
|
||||
style="Play.TButton",
|
||||
command=save_current_settings,
|
||||
).pack(side="left", padx=(8, 0))
|
||||
|
||||
settings_layout_mode: tuple[bool, bool] | None = None
|
||||
settings_layout_width: int | None = None
|
||||
pending_settings_width = 1
|
||||
settings_layout_after: str | None = None
|
||||
|
||||
def arrange_settings(viewport_width: int) -> None:
|
||||
"""Reflow cards and footer controls for the available logical width."""
|
||||
|
||||
nonlocal settings_layout_mode, settings_layout_width
|
||||
if settings_layout_width == viewport_width:
|
||||
return
|
||||
settings_layout_width = viewport_width
|
||||
logical_width = viewport_width / max(launcher_ui_scale, 0.01)
|
||||
stacked = logical_width < SETTINGS_STACKED_LAYOUT_WIDTH
|
||||
footer_stacked = logical_width < SETTINGS_STACKED_FOOTER_WIDTH
|
||||
card_width = (
|
||||
viewport_width
|
||||
if stacked
|
||||
else (viewport_width - round(12 * launcher_ui_scale)) // 2
|
||||
)
|
||||
card_wraplength = max(140, card_width - round(42 * launcher_ui_scale))
|
||||
display_hint.configure(wraplength=card_wraplength)
|
||||
rendering_hint.configure(wraplength=card_wraplength)
|
||||
footer_note.configure(
|
||||
wraplength=(
|
||||
max(140, viewport_width - round(42 * launcher_ui_scale))
|
||||
if footer_stacked
|
||||
else max(140, viewport_width - round(300 * launcher_ui_scale))
|
||||
)
|
||||
)
|
||||
|
||||
mode = (stacked, footer_stacked)
|
||||
if settings_layout_mode == mode:
|
||||
return
|
||||
settings_layout_mode = mode
|
||||
if stacked:
|
||||
display_card.grid_configure(
|
||||
row=0,
|
||||
column=0,
|
||||
columnspan=2,
|
||||
sticky="ew",
|
||||
padx=0,
|
||||
pady=0,
|
||||
)
|
||||
rendering_card.grid_configure(
|
||||
row=1,
|
||||
column=0,
|
||||
columnspan=2,
|
||||
sticky="ew",
|
||||
padx=0,
|
||||
pady=(12, 0),
|
||||
)
|
||||
downloads_card.grid_configure(row=2, pady=(12, 0))
|
||||
overrides_card.grid_configure(row=3, pady=(12, 0))
|
||||
else:
|
||||
display_card.grid_configure(
|
||||
row=0,
|
||||
column=0,
|
||||
columnspan=1,
|
||||
sticky="nsew",
|
||||
padx=(0, 6),
|
||||
pady=0,
|
||||
)
|
||||
rendering_card.grid_configure(
|
||||
row=0,
|
||||
column=1,
|
||||
columnspan=1,
|
||||
sticky="nsew",
|
||||
padx=(6, 0),
|
||||
pady=0,
|
||||
)
|
||||
downloads_card.grid_configure(row=1, pady=(12, 0))
|
||||
overrides_card.grid_configure(row=2, pady=(12, 0))
|
||||
|
||||
if footer_stacked:
|
||||
footer_note.grid_configure(row=0, column=0, columnspan=2)
|
||||
buttons_row.grid_configure(
|
||||
row=1,
|
||||
column=0,
|
||||
columnspan=2,
|
||||
pady=(8, 0),
|
||||
)
|
||||
else:
|
||||
footer_note.grid_configure(row=0, column=0, columnspan=1)
|
||||
buttons_row.grid_configure(
|
||||
row=0,
|
||||
column=1,
|
||||
columnspan=1,
|
||||
pady=0,
|
||||
)
|
||||
|
||||
def refresh_scroll_region(_event: object | None = None) -> None:
|
||||
bounds = settings_canvas.bbox("all")
|
||||
if bounds is not None:
|
||||
settings_canvas.configure(scrollregion=bounds)
|
||||
|
||||
def apply_pending_settings_layout() -> None:
|
||||
nonlocal settings_layout_after
|
||||
settings_layout_after = None
|
||||
arrange_settings(pending_settings_width)
|
||||
|
||||
def resize_settings_content(event: Any) -> None:
|
||||
nonlocal pending_settings_width, settings_layout_after
|
||||
pending_settings_width = max(1, int(event.width))
|
||||
settings_canvas.itemconfigure(content_window, width=pending_settings_width)
|
||||
if settings_layout_after is None:
|
||||
settings_layout_after = dialog.after_idle(apply_pending_settings_layout)
|
||||
|
||||
def scroll_settings(event: Any) -> str | None:
|
||||
canvas_left = settings_canvas.winfo_rootx()
|
||||
canvas_top = settings_canvas.winfo_rooty()
|
||||
pointer_x = dialog.winfo_pointerx()
|
||||
pointer_y = dialog.winfo_pointery()
|
||||
if not (
|
||||
canvas_left <= pointer_x < canvas_left + settings_canvas.winfo_width()
|
||||
and canvas_top <= pointer_y < canvas_top + settings_canvas.winfo_height()
|
||||
):
|
||||
return None
|
||||
if getattr(event.widget, "winfo_class", lambda: "")() == "TCombobox":
|
||||
return None
|
||||
first, last = settings_canvas.yview()
|
||||
if last - first >= 0.999:
|
||||
return None
|
||||
if getattr(event, "num", None) == 4:
|
||||
units = -3
|
||||
elif getattr(event, "num", None) == 5:
|
||||
units = 3
|
||||
else:
|
||||
delta = int(getattr(event, "delta", 0))
|
||||
if delta == 0:
|
||||
return None
|
||||
steps = max(1, min(4, abs(delta) // 120 or 1))
|
||||
units = -steps if delta > 0 else steps
|
||||
settings_canvas.yview_scroll(units, "units")
|
||||
return "break"
|
||||
|
||||
content.bind("<Configure>", refresh_scroll_region)
|
||||
settings_canvas.bind("<Configure>", resize_settings_content)
|
||||
dialog.bind("<MouseWheel>", scroll_settings, add="+")
|
||||
dialog.bind("<Button-4>", scroll_settings, add="+")
|
||||
dialog.bind("<Button-5>", scroll_settings, add="+")
|
||||
settings_canvas.bind("<Home>", lambda _event: settings_canvas.yview_moveto(0.0))
|
||||
settings_canvas.bind("<End>", lambda _event: settings_canvas.yview_moveto(1.0))
|
||||
settings_canvas.bind(
|
||||
"<Prior>",
|
||||
lambda _event: settings_canvas.yview_scroll(-1, "pages"),
|
||||
)
|
||||
settings_canvas.bind(
|
||||
"<Next>",
|
||||
lambda _event: settings_canvas.yview_scroll(1, "pages"),
|
||||
)
|
||||
|
||||
dialog.protocol("WM_DELETE_WINDOW", close_settings)
|
||||
dialog.bind("<Escape>", lambda _event: close_settings())
|
||||
dialog.bind("<Control-s>", lambda _event: save_current_settings())
|
||||
@@ -545,6 +754,14 @@ def open_settings_dialog(
|
||||
screen_width=dialog.winfo_screenwidth(),
|
||||
screen_height=dialog.winfo_screenheight(),
|
||||
)
|
||||
minimum_width, minimum_height = fitted_window_size(
|
||||
SETTINGS_MINIMUM_WIDTH,
|
||||
SETTINGS_MINIMUM_HEIGHT,
|
||||
scale=launcher_ui_scale,
|
||||
screen_width=dialog.winfo_screenwidth(),
|
||||
screen_height=dialog.winfo_screenheight(),
|
||||
)
|
||||
dialog.minsize(minimum_width, minimum_height)
|
||||
dialog.geometry(
|
||||
centered_window_geometry(
|
||||
settings_width,
|
||||
|
||||
Reference in New Issue
Block a user