mirror of
https://github.com/kuhyx/screen-locker.git
synced 2026-11-11 12:47:41 +01:00
self._colors = LockConfig(...) is now built unconditionally in ScreenLocker.__init__ (previously only the fullscreen lock path built a local `config`), and every raw hex literal across status_view.py, _ui_flows.py, _ui_flows_relaxed.py, _sick_dialog.py, _manual_workout_dialog.py, _manual_workout_widgets.py, and _temperature_status_mixin.py now reads from it instead -- replacing ad hoc greens/oranges/reds (#00ff00, #0066cc, #ff4444, ...) with the shared success/accent/danger/warning/muted tokens. Also fixes the verify-window and status-window paths that still hardcoded #1a1a1a for the background. This was the prerequisite the on-fill fix (previous commit) actually needed: _window_setup.py/_ui_widgets.py/_heat_skip.py reference self._colors, which nothing in the codebase constructed outside the fullscreen lock path until this commit. Verified: 859/859 tests, 100% coverage.
177 lines
6.1 KiB
Python
177 lines
6.1 KiB
Python
"""Low-level widget/grid builders for the manual-workout evidence form.
|
|
|
|
Split out of ``_manual_workout_dialog`` so the dialog module stays under the
|
|
repo's file-length cap. These helpers build individual form cells and place
|
|
them into a two-column grid; the orchestration (which fields, in what order,
|
|
and submission) lives in ``ManualWorkoutDialogMixin``, which inherits this.
|
|
|
|
The host is expected to have initialised ``self._mw_grid_counters`` (per-master
|
|
grid cursors) and, for ``_mw_rpe_row``, ``self._mw_rpe_var``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import tkinter as tk
|
|
|
|
from screen_locker._constants import (
|
|
MANUAL_WORKOUT_RPE_MAX,
|
|
MANUAL_WORKOUT_RPE_MIN,
|
|
)
|
|
from screen_locker._ui_widgets import disable_paste
|
|
|
|
|
|
class ManualWorkoutFormWidgetsMixin:
|
|
"""Two-column grid placement + individual field-cell builders."""
|
|
|
|
def _mw_grid(
|
|
self, parent: tk.Widget, widget: tk.Widget, *, full: bool = False
|
|
) -> None:
|
|
"""Place ``widget`` into ``parent``'s two-column grid cursor.
|
|
|
|
A half-width item (``full=False``) fills the next cell (left, then
|
|
right); a ``full`` item starts a fresh row and spans both columns. Each
|
|
master keeps its own cursor (keyed by ``id(parent)``) so nested sport
|
|
frames grid independently of the main form.
|
|
"""
|
|
counters = self._mw_grid_counters
|
|
idx = counters.get(id(parent), 0)
|
|
if full and idx % 2 == 1:
|
|
idx += 1 # a full-width item can't share a row — bump to a new one
|
|
row, col = divmod(idx, 2)
|
|
widget.grid(
|
|
row=row,
|
|
column=col,
|
|
columnspan=2 if full else 1,
|
|
sticky="ew",
|
|
padx=12,
|
|
pady=8,
|
|
)
|
|
counters[id(parent)] = idx + (2 if full else 1)
|
|
|
|
def _mw_next_full_row(self, parent: tk.Widget) -> int:
|
|
"""Reserve a fresh full-width row for a manually-gridded widget.
|
|
|
|
Used for the twin sport frames, which share one slot and are gridded
|
|
directly (not through ``_mw_grid``); this advances the cursor past that
|
|
row so following fields resume cleanly.
|
|
"""
|
|
counters = self._mw_grid_counters
|
|
idx = counters.get(id(parent), 0)
|
|
if idx % 2 == 1:
|
|
idx += 1
|
|
counters[id(parent)] = idx + 2
|
|
return idx // 2
|
|
|
|
def _mw_section(self, parent: tk.Widget, title: str) -> None:
|
|
"""Add a full-width section heading inside the form."""
|
|
label = tk.Label(
|
|
parent,
|
|
text=title,
|
|
font=(self._colors.font_family, 20, "bold"),
|
|
fg=self._colors.accent,
|
|
bg=self._colors.bg,
|
|
anchor="w",
|
|
)
|
|
self._mw_grid(parent, label, full=True)
|
|
|
|
def _mw_entry(self, parent: tk.Widget, label: str) -> tk.StringVar:
|
|
"""Add a half-width label+entry cell and return its backing StringVar.
|
|
|
|
Builds its own cell inline (rather than reusing ``_add_label_entry``,
|
|
which is pack-based and shared with the sick dialog) so it slots into
|
|
the two-column grid. Paste stays disabled via ``disable_paste``.
|
|
"""
|
|
var = tk.StringVar()
|
|
cell = tk.Frame(parent, bg=self._colors.bg)
|
|
tk.Label(
|
|
cell,
|
|
text=label,
|
|
font=(self._colors.font_family, 16),
|
|
fg=self._colors.fg,
|
|
bg=self._colors.bg,
|
|
anchor="w",
|
|
).pack(fill="x")
|
|
entry = tk.Entry(
|
|
cell,
|
|
textvariable=var,
|
|
font=(self._colors.font_family, 18),
|
|
bg=self._colors.field_bg,
|
|
fg=self._colors.fg,
|
|
insertbackground=self._colors.fg,
|
|
)
|
|
entry.pack(fill="x", pady=4)
|
|
disable_paste(entry)
|
|
self._mw_grid(parent, cell)
|
|
return var
|
|
|
|
def _mw_int_field(
|
|
self, parent: tk.Widget, label: str, *, frm: int = 0, to: int = 99
|
|
) -> tk.IntVar:
|
|
"""Add a half-width label + numeric Spinbox and return its IntVar."""
|
|
var = tk.IntVar(value=0)
|
|
row = tk.Frame(parent, bg=self._colors.bg)
|
|
tk.Label(
|
|
row,
|
|
text=label,
|
|
font=(self._colors.font_family, 16),
|
|
fg=self._colors.fg,
|
|
bg=self._colors.bg,
|
|
).pack(side="left", padx=5)
|
|
tk.Spinbox(
|
|
row,
|
|
from_=frm,
|
|
to=to,
|
|
textvariable=var,
|
|
width=4,
|
|
font=(self._colors.font_family, 16),
|
|
).pack(side="left", padx=5)
|
|
self._mw_grid(parent, row)
|
|
return var
|
|
|
|
def _mw_textbox(self, parent: tk.Widget, label: str) -> tk.Text:
|
|
"""Add a full-width label + multi-line Text cell and return the widget."""
|
|
cell = tk.Frame(parent, bg=self._colors.bg)
|
|
tk.Label(
|
|
cell,
|
|
text=label,
|
|
font=(self._colors.font_family, 16),
|
|
fg=self._colors.fg,
|
|
bg=self._colors.bg,
|
|
anchor="w",
|
|
).pack(fill="x", pady=(8, 0))
|
|
text_widget = tk.Text(
|
|
cell,
|
|
height=3,
|
|
font=(self._colors.font_family, 14),
|
|
bg=self._colors.field_bg,
|
|
fg=self._colors.fg,
|
|
insertbackground=self._colors.fg,
|
|
)
|
|
text_widget.pack(pady=4, fill="x")
|
|
disable_paste(text_widget)
|
|
self._mw_grid(parent, cell, full=True)
|
|
return text_widget
|
|
|
|
def _mw_rpe_row(self, parent: tk.Widget) -> None:
|
|
"""Add the RPE (rate of perceived exertion) spinbox row."""
|
|
row = tk.Frame(parent, bg=self._colors.bg)
|
|
tk.Label(
|
|
row,
|
|
text=(
|
|
f"RPE — perceived exertion "
|
|
f"({MANUAL_WORKOUT_RPE_MIN}-{MANUAL_WORKOUT_RPE_MAX}):"
|
|
),
|
|
font=(self._colors.font_family, 16),
|
|
fg=self._colors.fg,
|
|
bg=self._colors.bg,
|
|
).pack(side="left", padx=5)
|
|
tk.Spinbox(
|
|
row,
|
|
from_=MANUAL_WORKOUT_RPE_MIN,
|
|
to=MANUAL_WORKOUT_RPE_MAX,
|
|
textvariable=self._mw_rpe_var,
|
|
width=4,
|
|
font=(self._colors.font_family, 16),
|
|
).pack(side="left", padx=5)
|
|
self._mw_grid(parent, row)
|