ADR-009: Slicer Action Mapping
Status
Accepted
Context
MouseMaster needs to map button presses to Slicer actions. Actions can include:
Built-in Slicer commands (undo, redo, save)
Module-specific actions (Segment Editor effects)
View manipulation (zoom, pan, rotate)
Custom Python commands
Need to decide:
How to discover available actions
How to represent actions in presets
How to execute actions when buttons are pressed
Decision
Implement an ActionRegistry pattern with categorized actions.
ActionRegistry Singleton
class ActionRegistry:
_instance = None
@classmethod
def get_instance(cls) -> "ActionRegistry":
if cls._instance is None:
cls._instance = ActionRegistry()
cls._instance._register_builtin_actions()
return cls._instance
def register(
self,
action_id: str,
handler: ActionHandler,
category: str,
description: str
) -> None:
self._actions[action_id] = ActionEntry(
id=action_id,
handler=handler,
category=category,
description=description
)
def execute(self, action_id: str, context: ActionContext) -> bool:
if action_id not in self._actions:
return False
return self._actions[action_id].handler.execute(context)
Action Handler Protocol
class ActionHandler(Protocol):
def execute(self, context: ActionContext) -> bool:
"""Execute the action. Return True if successful."""
...
def is_available(self, context: ActionContext) -> bool:
"""Check if action is currently available."""
...
Built-in Action Categories
Navigation:
view_reset_3d: Reset 3D viewview_zoom_in,view_zoom_out: Zoom controlsview_center_crosshair: Center on crosshair
Editing:
edit_undo,edit_redo: Undo/redoedit_delete: Delete selected
Segment Editor:
segment_editor_paint,segment_editor_erase: Toggle effectssegment_next,segment_previous: Navigate segmentssegment_toggle_visibility: Show/hide current segment
Custom:
python_command: Execute arbitrary Pythonmenu_action: Trigger menu action by namekeyboard_shortcut: Simulate key press
Preset Action Reference
{
"mappings": {
"back": {
"action": "edit_undo"
},
"forward": {
"action": "python_command",
"command": "slicer.util.selectModule('SegmentEditor')"
},
"thumb": {
"action": "menu_action",
"menuPath": "Edit/Undo"
}
}
}
Consequences
Positive
Registry pattern allows extension by other modules
Categorized actions help UI organization
ActionHandler protocol enables custom implementations
is_available allows disabling unavailable actions
Presets reference actions by stable ID
Negative
Discovering all Slicer actions is complex
Some actions are module-specific and may not be available
Custom Python commands are a security consideration
Neutral
Actions can be registered dynamically
Need to handle action not found gracefully
References
Slicer Python API: https://slicer.readthedocs.io/en/latest/developer_guide/python_api.html
ADR-010: Context affects action availability
ADR-002: How actions are referenced in presets