diff --git a/fsl/data/strings.py b/fsl/data/strings.py index 060e26d291a88cf1053963f11f3820938822bf26..000c03cdb085dd906c972fd2387dd56937a79019 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -135,7 +135,7 @@ titles = TypeDict({ 'CanvasSettingsPanel' : 'View settings', 'OverlayDisplayPanel' : 'Display settings', 'OrthoToolBar' : 'Ortho view toolbar', - 'OrthoProfileToolBar' : 'Ortho view edit toolbar', + 'OrthoEditToolBar' : 'Ortho view edit toolbar', 'LightBoxToolBar' : 'Lightbox view toolbar', 'LookupTablePanel' : 'Lookup tables', 'LutLabelDialog' : 'New LUT label', @@ -176,7 +176,7 @@ actions = TypeDict({ 'CanvasPanel.toggleShell' : 'Python shell', 'OrthoPanel.toggleOrthoToolBar' : 'View properties', - 'OrthoPanel.toggleProfileToolBar' : 'Edit toolbar', + 'OrthoPanel.toggleEditToolBar' : 'Edit toolbar', 'OrthoToolBar.more' : 'More settings', 'LightBoxToolBar.more' : 'More settings', diff --git a/fsl/fsleyes/controls/__init__.py b/fsl/fsleyes/controls/__init__.py index e2f22af9fda41aed7ad087ccd631df239887b8d5..54a6a399e8e7d8e4db462d1aefe28ffe2b68f9c1 100644 --- a/fsl/fsleyes/controls/__init__.py +++ b/fsl/fsleyes/controls/__init__.py @@ -20,6 +20,6 @@ from overlayinfopanel import OverlayInfoPanel from shellpanel import ShellPanel from orthotoolbar import OrthoToolBar -from orthoprofiletoolbar import OrthoProfileToolBar +from orthoedittoolbar import OrthoEditToolBar from lightboxtoolbar import LightBoxToolBar from overlaydisplaytoolbar import OverlayDisplayToolBar diff --git a/fsl/fsleyes/controls/orthoedittoolbar.py b/fsl/fsleyes/controls/orthoedittoolbar.py new file mode 100644 index 0000000000000000000000000000000000000000..7f9ff6e5a3374fc2cd39eaed54db9454010172b2 --- /dev/null +++ b/fsl/fsleyes/controls/orthoedittoolbar.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python +# +# orthoedittoolbar.py - +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import logging + +import props + +import fsl.fsleyes.toolbar as fsltoolbar +import fsl.fsleyes.actions as actions +import fsl.fsleyes.icons as fslicons +import fsl.fsleyes.tooltips as fsltooltips +import fsl.data.strings as strings + +from fsl.fsleyes.profiles.orthoeditprofile import OrthoEditProfile + + +log = logging.getLogger(__name__) + +# Some of the toolbar widgets are labelled +_LABELS = { + + 'selectionCursorColour' : strings.properties[OrthoEditProfile, + 'selectionCursorColour'], + 'selectionOverlayColour' : strings.properties[OrthoEditProfile, + 'selectionOverlayColour'], + 'selectionSize' : strings.properties[OrthoEditProfile, + 'selectionSize'], + 'intensityThres' : strings.properties[OrthoEditProfile, + 'intensityThres'], + 'searchRadius' : strings.properties[OrthoEditProfile, + 'searchRadius'], + 'fillValue' : strings.properties[OrthoEditProfile, + 'fillValue'], +} + +_ICONS = { + 'view' : fslicons.findImageFile('eye24'), + 'edit' : fslicons.findImageFile('pencil24'), + 'selectionIs3D' : [fslicons.findImageFile('selection3D24'), + fslicons.findImageFile('selection2D24')], + 'clearSelection' : fslicons.findImageFile('clear24'), + 'undo' : fslicons.findImageFile('undo24'), + 'redo' : fslicons.findImageFile('redo24'), + 'fillSelection' : fslicons.findImageFile('fill24'), + 'createMaskFromSelection' : fslicons.findImageFile('createMask24'), + 'createROIFromSelection' : fslicons.findImageFile('createROI24'), + 'limitToRadius' : fslicons.findImageFile('radius24'), + 'localFill' : fslicons.findImageFile('localsearch24'), + 'selint' : fslicons.findImageFile('selectByIntensity24'), +} + +_TOOLTIPS = { + 'profile' : fsltooltips.properties['OrthoPanel.profile'], + 'selectionIs3D' : fsltooltips.properties['OrthoEditProfile.' + 'selectionIs3D'], + + 'clearSelection' : fsltooltips.actions['OrthoEditProfile.' + 'clearSelection'], + 'undo' : fsltooltips.actions['OrthoEditProfile.' + 'undo'], + 'redo' : fsltooltips.actions['OrthoEditProfile.' + 'redo'], + 'fillSelection' : fsltooltips.actions['OrthoEditProfile.' + 'fillSelection'], + 'createMaskFromSelection' : fsltooltips.actions['OrthoEditProfile.' + 'createMaskFromSelection'], + 'createROIFromSelection' : fsltooltips.actions['OrthoEditProfile.' + 'createROIFromSelection'], + + 'selint' : fsltooltips.properties['OrthoEditToolBar.' + 'selint'], + 'limitToRadius' : fsltooltips.properties['OrthoEditProfile.' + 'limitToRadius'], + 'searchRadius' : fsltooltips.properties['OrthoEditProfile.' + 'searchRadius'], + 'localFill' : fsltooltips.properties['OrthoEditProfile.' + 'localFill'], + 'selectionCursorColour' : fsltooltips.properties['OrthoEditProfile.sel' + 'ectionCursorColour'], + 'selectionOverlayColour' : fsltooltips.properties['OrthoEditProfile.sel' + 'ectionOverlayColour'], + 'selectionSize' : fsltooltips.properties['OrthoEditProfile.' + 'selectionSize'], + 'fillValue' : fsltooltips.properties['OrthoEditProfile.' + 'fillValue'], + 'intensityThres' : fsltooltips.properties['OrthoEditProfile.' + 'intensityThres'], +} + +_TOOLBAR_SPECS = { + + 'profile' : props.Widget( + 'profile', + tooltip=_TOOLTIPS['profile'], + icons={ + 'view' : _ICONS['view'], + 'edit' : _ICONS['edit']}), + + 'view' : {}, + + 'edit' : [ + props.Widget( + 'selectionIs3D', + enabledWhen=lambda p: p.mode in ['sel', 'desel'], + icon=_ICONS['selectionIs3D'], + tooltip=_TOOLTIPS['selectionIs3D'], + toggle=True), + actions.ActionButton( + 'clearSelection', + icon=_ICONS['clearSelection'], + tooltip=_TOOLTIPS['clearSelection']), + actions.ActionButton( + 'undo', + icon=_ICONS['undo'], + tooltip=_TOOLTIPS['undo']), + actions.ActionButton( + 'redo', + icon=_ICONS['redo'], + tooltip=_TOOLTIPS['redo']), + actions.ActionButton( + 'fillSelection', + icon=_ICONS['fillSelection'], + tooltip=_TOOLTIPS['fillSelection']), + actions.ActionButton( + 'createMaskFromSelection', + icon=_ICONS['createMaskFromSelection'], + tooltip=_TOOLTIPS['createMaskFromSelection']), + actions.ActionButton( + 'createROIFromSelection', + icon=_ICONS['createROIFromSelection'], + tooltip=_TOOLTIPS['createROIFromSelection']), + props.Widget( + 'selint', + icon=_ICONS['selint'], + tooltip=_TOOLTIPS['selint']), + props.Widget( + 'limitToRadius', + icon=_ICONS['limitToRadius'], + tooltip=_TOOLTIPS['limitToRadius'], + enabledWhen=lambda p: p.mode == 'selint'), + props.Widget( + 'localFill', + icon=_ICONS['localFill'], + tooltip=_TOOLTIPS['localFill'], + enabledWhen=lambda p: p.mode == 'selint'), + props.Widget( + 'selectionCursorColour', + label=_LABELS['selectionCursorColour'], + tooltip=_TOOLTIPS['selectionCursorColour']), + props.Widget( + 'selectionOverlayColour', + label=_LABELS['selectionOverlayColour'], + tooltip=_TOOLTIPS['selectionOverlayColour']), + props.Widget( + 'selectionSize', + enabledWhen=lambda p: p.mode in ['sel', 'desel'], + label=_LABELS['selectionSize'], + tooltip=_TOOLTIPS['selectionSize']), + props.Widget( + 'fillValue', + label=_LABELS['fillValue'], + tooltip=_TOOLTIPS['fillValue']), + props.Widget( + 'intensityThres', + label=_LABELS['intensityThres'], + tooltip=_TOOLTIPS['intensityThres'], + enabledWhen=lambda p: p.mode == 'selint'), + + props.Widget( + 'searchRadius', + label=_LABELS['searchRadius'], + tooltip=_TOOLTIPS['searchRadius'], + enabledWhen=lambda p: p.mode == 'selint' and p.limitToRadius) + ] +} + + + +class OrthoEditToolBar(fsltoolbar.FSLEyesToolBar): + + + selint = props.Boolean(default=False) + + + def __init__(self, parent, overlayList, displayCtx, ortho): + fsltoolbar.FSLEyesToolBar.__init__(self, + parent, + overlayList, + displayCtx, + 24) + + self.orthoPanel = ortho + + self .addListener('selint', self._name, self.__selintChanged) + ortho.addListener('profile', self._name, self.__profileChanged) + + self.__profileTool = props.buildGUI( + self, + ortho, + _TOOLBAR_SPECS['profile']) + + self.AddTool(self.__profileTool) + + self.__profileChanged() + + + def destroy(self): + self.orthoPanel.removeListener('profile', self._name) + fsltoolbar.FSLEyesToolBar.destroy(self) + + + def __selintChanged(self, *a): + + ortho = self.orthoPanel + + if ortho.profile != 'edit': + return + + profile = ortho.getCurrentProfile() + + if self.selint: profile.mode = 'selint' + else: profile.mode = 'sel' + + + def __profileChanged(self, *a): + + # We don't want to remove the profile tool + # created in __init__, so we skip the first + # tool + self.ClearTools(startIdx=1, destroy=True, postevent=False) + + ortho = self.orthoPanel + profile = ortho.profile + profileObj = ortho.getCurrentProfile() + + if profile == 'edit': + self.disableNotification('selint') + self.selint = profileObj.mode == 'selint' + self.enableNotification('selint') + + specs = _TOOLBAR_SPECS[profile] + + tools = [] + + for spec in specs: + + if spec.key == 'selint': target = self + else: target = profileObj + + widget = props.buildGUI(self, target, spec) + if spec.label is not None: + widget = self.MakeLabelledTool(widget, spec.label) + + tools.append(widget) + + self.InsertTools(tools, 1) diff --git a/fsl/fsleyes/controls/orthoprofiletoolbar.py b/fsl/fsleyes/controls/orthoprofiletoolbar.py deleted file mode 100644 index 252d91ccb0fd267e31e793af7da77608e5ab70c2..0000000000000000000000000000000000000000 --- a/fsl/fsleyes/controls/orthoprofiletoolbar.py +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/env python -# -# orthoprofiletoolbar.py - -# -# Author: Paul McCarthy <pauldmccarthy@gmail.com> -# - -import logging - -import wx - -import props - -import fsl.fsleyes.toolbar as fsltoolbar -import fsl.fsleyes.actions as actions -import fsl.fsleyes.icons as icons -import fsl.data.strings as strings - -from fsl.fsleyes.profiles.orthoeditprofile import OrthoEditProfile - - -log = logging.getLogger(__name__) - -# Some of the toolbar widgets are labelled -_LABELS = { - - 'selectionCursorColour' : strings.properties[OrthoEditProfile, - 'selectionCursorColour'], - 'selectionOverlayColour' : strings.properties[OrthoEditProfile, - 'selectionOverlayColour'], - 'selectionSize' : strings.properties[OrthoEditProfile, - 'selectionSize'], - 'intensityThres' : strings.properties[OrthoEditProfile, - 'intensityThres'], - 'searchRadius' : strings.properties[OrthoEditProfile, - 'searchRadius'], - 'fillValue' : strings.properties[OrthoEditProfile, - 'fillValue'], -} - -_ICONS = { - 'view' : icons.findImageFile('eye24'), - 'edit' : icons.findImageFile('pencil24'), - 'selectionIs3D' : [icons.findImageFile('selection3D24'), - icons.findImageFile('selection2D24')], - 'clearSelection' : icons.findImageFile('clear24'), - 'undo' : icons.findImageFile('undo24'), - 'redo' : icons.findImageFile('redo24'), - 'fillSelection' : icons.findImageFile('fill24'), - 'createMaskFromSelection' : icons.findImageFile('createMask24'), - 'createROIFromSelection' : icons.findImageFile('createROI24'), - 'limitToRadius' : icons.findImageFile('radius24'), - 'localFill' : icons.findImageFile('localsearch24'), - 'selint' : icons.findImageFile('selectByIntensity24'), -} - -_TOOLBAR_SPECS = { - - 'profile' : props.Widget( - 'profile', - icons={ - 'view' : _ICONS['view'], - 'edit' : _ICONS['edit']}), - - 'view' : {}, - - 'edit' : [ - props.Widget('selectionIs3D', - enabledWhen=lambda p: p.mode in ['sel', 'desel'], - icon=_ICONS['selectionIs3D'], - toggle=True), - actions.ActionButton('clearSelection', icon=_ICONS['clearSelection']), - actions.ActionButton('undo', icon=_ICONS['undo']), - actions.ActionButton('redo', icon=_ICONS['redo']), - actions.ActionButton('fillSelection', icon=_ICONS['fillSelection']), - actions.ActionButton('createMaskFromSelection', - icon=_ICONS['createMaskFromSelection']), - actions.ActionButton('createROIFromSelection', - icon=_ICONS['createROIFromSelection']), - - props.Widget('selint', icon=_ICONS['selint']), - props.Widget('limitToRadius', - icon=_ICONS['limitToRadius'], - enabledWhen=lambda p: p.mode == 'selint'), - - props.Widget('localFill', - icon=_ICONS['localFill'], - enabledWhen=lambda p: p.mode == 'selint'), - - props.Widget('selectionCursorColour', - label=_LABELS['selectionCursorColour']), - props.Widget('selectionOverlayColour', - label=_LABELS['selectionOverlayColour']), - props.Widget('selectionSize', - enabledWhen=lambda p: p.mode in ['sel', 'desel'], - label=_LABELS['selectionSize']), - - props.Widget('fillValue', label=_LABELS['fillValue']), - - props.Widget('intensityThres', - label=_LABELS['intensityThres'], - enabledWhen=lambda p: p.mode == 'selint'), - - props.Widget('searchRadius', - label=_LABELS['searchRadius'], - enabledWhen=lambda p: p.mode == 'selint' and - p.limitToRadius) - ] -} - - - -class OrthoProfileToolBar(fsltoolbar.FSLEyesToolBar): - - selint = props.Boolean(default=False) - - radius = props.Boolean(default=False) - - def __init__(self, parent, overlayList, displayCtx, ortho): - fsltoolbar.FSLEyesToolBar.__init__(self, - parent, - overlayList, - displayCtx, - 24) - - self.orthoPanel = ortho - - self .addListener('selint', self._name, self.__selintChanged) - ortho.addListener('profile', self._name, self.__profileChanged) - - self.__profileTool = props.buildGUI( - self, - ortho, - _TOOLBAR_SPECS['profile']) - - self.AddTool(self.__profileTool) - - self.__profileChanged() - - - def destroy(self): - self.orthoPanel.removeListener('profile', self._name) - fsltoolbar.FSLEyesToolBar.destroy(self) - - - def __selintChanged(self, *a): - - ortho = self.orthoPanel - - if ortho.profile != 'edit': - return - - profile = ortho.getCurrentProfile() - - if self.selint: profile.mode = 'selint' - else: profile.mode = 'sel' - - - def __profileChanged(self, *a): - - # We don't want to remove the profile tool - # created in __init__, so we skip the first - # tool - self.ClearTools(startIdx=1, destroy=True, postevent=False) - - ortho = self.orthoPanel - profile = ortho.profile - profileObj = ortho.getCurrentProfile() - - if profile == 'edit': - self.disableNotification('selint') - self.selint = profileObj.mode == 'selint' - self.enableNotification('selint') - - specs = _TOOLBAR_SPECS[profile] - - tools = [] - - for spec in specs: - - if spec.key == 'selint': target = self - else: target = profileObj - - widget = props.buildGUI(self, target, spec) - if spec.label is not None: - widget = self.MakeLabelledTool(widget, spec.label) - - tools.append(widget) - - self.InsertTools(tools, 1) diff --git a/fsl/fsleyes/tooltips.py b/fsl/fsleyes/tooltips.py index 6f3aaa11dcd49eb637c82d35743b5fd8e1382580..17d40670dc3174855f326828da6ac7120ca4aa40 100644 --- a/fsl/fsleyes/tooltips.py +++ b/fsl/fsleyes/tooltips.py @@ -194,8 +194,6 @@ properties = TypeDict({ # ViewPanels - 'ViewPanel.profile' : '', - 'CanvasPanel.syncLocation' : 'If checked, the location shown on ' 'this panel will be linked to the ' 'location shown on other panels (as ' @@ -309,13 +307,14 @@ properties = TypeDict({ # Profiles + 'OrthoPanel.profile' : 'Switch between view mode ' + 'and edit mode', 'OrthoEditProfile.selectionSize' : 'Size (in voxels) of the ' 'selection region.', - 'OrthoEditProfile.selectionIs3D' : 'If checked, the selection ' - 'region will be a 3D cube; ' - 'otherwise, it will be a' - 'square in the plane of the ' - 'active canvas.' , + 'OrthoEditProfile.selectionIs3D' : 'Choose between a 2D square ' + 'selection in the plane of ' + 'the active canvas, or a 3D ' + 'cube.', 'OrthoEditProfile.selectionCursorColour' : 'Colour to use for the ' 'selection cursor.', 'OrthoEditProfile.selectionOverlayColour' : 'Colour to use to highlight ' @@ -329,14 +328,16 @@ properties = TypeDict({ 'values for the purpose of ' 'the search.', 'OrthoEditProfile.localFill' : 'If selecting by intensity, ' - 'voxels must be adjacent to ' - 'an already selected voxel ' - 'to be conxidered in the ' - 'search. Otherwise, all ' - 'voxels in the search radius ' - 'are considered.', + 'only select voxels which are ' + 'adjacent to an already ' + 'selected voxel', + 'OrthoEditProfile.limitToRadius' : 'If selecting by intensity, ' + 'limit the search to a sphere ' + 'of the specified radius.', 'OrthoEditProfile.searchRadius' : 'Limit the search to the ' - 'specified radius.', + 'specified radius.', + + 'OrthoEditToolBar.selint' : 'Select voxels based on similar intensities', }) @@ -348,6 +349,17 @@ actions = TypeDict({ 'OrthoViewProfile.resetZoom' : 'Reset zoom level to 100%', 'OrthoViewProfile.centreCursor' : 'Reset location to centre of scene', + + 'OrthoEditProfile.undo' : 'Undo the most recent action', + 'OrthoEditProfile.redo' : 'Redo the most recent ' + 'undone action', + 'OrthoEditProfile.fillSelection' : 'Fill the selection with ' + 'the current fill value', + 'OrthoEditProfile.clearSelection' : 'Clear the current selection', + 'OrthoEditProfile.createMaskFromSelection' : 'Create a new mask overlay ' + 'from the current selection', + 'OrthoEditProfile.createROIFromSelection' : 'Create a new ROI overlay ' + 'from the current selection', }) diff --git a/fsl/fsleyes/views/orthopanel.py b/fsl/fsleyes/views/orthopanel.py index 723e0fbac53dd47691b4caee3225881142195241..04086ac0bf4e8541d2ea7572457d07d1d7dcf8d1 100644 --- a/fsl/fsleyes/views/orthopanel.py +++ b/fsl/fsleyes/views/orthopanel.py @@ -25,7 +25,7 @@ import fsl.fsleyes.colourmaps as colourmaps import fsl.fsleyes.gl.wxglslicecanvas as slicecanvas import fsl.fsleyes.controls.overlaydisplaytoolbar as overlaydisplaytoolbar import fsl.fsleyes.controls.orthotoolbar as orthotoolbar -import fsl.fsleyes.controls.orthoprofiletoolbar as orthoprofiletoolbar +import fsl.fsleyes.controls.orthoedittoolbar as orthoedittoolbar import fsl.fsleyes.displaycontext.orthoopts as orthoopts import canvaspanel @@ -48,8 +48,8 @@ class OrthoPanel(canvaspanel.CanvasPanel): actionz = { 'toggleOrthoToolBar' : lambda *a: self.togglePanel( orthotoolbar.OrthoToolBar, ortho=self), - 'toggleProfileToolBar' : lambda *a: self.togglePanel( - orthoprofiletoolbar.OrthoProfileToolBar, ortho=self), + 'toggleEditToolBar' : lambda *a: self.togglePanel( + orthoedittoolbar.OrthoEditToolBar, ortho=self), } canvaspanel.CanvasPanel.__init__(self, @@ -183,7 +183,7 @@ class OrthoPanel(canvaspanel.CanvasPanel): viewPanel=self) self.togglePanel(orthotoolbar.OrthoToolBar, ortho=self) - self.togglePanel(orthoprofiletoolbar.OrthoProfileToolBar, + self.togglePanel(orthoedittoolbar.OrthoEditToolBar, ortho=self) wx.CallAfter(addToolbars)