From dbd5b9078f6223ff81bc5af1448fa952a09ea141 Mon Sep 17 00:00:00 2001 From: Dawn Date: Tue, 8 Sep 2026 14:31:32 +0200 Subject: [PATCH] style: paint the unknown-session badge with the viewing-mode style The sample camera drew its own gold/orange/red "Session Vacant / Baton Requested / Guest Mode" box whenever the busy overlay had nothing to show. Since the busy-style builder already receives the session state, that box only ever appeared while the session was still unknown (no status yet, or one without a session), so it flashed a different color and shape than the yellow "Viewing mode, click here to grab the baton" badge every known not-owned state gets. Hoist that badge into VIEWING_MODE_STYLE and paint it from both paths; the hover fill is shared through _badge_fill. The three MARK_TOOLTIP constants had no other users and are dropped. Co-Authored-By: Claude Fable 5.1 --- src/aare/gui/styles.py | 3 - src/aare/gui/widgets/busy_overlay.py | 26 ++++---- src/aare/gui/widgets/camera_image.py | 90 +++++++++------------------- tests/unit/gui/test_camera_image.py | 8 +++ 4 files changed, 52 insertions(+), 75 deletions(-) diff --git a/src/aare/gui/styles.py b/src/aare/gui/styles.py index 03abcac8..ec619d1d 100644 --- a/src/aare/gui/styles.py +++ b/src/aare/gui/styles.py @@ -471,9 +471,6 @@ LEGEND_BG = "#eff1f5" # base LEGEND_TEXT = "#4c4f69" # text TOOLTIP_TEXT = "#4c4f69" # camera coords tooltip pen — NOT the QToolTip popup SCALE_BAR_GREY = "#8c8fa1" # hover HUD scale bar (Latte overlay1 grey) -MARK_TOOLTIP_GOLD = "#df8e1d" # yellow -MARK_TOOLTIP_ORANGE = "#fe640b" # peach -MARK_TOOLTIP_RED = "#d20f39" # red MARK_BADGE_BG = "#fe640b" # peach # Prediction class overlay colors. The old pure-green vs CSS-green split diff --git a/src/aare/gui/widgets/busy_overlay.py b/src/aare/gui/widgets/busy_overlay.py index b66d21f8..19b6fd6d 100644 --- a/src/aare/gui/widgets/busy_overlay.py +++ b/src/aare/gui/widgets/busy_overlay.py @@ -161,6 +161,21 @@ def draw_busy_status_text( painter.drawText(QPoint(x, baseline), style.text) +# The one "not yours" badge. Module-level so the sample camera can paint the +# same box while the session state is still unknown (no status yet), instead +# of a differently colored hand-rolled one. +VIEWING_MODE_STYLE = BusyOverlayStyle( + text="Viewing mode, Click here to grab the baton", + badge_bg=BUSY_YELLOW, + badge_fg=WHITE, + overlay_fill=qcolor(BUSY_YELLOW, 195), + overlay_border=qcolor(BUSY_YELLOW_BORDER, 235), + overlay_text=qcolor(WHITE), + accent_dot=BUSY_YELLOW_DOT, + subtext="Grab the baton if you need to interact with GUI", +) + + def build_busy_overlay_style( *, is_busy: bool, @@ -173,16 +188,7 @@ def build_busy_overlay_style( SessionsStateEnum.PendingYouToElse, SessionsStateEnum.Vacant, }: - return BusyOverlayStyle( - text="Viewing mode, Click here to grab the baton", - badge_bg=BUSY_YELLOW, - badge_fg=WHITE, - overlay_fill=qcolor(BUSY_YELLOW, 195), - overlay_border=qcolor(BUSY_YELLOW_BORDER, 235), - overlay_text=qcolor(WHITE), - accent_dot=BUSY_YELLOW_DOT, - subtext="Grab the baton if you need to interact with GUI", - ) + return VIEWING_MODE_STYLE # Auto loop centering is busy + SampleAlignment in /status — the exact # combo the callers hide (manual omega moves look identical), so it diff --git a/src/aare/gui/widgets/camera_image.py b/src/aare/gui/widgets/camera_image.py index d4093c74..03454282 100644 --- a/src/aare/gui/widgets/camera_image.py +++ b/src/aare/gui/widgets/camera_image.py @@ -50,9 +50,6 @@ from aare.gui.styles import ( LEGEND_BG, LEGEND_TEXT, MARK_BADGE_BG, - MARK_TOOLTIP_GOLD, - MARK_TOOLTIP_ORANGE, - MARK_TOOLTIP_RED, MARKER_GREEN, PATH_END, PATH_START, @@ -65,6 +62,7 @@ from aare.gui.styles import ( qcolor, ) from aare.gui.widgets.busy_overlay import ( + VIEWING_MODE_STYLE, BusyOverlayStyle, build_busy_overlay_style, draw_busy_badge, @@ -374,27 +372,31 @@ class SampleCameraImageLabel(QGraphicsView): painter.restore() return - # SESSION VACANT / GUEST MODE badges double as the click target for the - # grab/request menu, same as the _draw_session_overlay badge they hide. - session_badge = self._session_state in ( - SessionsStateEnum.Vacant, - SessionsStateEnum.OwnedByElse, - SessionsStateEnum.PendingYouToElse, + # The session badge doubles as the click target for the grab/request + # menu, same as the _draw_session_overlay badge it hides. + self._session_badge_rect = draw_busy_badge( + painter, + self.viewport().width(), + self.viewport().height(), + style, + fill=self._badge_fill(style), ) - fill = QColor(style.overlay_fill) - if session_badge and self._session_badge_hovered: - # Hover: darker in the light themes, brighter in Sunset. - fill = fill.lighter(125) if self._dark_theme else fill.darker(115) - - bg_rect = draw_busy_badge( - painter, self.viewport().width(), self.viewport().height(), style, fill=fill - ) - self._session_badge_rect = bg_rect if session_badge else None - painter.restore() + def _badge_fill(self, style: BusyOverlayStyle) -> QColor: + fill = QColor(style.overlay_fill) + if self._session_badge_hovered: + # Hover: darker in the light themes, brighter in Sunset. + fill = fill.lighter(125) if self._dark_theme else fill.darker(115) + return fill + def _draw_session_overlay(self, painter: QPainter): + """Session badge for when the busy overlay has nothing to draw, i.e. + the session state is still unknown (no status yet, or one without a + session). Same yellow "viewing mode" badge as the known not-owned + states, so the click target looks identical whichever path paints it + (it used to be a gold/orange/red "Guest Mode" box of its own).""" if self._busy_overlay_style is not None: # Busy overlay drew (and owns) the session badge rect — don't clobber. return @@ -408,49 +410,13 @@ class SampleCameraImageLabel(QGraphicsView): painter.save() painter.resetTransform() - - font = QFont() - font.setPointSize(24) - font.setBold(True) - painter.setFont(font) - - if self._session_state == SessionsStateEnum.Vacant: - bg_color = qcolor(MARK_TOOLTIP_GOLD, 180) - text = "Session Vacant" - elif self._session_state == SessionsStateEnum.PendingYouToElse: - bg_color = qcolor(MARK_TOOLTIP_ORANGE, 150) - text = "Baton Requested..." - else: - bg_color = qcolor(MARK_TOOLTIP_RED, 150) - text = "Guest Mode" - - fm = QFontMetrics(font) - text_rect = fm.boundingRect(text) - padding = 16 - - vw = self.viewport().width() - vh = self.viewport().height() - - bg_w = text_rect.width() + 2 * padding - bg_h = text_rect.height() + 2 * padding - position_x = int((vw - bg_w) / 2) - position_y = int((vh - bg_h) / 2) - - bg_rect = QRect(position_x, position_y, bg_w, bg_h) - # Clicking the badge opens the session (grab/request) menu. - self._session_badge_rect = bg_rect - - if self._session_badge_hovered: - # Same hover polarity as the busy-overlay badge. - bg_color = bg_color.lighter(125) if self._dark_theme else bg_color.darker(115) - - painter.setPen(QPen(qcolor(WHITE, 220))) - painter.setBrush(bg_color) - painter.drawRoundedRect(bg_rect, 10, 10) - - painter.setPen(QPen(qcolor(WHITE))) - painter.drawText(QPoint(position_x + padding, position_y + padding + fm.ascent()), text) - + self._session_badge_rect = draw_busy_badge( + painter, + self.viewport().width(), + self.viewport().height(), + VIEWING_MODE_STYLE, + fill=self._badge_fill(VIEWING_MODE_STYLE), + ) painter.restore() def _draw_camera_unavailable_overlay(self, painter: QPainter): diff --git a/tests/unit/gui/test_camera_image.py b/tests/unit/gui/test_camera_image.py index ac9c866e..be91b41a 100644 --- a/tests/unit/gui/test_camera_image.py +++ b/tests/unit/gui/test_camera_image.py @@ -289,3 +289,11 @@ def test_autoscale_fits_from_the_first_frame(camera): camera._autoscale = False camera._scaling() assert camera.transform().isIdentity() + + +def test_unknown_session_paints_the_viewing_mode_badge(camera): + # No status yet: the busy overlay has nothing, the session overlay must + # still hand out the same click target as the known not-owned states. + assert camera._busy_overlay_style is None + camera.grab() + assert camera._session_badge_rect is not None