Updated settings modal layout.
This commit is contained in:
@@ -37,6 +37,11 @@ PROTON_SYNC_LABELS: dict[str, str] = {
|
|||||||
"Esync": "esync",
|
"Esync": "esync",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SETTINGS_STACKED_LAYOUT_WIDTH = 720
|
||||||
|
SETTINGS_STACKED_FOOTER_WIDTH = 640
|
||||||
|
SETTINGS_MINIMUM_WIDTH = 620
|
||||||
|
SETTINGS_MINIMUM_HEIGHT = 520
|
||||||
|
|
||||||
|
|
||||||
def open_settings_dialog(
|
def open_settings_dialog(
|
||||||
root: Any,
|
root: Any,
|
||||||
@@ -74,7 +79,7 @@ def open_settings_dialog(
|
|||||||
dialog = tk.Toplevel(root)
|
dialog = tk.Toplevel(root)
|
||||||
dialog.withdraw()
|
dialog.withdraw()
|
||||||
dialog.title("PristonTale EU — Settings")
|
dialog.title("PristonTale EU — Settings")
|
||||||
dialog.resizable(False, False)
|
dialog.resizable(True, True)
|
||||||
dialog.configure(background="#0c0908")
|
dialog.configure(background="#0c0908")
|
||||||
dialog.transient(root)
|
dialog.transient(root)
|
||||||
apply_window_icon(dialog)
|
apply_window_icon(dialog)
|
||||||
@@ -121,12 +126,50 @@ def open_settings_dialog(
|
|||||||
font=("Sans", 9),
|
font=("Sans", 9),
|
||||||
).pack(anchor="w", pady=(2, 0))
|
).pack(anchor="w", pady=(2, 0))
|
||||||
|
|
||||||
content = ttk.Frame(
|
body = ttk.Frame(settings_chrome.content, style="Root.TFrame")
|
||||||
settings_chrome.content,
|
body.pack(fill="both", expand=True)
|
||||||
style="Root.TFrame",
|
body.columnconfigure(0, weight=1)
|
||||||
padding=(16, 14, 16, 16),
|
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(0, weight=1, uniform="settings-card")
|
||||||
content.columnconfigure(1, 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.grid(row=0, column=0, sticky="nsew", padx=(0, 6))
|
||||||
display_card.columnconfigure(0, weight=1)
|
display_card.columnconfigure(0, weight=1)
|
||||||
display_card.columnconfigure(1, weight=1)
|
display_card.columnconfigure(1, weight=1)
|
||||||
ttk.Label(
|
display_hint = ttk.Label(
|
||||||
display_card,
|
display_card,
|
||||||
text=(
|
text=(
|
||||||
"Gamescope can resize the desktop window while keeping the game's 32-bit "
|
"Gamescope can resize the desktop window while keeping the game's 32-bit "
|
||||||
@@ -314,7 +357,8 @@ def open_settings_dialog(
|
|||||||
),
|
),
|
||||||
style="SettingsHint.TLabel",
|
style="SettingsHint.TLabel",
|
||||||
wraplength=360,
|
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 = ttk.Frame(display_card, style="SettingsCard.TFrame")
|
||||||
presentation.grid(row=1, column=0, columnspan=2, sticky="ew")
|
presentation.grid(row=1, column=0, columnspan=2, sticky="ew")
|
||||||
ttk.Checkbutton(
|
ttk.Checkbutton(
|
||||||
@@ -360,12 +404,13 @@ def open_settings_dialog(
|
|||||||
rendering_card.grid(row=0, column=1, sticky="nsew", padx=(6, 0))
|
rendering_card.grid(row=0, column=1, sticky="nsew", padx=(6, 0))
|
||||||
rendering_card.columnconfigure(0, weight=1)
|
rendering_card.columnconfigure(0, weight=1)
|
||||||
rendering_card.columnconfigure(1, weight=1)
|
rendering_card.columnconfigure(1, weight=1)
|
||||||
ttk.Label(
|
rendering_hint = ttk.Label(
|
||||||
rendering_card,
|
rendering_card,
|
||||||
text="Choose which compatibility runtime launches the proven game setup.",
|
text="Choose which compatibility runtime launches the proven game setup.",
|
||||||
style="SettingsHint.TLabel",
|
style="SettingsHint.TLabel",
|
||||||
wraplength=360,
|
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(
|
add_choice(
|
||||||
rendering_card,
|
rendering_card,
|
||||||
1,
|
1,
|
||||||
@@ -511,29 +556,193 @@ def open_settings_dialog(
|
|||||||
choose_game_source,
|
choose_game_source,
|
||||||
)
|
)
|
||||||
|
|
||||||
footer = ttk.Frame(content, style="SettingsFooter.TFrame", padding=(12, 9))
|
footer = ttk.Frame(
|
||||||
footer.grid(row=3, column=0, columnspan=2, sticky="ew", pady=(12, 0))
|
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)
|
footer.columnconfigure(0, weight=1)
|
||||||
ttk.Label(
|
footer_note = ttk.Label(
|
||||||
footer,
|
footer,
|
||||||
text="Only the settings shown here affect the next launcher operation.",
|
text="Only the settings shown here affect the next launcher operation.",
|
||||||
style="SettingsFooter.TLabel",
|
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")
|
buttons_row.grid(row=0, column=1, sticky="e")
|
||||||
ttk.Button(
|
ttk.Button(
|
||||||
buttons_row,
|
buttons_row,
|
||||||
|
name="settings_cancel",
|
||||||
text="CANCEL",
|
text="CANCEL",
|
||||||
style="Secondary.TButton",
|
style="Secondary.TButton",
|
||||||
command=close_settings,
|
command=close_settings,
|
||||||
).pack(side="left")
|
).pack(side="left")
|
||||||
ttk.Button(
|
ttk.Button(
|
||||||
buttons_row,
|
buttons_row,
|
||||||
|
name="settings_save",
|
||||||
text="SAVE SETTINGS",
|
text="SAVE SETTINGS",
|
||||||
style="Play.TButton",
|
style="Play.TButton",
|
||||||
command=save_current_settings,
|
command=save_current_settings,
|
||||||
).pack(side="left", padx=(8, 0))
|
).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.protocol("WM_DELETE_WINDOW", close_settings)
|
||||||
dialog.bind("<Escape>", lambda _event: close_settings())
|
dialog.bind("<Escape>", lambda _event: close_settings())
|
||||||
dialog.bind("<Control-s>", lambda _event: save_current_settings())
|
dialog.bind("<Control-s>", lambda _event: save_current_settings())
|
||||||
@@ -545,6 +754,14 @@ def open_settings_dialog(
|
|||||||
screen_width=dialog.winfo_screenwidth(),
|
screen_width=dialog.winfo_screenwidth(),
|
||||||
screen_height=dialog.winfo_screenheight(),
|
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(
|
dialog.geometry(
|
||||||
centered_window_geometry(
|
centered_window_geometry(
|
||||||
settings_width,
|
settings_width,
|
||||||
|
|||||||
Reference in New Issue
Block a user