From 750559fadedbdbefa09b7e8d58fbbf1475c706df Mon Sep 17 00:00:00 2001 From: Dawn Date: Wed, 16 Sep 2026 10:46:09 +0200 Subject: [PATCH] fix: full-length hint line on resize-bar hover/drag, short grip idle User feedback: idle bars stay short centered grips, but hovering or grabbing a resize bar brings back the full-length 2px line + shadow gradient so the active bar reads over its whole run. The now-unused hint grip PNGs are removed. Co-Authored-By: Claude Fable 5 --- .../gui/graphics/resize_grip_h_hint_dark.png | Bin 139 -> 0 bytes .../gui/graphics/resize_grip_h_hint_light.png | Bin 141 -> 0 bytes .../gui/graphics/resize_grip_v_hint_dark.png | Bin 145 -> 0 bytes .../gui/graphics/resize_grip_v_hint_light.png | Bin 155 -> 0 bytes src/aare/gui/styles.py | 72 +++++++++++++----- 5 files changed, 51 insertions(+), 21 deletions(-) delete mode 100644 src/aare/gui/graphics/resize_grip_h_hint_dark.png delete mode 100644 src/aare/gui/graphics/resize_grip_h_hint_light.png delete mode 100644 src/aare/gui/graphics/resize_grip_v_hint_dark.png delete mode 100644 src/aare/gui/graphics/resize_grip_v_hint_light.png 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 6e9bdd7921a5fde40f83a35b24155adf8f39a71c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^PC(4e!3HGN18yn;Db50q$YKTtz9S&aI8~cZ8YpP% z>EaloG4bgIM_vX69+rc9_g!pRDRqE>Q%LaQf5pZ8ZU@s!&-*N4<@pzKLwmxcdUXb# jB|L9#j+S3j3^P6EaloG4bgILs13=o+B4x(oHrlW)d`QV7ycIY{J0<;SEx6FDb50q$YKTtz9S&aI8~cZ8Yt-O z>EaloG4bv3jl2gGcvvrP&Q4Qu-pIi1!X|-2DINd- 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 02c3badbc3f63e17d4827d840c2a200dc355e2c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^%s}kK!3HEJ>Ex6FDb50q$YKTtz9S&aI8~cZ8Yt-N z>EaloG4btjMbQQWiPnqn|K70VdaxmbWu8b&M5AbgB3EES75`DomK&wv$177ibAp$r z-pxx0+rX~Im=N^A*vROUs|kY(cRAOG9l>#4uLK;9RJ?l&G?>BD)z4*}Q$iB}KVvXh 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. */