mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-06-05 04:48:40 +02:00
wip card on hover
This commit is contained in:
@@ -71,6 +71,7 @@ class BeamlineStatePill(BECWidget, QWidget):
|
||||
}
|
||||
_SETTINGS_FIELD_WIDTH = 280
|
||||
_VALID_DRAG_PAYLOAD_MODES = {"config", "device"}
|
||||
_VALID_CARD_BACKGROUND_MODES = {"hover", "always"}
|
||||
MIME_PAYLOAD = "application/x-bec-beamline-state-payload"
|
||||
MIME_CONFIG = "application/x-bec-beamline-state-config"
|
||||
MIME_NAME = "application/x-bec-beamline-state-name"
|
||||
@@ -100,6 +101,7 @@ class BeamlineStatePill(BECWidget, QWidget):
|
||||
self._flash_active = False
|
||||
self._expanded = False
|
||||
self._hovered = False
|
||||
self._card_background_mode = "hover"
|
||||
self._drag_payload_mode = "config"
|
||||
self._drag_start_position: QPoint | None = None
|
||||
self._drag_started = False
|
||||
@@ -361,6 +363,31 @@ class BeamlineStatePill(BECWidget, QWidget):
|
||||
"""Set the payload mode used for drag-and-drop."""
|
||||
self.drag_payload_mode = mode
|
||||
|
||||
@property
|
||||
def card_background_mode(self) -> str:
|
||||
"""
|
||||
Background mode for the pill card.
|
||||
|
||||
Supported values:
|
||||
``"hover"``: idle pills are transparent; hover/expanded pills use a card background.
|
||||
``"always"``: idle pills keep the status-tinted background.
|
||||
"""
|
||||
return self._card_background_mode
|
||||
|
||||
@card_background_mode.setter
|
||||
def card_background_mode(self, mode: str) -> None:
|
||||
if mode not in self._VALID_CARD_BACKGROUND_MODES:
|
||||
valid_modes = ", ".join(sorted(self._VALID_CARD_BACKGROUND_MODES))
|
||||
raise ValueError(
|
||||
f"Invalid card background mode '{mode}'. Expected one of: {valid_modes}."
|
||||
)
|
||||
self._card_background_mode = mode
|
||||
self._apply_visual_state()
|
||||
|
||||
def set_card_background_mode(self, mode: str) -> None:
|
||||
"""Set when the pill card background should be shown."""
|
||||
self.card_background_mode = mode
|
||||
|
||||
def _refresh_latest_state(self) -> None:
|
||||
if self._state_name is None:
|
||||
return
|
||||
@@ -411,8 +438,17 @@ class BeamlineStatePill(BECWidget, QWidget):
|
||||
accent = colors["accent"]
|
||||
on_accent = colors["on_accent"]
|
||||
active_card = self._hovered or self._expanded
|
||||
border = colors["flash_border"] if self._flash_active else colors["border"]
|
||||
background = colors["flash_background"] if self._flash_active else colors["background"]
|
||||
show_idle_background = self._card_background_mode == "always" or self._flash_active
|
||||
border = (
|
||||
colors["flash_border"]
|
||||
if self._flash_active
|
||||
else colors["border"] if show_idle_background else "transparent"
|
||||
)
|
||||
background = (
|
||||
colors["flash_background"]
|
||||
if self._flash_active
|
||||
else colors["background"] if show_idle_background else "transparent"
|
||||
)
|
||||
if active_card:
|
||||
background = (
|
||||
"qlineargradient("
|
||||
@@ -1109,6 +1145,8 @@ class BeamlineStateManager(BECWidget, QWidget):
|
||||
USER_ACCESS = [
|
||||
"drag_payload_mode",
|
||||
"set_drag_payload_mode",
|
||||
"card_background_mode",
|
||||
"set_card_background_mode",
|
||||
"refresh_states",
|
||||
"clear_filters",
|
||||
"remove",
|
||||
@@ -1124,6 +1162,7 @@ class BeamlineStateManager(BECWidget, QWidget):
|
||||
config: ConnectionConfig | None = None,
|
||||
gui_id: str | None = None,
|
||||
drag_payload_mode: str = "config",
|
||||
card_background_mode: str = "hover",
|
||||
**kwargs,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
@@ -1137,7 +1176,9 @@ class BeamlineStateManager(BECWidget, QWidget):
|
||||
self._device_filter_text = ""
|
||||
self._hidden_expanded = False
|
||||
self._drag_payload_mode = "config"
|
||||
self._card_background_mode = "hover"
|
||||
self.drag_payload_mode = drag_payload_mode
|
||||
self.card_background_mode = card_background_mode
|
||||
|
||||
self._empty_label = QLabel(
|
||||
"No beamline states available.\n Add new state from toolbar or CLI.", self
|
||||
@@ -1209,6 +1250,32 @@ class BeamlineStateManager(BECWidget, QWidget):
|
||||
"""Set the payload mode used for drag-and-drop."""
|
||||
self.drag_payload_mode = mode
|
||||
|
||||
@property
|
||||
def card_background_mode(self) -> str:
|
||||
"""
|
||||
Background mode used by pills in this manager.
|
||||
|
||||
Supported values:
|
||||
``"hover"``: idle pills are transparent; hover/expanded pills use a card background.
|
||||
``"always"``: idle pills keep the status-tinted background.
|
||||
"""
|
||||
return self._card_background_mode
|
||||
|
||||
@card_background_mode.setter
|
||||
def card_background_mode(self, mode: str) -> None:
|
||||
if mode not in BeamlineStatePill._VALID_CARD_BACKGROUND_MODES:
|
||||
valid_modes = ", ".join(sorted(BeamlineStatePill._VALID_CARD_BACKGROUND_MODES))
|
||||
raise ValueError(
|
||||
f"Invalid card background mode '{mode}'. Expected one of: {valid_modes}."
|
||||
)
|
||||
self._card_background_mode = mode
|
||||
for pill in self._state_pills.values():
|
||||
pill.card_background_mode = mode
|
||||
|
||||
def set_card_background_mode(self, mode: str) -> None:
|
||||
"""Set when pill card backgrounds should be shown."""
|
||||
self.card_background_mode = mode
|
||||
|
||||
def _create_toolbar(self) -> ModularToolBar:
|
||||
toolbar = ModularToolBar(parent=self)
|
||||
|
||||
@@ -1358,6 +1425,7 @@ class BeamlineStateManager(BECWidget, QWidget):
|
||||
parent=self._content, state_name=name, title=title, client=self.client
|
||||
)
|
||||
pill.drag_payload_mode = self._drag_payload_mode
|
||||
pill.card_background_mode = self._card_background_mode
|
||||
pill.set_state_config(state_config)
|
||||
pill.state_changed.connect(self._on_pill_state_changed)
|
||||
pill.update_requested.connect(self._update_state_parameters)
|
||||
@@ -1587,6 +1655,12 @@ if __name__ == "__main__": # pragma: no cover
|
||||
mode_combo.currentIndexChanged.connect(
|
||||
lambda: setattr(manager, "drag_payload_mode", mode_combo.currentData())
|
||||
)
|
||||
background_combo = QComboBox(window)
|
||||
background_combo.addItem("Card on hover", "hover")
|
||||
background_combo.addItem("Card always", "always")
|
||||
background_combo.currentIndexChanged.connect(
|
||||
lambda: setattr(manager, "card_background_mode", background_combo.currentData())
|
||||
)
|
||||
|
||||
drop_list = BeamlineStateDropList(window)
|
||||
drop_list.setMinimumWidth(260)
|
||||
@@ -1594,6 +1668,8 @@ if __name__ == "__main__": # pragma: no cover
|
||||
payload_row = QHBoxLayout()
|
||||
payload_row.addWidget(QLabel("Drag payload", window))
|
||||
payload_row.addWidget(mode_combo)
|
||||
payload_row.addWidget(QLabel("Card background", window))
|
||||
payload_row.addWidget(background_combo)
|
||||
payload_row.addStretch(1)
|
||||
layout.addLayout(payload_row)
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ def test_beamline_state_pill_uses_card_style_when_expanded(qtbot, mocked_client)
|
||||
qtbot.addWidget(widget)
|
||||
|
||||
assert "qlineargradient" not in widget.styleSheet()
|
||||
assert "#BeamlineStatePill {background: transparent" in widget.styleSheet()
|
||||
|
||||
widget._toggle_expanded()
|
||||
|
||||
@@ -104,6 +105,18 @@ def test_beamline_state_pill_uses_card_style_when_expanded(qtbot, mocked_client)
|
||||
assert widget._shadow.isEnabled()
|
||||
|
||||
|
||||
def test_beamline_state_pill_can_keep_idle_background(qtbot, mocked_client):
|
||||
widget = BeamlineStatePill(state_name="limits", title="Limits", client=mocked_client)
|
||||
qtbot.addWidget(widget)
|
||||
|
||||
assert "#BeamlineStatePill {background: transparent" in widget.styleSheet()
|
||||
|
||||
widget.card_background_mode = "always"
|
||||
|
||||
assert "#BeamlineStatePill {background: transparent" not in widget.styleSheet()
|
||||
assert "qlineargradient" not in widget.styleSheet()
|
||||
|
||||
|
||||
def test_beamline_state_pill_uses_card_style_when_hovered(qtbot, mocked_client):
|
||||
widget = BeamlineStatePill(state_name="limits", title="Limits", client=mocked_client)
|
||||
qtbot.addWidget(widget)
|
||||
@@ -208,6 +221,31 @@ def test_beamline_state_manager_propagates_drag_payload_mode(qtbot, mocked_clien
|
||||
assert widget._state_pills["limits"].drag_payload_mode == "config"
|
||||
|
||||
|
||||
def test_beamline_state_manager_propagates_card_background_mode(qtbot, mocked_client):
|
||||
widget = BeamlineStateManager(client=mocked_client, card_background_mode="always")
|
||||
qtbot.addWidget(widget)
|
||||
|
||||
widget.update_available_states(
|
||||
{
|
||||
"states": [
|
||||
{
|
||||
"name": "limits",
|
||||
"title": "Limits",
|
||||
"state_type": "DeviceWithinLimitsState",
|
||||
"parameters": {"device": "samx"},
|
||||
}
|
||||
]
|
||||
},
|
||||
{},
|
||||
)
|
||||
|
||||
assert widget._state_pills["limits"].card_background_mode == "always"
|
||||
|
||||
widget.card_background_mode = "hover"
|
||||
|
||||
assert widget._state_pills["limits"].card_background_mode == "hover"
|
||||
|
||||
|
||||
def test_beamline_state_manager_filters_status(qtbot, mocked_client):
|
||||
widget = BeamlineStateManager(client=mocked_client)
|
||||
qtbot.addWidget(widget)
|
||||
|
||||
Reference in New Issue
Block a user