Updated settings modal layout.

This commit is contained in:
2026-09-06 20:59:48 +02:00
parent 3a01c6ba2a
commit f9a6d6aed0

View File

@@ -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,