diff --git a/src/aare/gui/graphics/resize_grip_h_hint_dark.png b/src/aare/gui/graphics/resize_grip_h_hint_dark.png deleted file mode 100644 index 6e9bdd79..00000000 Binary files a/src/aare/gui/graphics/resize_grip_h_hint_dark.png and /dev/null differ diff --git a/src/aare/gui/graphics/resize_grip_h_hint_light.png b/src/aare/gui/graphics/resize_grip_h_hint_light.png deleted file mode 100644 index fa6a8787..00000000 Binary files a/src/aare/gui/graphics/resize_grip_h_hint_light.png and /dev/null differ diff --git a/src/aare/gui/graphics/resize_grip_v_hint_dark.png b/src/aare/gui/graphics/resize_grip_v_hint_dark.png deleted file mode 100644 index 7ca63bff..00000000 Binary files a/src/aare/gui/graphics/resize_grip_v_hint_dark.png and /dev/null differ diff --git a/src/aare/gui/graphics/resize_grip_v_hint_light.png b/src/aare/gui/graphics/resize_grip_v_hint_light.png deleted file mode 100644 index 02c3badb..00000000 Binary files a/src/aare/gui/graphics/resize_grip_v_hint_light.png and /dev/null differ diff --git a/src/aare/gui/styles.py b/src/aare/gui/styles.py index 3110354c..1f05bd8c 100644 --- a/src/aare/gui/styles.py +++ b/src/aare/gui/styles.py @@ -82,20 +82,17 @@ DARK_SLIDER_GRIP = (_GRAPHICS_DIR / "slider_grip_dark.png").as_posix() # Check marks (PRIMARY blue / dusk gold at generation time): CHECK_MARK = (_GRAPHICS_DIR / "check_mark_light.png").as_posix() DARK_CHECK_MARK = (_GRAPHICS_DIR / "check_mark_dark.png").as_posix() -# Resize-bar grips: a short (66px) centered bar instead of a full-length -# line — the full line read as a wall between panels. QSS can't paint a -# fixed-length centered segment, so PNGs like the arrows above; used by BOTH -# QMainWindow::separator and QSplitter::handle, so this is the one place. -# Colors baked in (SEPARATOR_IDLE / SEPARATOR_HINT / DARK_SEPARATOR_IDLE / -# DARK_ACCENT) — regenerate if those knobs change. +# Resize-bar grips: IDLE paints a short (66px) centered bar instead of a +# full-length line — the full idle line read as a wall between panels; the +# hover/drag hint keeps the full-length gradient (see _separator_gradient). +# QSS can't paint a fixed-length centered segment, so PNGs like the arrows +# above; used by BOTH QMainWindow::separator and QSplitter::handle, so this +# is the one place. Colors baked in (SEPARATOR_IDLE / DARK_SEPARATOR_IDLE) +# — regenerate if those knobs change. GRIP_IDLE_V = (_GRAPHICS_DIR / "resize_grip_v_idle_light.png").as_posix() GRIP_IDLE_H = (_GRAPHICS_DIR / "resize_grip_h_idle_light.png").as_posix() -GRIP_HINT_V = (_GRAPHICS_DIR / "resize_grip_v_hint_light.png").as_posix() -GRIP_HINT_H = (_GRAPHICS_DIR / "resize_grip_h_hint_light.png").as_posix() DARK_GRIP_IDLE_V = (_GRAPHICS_DIR / "resize_grip_v_idle_dark.png").as_posix() DARK_GRIP_IDLE_H = (_GRAPHICS_DIR / "resize_grip_h_idle_dark.png").as_posix() -DARK_GRIP_HINT_V = (_GRAPHICS_DIR / "resize_grip_v_hint_dark.png").as_posix() -DARK_GRIP_HINT_H = (_GRAPHICS_DIR / "resize_grip_h_hint_dark.png").as_posix() # Borders (all can be "transparent" to hide the line): BORDER = "transparent" # main dividers, e.g. the beamline state bar top line @@ -138,10 +135,32 @@ SEPARATOR_HINT = "#3f4a5f" SEPARATOR_IDLE = "#47536a" SEPARATOR_HINT_DELAY_MS = 66 # int, used in code, not QSS -# The gutter keeps this full width for the mouse; only the short GRIP_* -# bar is painted inside it (a full-length line read as a wall). 5px is a -# first guess — adjust here if the grab target feels off. +# The gutter keeps this full width for the mouse; idle paints only the +# short GRIP_* bar (a full-length idle line read as a wall), hover/drag +# brings back the full-length hint gradient so the grabbed bar reads over +# its whole run. 5px is a first guess — adjust here if the grab target +# feels off. SEPARATOR_REGION = "5px" +SEPARATOR_SHADOW = "rgba(31, 41, 59, 25%)" + + +def _separator_gradient(line: str, shadow: str, axis: str) -> str: + """Full-length hover/drag hint of a resize gutter: transparent 1px, + shadow 1px, line 2px, shadow 1px — hard gradient stops at 1/5 steps of + SEPARATOR_REGION. axis "x" runs the gradient left->right (an upright + line), "y" top->down (a lying line).""" + x2, y2 = ("1", "0") if axis == "x" else ("0", "1") + return ( + f"qlineargradient(x1:0, y1:0, x2:{x2}, y2:{y2}," + f" stop:0 transparent, stop:0.19 transparent," + f" stop:0.2 {shadow}, stop:0.39 {shadow}," + f" stop:0.4 {line}, stop:0.79 {line}," + f" stop:0.8 {shadow}, stop:1 {shadow})" + ) + + +SEP_HINT_X = _separator_gradient(SEPARATOR_HINT, SEPARATOR_SHADOW, "x") +SEP_HINT_Y = _separator_gradient(SEPARATOR_HINT, SEPARATOR_SHADOW, "y") # Theme-switch screenshot cross-fade duration (int ms, used in code). THEME_FADE_MS = 250 @@ -249,6 +268,9 @@ DARK_ACCENT = "#e0913f" # gold # DARK_ACCENT @70%: 10% measured 1.16:1 on DARK_BG (invisible); 70% blends to # >=3.74:1 — same WCAG 1.4.11 floor as the light-theme separators. DARK_SEPARATOR_IDLE = "rgba(224, 145, 63, 70%)" +DARK_SEPARATOR_SHADOW = "rgba(0, 0, 0, 45%)" +DARK_SEP_HINT_X = _separator_gradient(DARK_ACCENT, DARK_SEPARATOR_SHADOW, "x") +DARK_SEP_HINT_Y = _separator_gradient(DARK_ACCENT, DARK_SEPARATOR_SHADOW, "y") DARK_ACCENT_HOVER = "#eaa253" # accent2 — brighter gold DARK_ACCENT_FILL = "#89b4fa" # action blue DARK_ACCENT_FILL_HOVER = "#9ec2fb" # +10% white, derived (site has no step) @@ -1180,20 +1202,24 @@ def _sunrise_stylesheet(overrides: dict[str, str] | None = None) -> str: MainWindow.event() after a 1s hover rest or on press; :hover limits the fill to the exact separator being dragged. */ QMainWindow[separatorHint="true"]::separator:vertical:hover { - image: url($grip_hint_v); + image: none; + background: $sep_hint_x; } QMainWindow[separatorHint="true"]::separator:horizontal:hover { - image: url($grip_hint_h); + image: none; + background: $sep_hint_y; } /* Splitter handles (camera region, prediction metrics) are plain child widgets the property gate above doesn't reach — immediate hover/press hint. */ QSplitter::handle:horizontal:hover, QSplitter::handle:horizontal:pressed { - image: url($grip_hint_v); + image: none; + background: $sep_hint_x; } QSplitter::handle:vertical:hover, QSplitter::handle:vertical:pressed { - image: url($grip_hint_h); + image: none; + background: $sep_hint_y; } QFrame#beamlineControls, @@ -1853,17 +1879,21 @@ def _sunset_stylesheet() -> str: QSplitter::handle:vertical { height: $separator_region; } QMainWindow[separatorHint="true"]::separator:vertical:hover { - image: url($dark_grip_hint_v); + image: none; + background: $dark_sep_hint_x; } QMainWindow[separatorHint="true"]::separator:horizontal:hover { - image: url($dark_grip_hint_h); + image: none; + background: $dark_sep_hint_y; } QSplitter::handle:horizontal:hover, QSplitter::handle:horizontal:pressed { - image: url($dark_grip_hint_v); + image: none; + background: $dark_sep_hint_x; } QSplitter::handle:vertical:hover, QSplitter::handle:vertical:pressed { - image: url($dark_grip_hint_h); + image: none; + background: $dark_sep_hint_y; } /* Plain scroll containers stay frameless. */