diff --git a/bec_widgets/widgets/figure/plots/motor_map/assets/connection.svg b/bec_widgets/widgets/figure/plots/motor_map/assets/connection.svg
new file mode 100644
index 00000000..3b31c422
--- /dev/null
+++ b/bec_widgets/widgets/figure/plots/motor_map/assets/connection.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/bec_widgets/widgets/figure/plots/motor_map/assets/settings.svg b/bec_widgets/widgets/figure/plots/motor_map/assets/settings.svg
new file mode 100644
index 00000000..9ce6f411
--- /dev/null
+++ b/bec_widgets/widgets/figure/plots/motor_map/assets/settings.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/bec_widgets/widgets/figure/plots/motor_map/motor_map_widget.py b/bec_widgets/widgets/figure/plots/motor_map/motor_map_widget.py
new file mode 100644
index 00000000..5e785a78
--- /dev/null
+++ b/bec_widgets/widgets/figure/plots/motor_map/motor_map_widget.py
@@ -0,0 +1,117 @@
+import os
+
+from qtpy.QtCore import QSize, Slot
+from qtpy.QtGui import QAction, QIcon
+from qtpy.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QWidget
+
+from bec_widgets.utils import BECConnector
+from bec_widgets.widgets.device_inputs import DeviceComboBox
+from bec_widgets.widgets.figure import BECFigure
+from bec_widgets.widgets.figure.plots.motor_map.motor_map import MotorMapConfig
+from bec_widgets.widgets.toolbar import ModularToolBar
+from bec_widgets.widgets.toolbar.toolbar import ToolBarAction
+
+
+class SettingsAction(ToolBarAction):
+ def add_to_toolbar(self, toolbar, target):
+ current_path = os.path.dirname(__file__)
+ icon = QIcon()
+ icon.addFile(os.path.join(current_path, "assets", "settings.svg"), size=QSize(20, 20))
+ action = QAction(icon, "Config", target)
+ action.triggered.connect(lambda: print(target.config_dict))
+ toolbar.addAction(action)
+
+
+class DeviceSelectionAction(ToolBarAction):
+ def __init__(self, label: str):
+ self.label = label
+ self.device_combobox = DeviceComboBox(device_filter="Positioner")
+
+ def add_to_toolbar(self, toolbar, target):
+ widget = QWidget()
+ layout = QHBoxLayout(widget)
+
+ label = QLabel(f"{self.label}")
+
+ layout.addWidget(label)
+ layout.addWidget(self.device_combobox)
+ toolbar.addWidget(widget)
+
+
+class ConnectAction(ToolBarAction):
+ def add_to_toolbar(self, toolbar, target):
+ current_path = os.path.dirname(__file__)
+ icon = QIcon()
+ icon.addFile(os.path.join(current_path, "assets", "connection.svg"), size=QSize(20, 20))
+ self.action = QAction(icon, "Connect Motors", target)
+ toolbar.addAction(self.action)
+
+
+class BECMotorMapWidget(BECConnector, QWidget):
+ USER_ACCESS = []
+
+ def __init__(
+ self,
+ parent: QWidget | None = None,
+ config: MotorMapConfig | None = None,
+ client=None,
+ gui_id: str | None = None,
+ ) -> None:
+ if config is None:
+ config = MotorMapConfig(widget_class=self.__class__.__name__)
+ else:
+ if isinstance(config, dict):
+ config = MotorMapConfig(**config)
+ super().__init__(client=client, gui_id=gui_id)
+ QWidget.__init__(self, parent)
+
+ self.layout = QVBoxLayout(self)
+ self.layout.setSpacing(0)
+ self.layout.setContentsMargins(0, 0, 0, 0)
+
+ self.fig = BECFigure()
+ self.toolbar = ModularToolBar(
+ actions={
+ "motor_x": DeviceSelectionAction("Motor X:"),
+ "motor_y": DeviceSelectionAction("Motor Y:"),
+ "connect": ConnectAction(),
+ "config": SettingsAction(),
+ },
+ target_widget=self,
+ )
+
+ self.layout.addWidget(self.toolbar)
+ self.layout.addWidget(self.fig)
+
+ self.map = self.fig.motor_map()
+ self.map.apply_config(config)
+
+ self.config = config
+
+ self._hook_actions()
+
+ def _hook_actions(self):
+ self.toolbar.widgets["connect"].action.triggered.connect(self.pass_motors)
+
+ def pass_motors(self):
+ motor_x = self.toolbar.widgets["motor_x"].device_combobox.currentText()
+ motor_y = self.toolbar.widgets["motor_y"].device_combobox.currentText()
+ self.change_motors(motor_x, motor_y)
+
+ @Slot(str, str)
+ def change_motors(self, motor_x, motor_y):
+ self.map.change_motors(motor_x, motor_y)
+
+ def set(self, **kwargs):
+ self.map.set(**kwargs)
+
+
+if __name__ == "__main__":
+ import sys
+
+ from PySide6.QtWidgets import QApplication
+
+ app = QApplication(sys.argv)
+ widget = BECMotorMapWidget()
+ widget.show()
+ sys.exit(app.exec_())
diff --git a/bec_widgets/widgets/toolbar/toolbar.py b/bec_widgets/widgets/toolbar/toolbar.py
index 1c3adc2c..badc01a9 100644
--- a/bec_widgets/widgets/toolbar/toolbar.py
+++ b/bec_widgets/widgets/toolbar/toolbar.py
@@ -1,4 +1,7 @@
from abc import ABC, abstractmethod
+from collections import defaultdict
+
+from PySide6.QtWidgets import QHBoxLayout, QLabel, QSpinBox
# pylint: disable=no-name-in-module
from qtpy.QtCore import QSize, QTimer
@@ -7,117 +10,63 @@ from qtpy.QtWidgets import QApplication, QStyle, QToolBar, QWidget
class ToolBarAction(ABC):
- """Abstract base class for action creators for the toolbar."""
-
@abstractmethod
- def create(self, target: QWidget):
- """Creates and returns an action to be added to a toolbar.
-
- This method must be implemented by subclasses.
+ def add_to_toolbar(self, toolbar: QToolBar, target: QWidget):
+ """Adds an action or widget to a toolbar.
Args:
- target (QWidget): The widget that the action will target.
-
- Returns:
- QAction: The action created for the toolbar.
+ toolbar (QToolBar): The toolbar to add the action or widget to.
+ target (QWidget): The target widget for the action.
"""
-class OpenFileAction: # (ToolBarAction):
- """Action creator for the 'Open File' action in the toolbar."""
+class ColumnAdjustAction(ToolBarAction):
+ """Toolbar spinbox to adjust number of columns in the plot layout"""
- def create(self, target: QWidget):
- """Creates an 'Open File' action for the toolbar.
+ def add_to_toolbar(self, toolbar: QToolBar, target: QWidget):
+ """Creates a access history button for the toolbar.
Args:
- target (QWidget): The widget that the 'Open File' action will be targeted.
+ toolbar (QToolBar): The toolbar to add the action to.
+ target (QWidget): The widget that the 'Access Scan History' action will be targeted.
Returns:
- QAction: The 'Open File' action created for the toolbar.
+ QAction: The 'Access Scan History' action created for the toolbar.
"""
- icon = QApplication.style().standardIcon(QStyle.StandardPixmap.SP_DialogOpenButton)
- action = QAction(icon, "Open File", target)
- # action = QAction("Open File", target)
- action.triggered.connect(target.open_file)
- return action
+ widget = QWidget()
+ layout = QHBoxLayout(widget)
+ label = QLabel("Columns:")
+ spin_box = QSpinBox()
+ spin_box.setMinimum(1) # Set minimum value
+ spin_box.setMaximum(10) # Set maximum value
+ spin_box.setValue(target.get_column_count()) # Initial value
+ spin_box.valueChanged.connect(lambda value: target.set_column_count(value))
-class SaveFileAction:
- """Action creator for the 'Save File' action in the toolbar."""
-
- def create(self, target):
- """Creates a 'Save File' action for the toolbar.
-
- Args:
- target (QWidget): The widget that the 'Save File' action will be targeted.
-
- Returns:
- QAction: The 'Save File' action created for the toolbar.
- """
- icon = QApplication.style().standardIcon(QStyle.StandardPixmap.SP_DialogSaveButton)
- action = QAction(icon, "Save File", target)
- # action = QAction("Save File", target)
- action.triggered.connect(target.save_file)
- return action
-
-
-class RunScriptAction:
- """Action creator for the 'Run Script' action in the toolbar."""
-
- def create(self, target):
- """Creates a 'Run Script' action for the toolbar.
-
- Args:
- target (QWidget): The widget that the 'Run Script' action will be targeted.
-
- Returns:
- QAction: The 'Run Script' action created for the toolbar.
- """
- icon = QApplication.style().standardIcon(QStyle.StandardPixmap.SP_MediaPlay)
- action = QAction(icon, "Run Script", target)
- # action = QAction("Run Script", target)
- action.triggered.connect(target.run_script)
- return action
+ layout.addWidget(label)
+ layout.addWidget(spin_box)
+ toolbar.addWidget(widget)
class ModularToolBar(QToolBar):
"""Modular toolbar with optional automatic initialization.
-
Args:
parent (QWidget, optional): The parent widget of the toolbar. Defaults to None.
auto_init (bool, optional): If True, automatically populates the toolbar based on the parent widget.
"""
- def __init__(self, parent=None, auto_init=True):
+ def __init__(self, parent=None, actions=None, target_widget=None):
super().__init__(parent)
- self.auto_init = auto_init
- self.handler = {
- "BECEditor": [OpenFileAction(), SaveFileAction(), RunScriptAction()],
- # BECMonitor: [SomeOtherAction(), AnotherAction()], # Example for another widget
- }
+
self.setStyleSheet("QToolBar { background: transparent; }")
- # Set the icon size for the toolbar
self.setIconSize(QSize(20, 20))
+ self.widgets = defaultdict(dict)
- if self.auto_init:
- QTimer.singleShot(0, self.auto_detect_and_populate)
+ if actions is not None and target_widget is not None:
+ self.populate_toolbar(actions, target_widget)
+ # QTimer.singleShot(0, lambda :self.set_manual_actions(actions, target_widget))
- def auto_detect_and_populate(self):
- """Automatically detects the parent widget and populates the toolbar with relevant actions."""
- if not self.auto_init:
- return
-
- parent_widget = self.parent()
- if parent_widget is None:
- return
-
- parent_widget_class_name = type(parent_widget).__name__
- for widget_type_name, actions in self.handler.items():
- if parent_widget_class_name == widget_type_name:
- self.populate_toolbar(actions, parent_widget)
- return
-
- def populate_toolbar(self, actions, target_widget):
+ def populate_toolbar(self, actions: dict, target_widget):
"""Populates the toolbar with a set of actions.
Args:
@@ -125,20 +74,23 @@ class ModularToolBar(QToolBar):
target_widget (QWidget): The widget that the actions will target.
"""
self.clear()
- for action_creator in actions:
- action = action_creator.create(target_widget)
- self.addAction(action)
+ for action_id, action in actions.items():
+ action.add_to_toolbar(self, target_widget)
+ self.widgets[action_id] = action
- def set_manual_actions(self, actions, target_widget):
- """Manually sets the actions for the toolbar.
+ # for action in actions:
+ # action.add_to_toolbar(self, target_widget)
- Args:
- actions (list[QAction or ToolBarAction]): A list of actions or action creators to populate the toolbar.
- target_widget (QWidget): The widget that the actions will target.
- """
- self.clear()
- for action in actions:
- if isinstance(action, QAction):
- self.addAction(action)
- elif isinstance(action, ToolBarAction):
- self.addAction(action.create(target_widget))
+ # def set_manual_actions(self, actions, target_widget):
+ # """Manually sets the actions for the toolbar.
+ #
+ # Args:
+ # actions (list[QAction or ToolBarAction]): A list of actions or action creators to populate the toolbar.
+ # target_widget (QWidget): The widget that the actions will target.
+ # """
+ # self.clear()
+ # for action in actions:
+ # if isinstance(action, QAction):
+ # self.addAction(action)
+ # elif isinstance(action, ToolBarAction):
+ # self.addAction(action.add_to_toolbar(self, target_widget))