Skip to content
Snippets Groups Projects
Commit d1b0f875 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Reworked OverlayDisplayToolbar - control lists are now in that module,

instead of in layouts. BitmapComboBox  does not get disabled properly,
which is causing me headaches.
parent 4f45ea89
No related branches found
No related tags found
No related merge requests found
...@@ -10,13 +10,50 @@ selected overlay. ...@@ -10,13 +10,50 @@ selected overlay.
""" """
import logging import logging
log = logging.getLogger(__name__)
import wx
import props
import fsl.fslview.toolbar as fsltoolbar import fsl.fslview.toolbar as fsltoolbar
import fsl.fslview.actions as actions
import fsl.utils.typedict as td
import overlaydisplaypanel as overlaydisplay import overlaydisplaypanel as overlaydisplay
log = logging.getLogger(__name__)
_TOOLBAR_PROPS = td.TypeDict({
'Display' : [
props.Widget('name'),
props.Widget('overlayType'),
props.Widget('alpha', spin=False, showLimits=False),
props.Widget('brightness', spin=False, showLimits=False),
props.Widget('contrast', spin=False, showLimits=False)],
'VolumeOpts' : [
props.Widget('cmap')],
'MaskOpts' : [
props.Widget('colour')],
'VectorOpts' : [
props.Widget('modulate'),
props.Widget('modThreshold', showLimits=False, spin=False)],
'LabelOpts' : [
props.Widget('lut'),
props.Widget('outline'),
props.Widget('outlineWidth', showLimits=False, spin=False)],
'ModelOpts' : [
props.Widget('colour'),
props.Widget('outline'),
props.Widget('outlineWidth', showLimits=False, spin=False)]
})
class OverlayDisplayToolBar(fsltoolbar.FSLViewToolBar): class OverlayDisplayToolBar(fsltoolbar.FSLViewToolBar):
def __init__(self, parent, overlayList, displayCtx, viewPanel): def __init__(self, parent, overlayList, displayCtx, viewPanel):
...@@ -26,20 +63,19 @@ class OverlayDisplayToolBar(fsltoolbar.FSLViewToolBar): ...@@ -26,20 +63,19 @@ class OverlayDisplayToolBar(fsltoolbar.FSLViewToolBar):
fsltoolbar.FSLViewToolBar.__init__( fsltoolbar.FSLViewToolBar.__init__(
self, parent, overlayList, displayCtx, actionz) self, parent, overlayList, displayCtx, actionz)
self._viewPanel = viewPanel self.__viewPanel = viewPanel
self._overlayTools = {} self.__currentOverlay = None
self._currentOverlay = None
self._displayCtx.addListener( self._displayCtx.addListener(
'selectedOverlay', 'selectedOverlay',
self._name, self._name,
self._selectedOverlayChanged) self.__selectedOverlayChanged)
self._overlayList.addListener( self._overlayList.addListener(
'overlays', 'overlays',
self._name, self._name,
self._overlayListChanged) self.__selectedOverlayChanged)
self._selectedOverlayChanged() self.__selectedOverlayChanged()
def destroy(self): def destroy(self):
...@@ -48,165 +84,109 @@ class OverlayDisplayToolBar(fsltoolbar.FSLViewToolBar): ...@@ -48,165 +84,109 @@ class OverlayDisplayToolBar(fsltoolbar.FSLViewToolBar):
self._overlayList.removeListener('overlays', self._name) self._overlayList.removeListener('overlays', self._name)
self._displayCtx .removeListener('selectedOverlay', self._name) self._displayCtx .removeListener('selectedOverlay', self._name)
for ovl in self._overlayList: if self.__currentOverlay is not None and \
self.__currentOverlay in self._overlayList:
display = self._displayCtx.getDisplay(ovl)
display = self._displayCtx.getDisplay(self.__currentOverlay)
display.removeListener('overlayType', self._name) display.removeListener('overlayType', self._name)
display.removeListener('enabled', self._name) display.removeListener('enabled', self._name)
self.__currentOverlay = None
self.__viewPanel = None
fsltoolbar.FSLViewToolBar.destroy(self) fsltoolbar.FSLViewToolBar.destroy(self)
def showMoreSettings(self, *a): def showMoreSettings(self, *a):
self._viewPanel.togglePanel(overlaydisplay.OverlayDisplayPanel, True) self.__viewPanel.togglePanel(overlaydisplay.OverlayDisplayPanel, True)
def _overlayListChanged(self, *a):
for ovl in self._overlayTools.keys():
if ovl not in self._overlayList:
dispTools, optsTools = self._overlayTools.pop(ovl)
log.debug('Destroying all tools for {}'.format(ovl))
if ovl is self._currentOverlay:
self.ClearTools()
for tool, _ in dispTools: tool.Destroy()
for tool, _ in optsTools: tool.Destroy()
self._selectedOverlayChanged()
def _overlayTypeChanged(self, value, valid, display, name, refresh=True):
overlay = display.getOverlay()
dispTools, oldOptsTools = self._overlayTools[overlay]
newOptsTools = self._makeOptsWidgets(overlay, self)
self._overlayTools[overlay] = (dispTools, newOptsTools)
if refresh and (overlay is self._displayCtx.getSelectedOverlay()):
self._refreshTools(overlay)
log.debug('Destroying opts tools for {}'.format(overlay))
for tool, _ in oldOptsTools:
tool.Destroy()
def _toggleEnabled(self, value, valid, ovl, name):
if ovl is not self._displayCtx.getSelectedOverlay(): def __overlayEnableChanged(self, *a):
return display = self._displayCtx.getDisplay(self.__currentOverlay)
display = self._displayCtx.getDisplay(ovl)
self.Enable(display.enabled) self.Enable(display.enabled)
def _selectedOverlayChanged(self, *a):
def __selectedOverlayChanged(self, *a):
"""Called when the :attr:`.DisplayContext.selectedOverlay` """Called when the :attr:`.DisplayContext.selectedOverlay`
index changes. Ensures that the correct display panel is visible. index changes. Ensures that the correct display panel is visible.
""" """
if self.__currentOverlay is not None and \
self.__currentOverlay in self._overlayList:
display = self._displayCtx.getDisplay(self.__currentOverlay)
display.removeListener('overlayType', self._name)
display.removeListener('enabled', self._name)
overlay = self._displayCtx.getSelectedOverlay() overlay = self._displayCtx.getSelectedOverlay()
self.__currentOverlay = overlay
if overlay is None: if overlay is None:
self.ClearTools() self.ClearTools(destroy=True)
return return
display = self._displayCtx.getDisplay(overlay) display = self._displayCtx.getDisplay(overlay)
# Call _toggleEnabled when display.addListener('enabled',
# the overlay is enabled/disabled self._name,
self.__overlayEnableChanged)
display.addListener('overlayType',
self._name,
self.__selectedOverlayChanged)
self.__showTools(overlay)
self.Enable(display.enabled) self.Enable(display.enabled)
for ovl in self._overlayList:
d = self._displayCtx.getDisplay(ovl)
if ovl == overlay:
d.addListener('enabled',
self._name,
self._toggleEnabled,
overwrite=True)
else:
d.removeListener('enabled', self._name)
# Build/refresh the toolbar widgets for this overlay
tools = self._overlayTools.get(overlay, None)
if tools is None:
displayTools = self._makeDisplayWidgets(overlay, self)
optsTools = self._makeOptsWidgets( overlay, self)
self._overlayTools[overlay] = (displayTools, optsTools)
display.addListener(
'overlayType',
self._name,
self._overlayTypeChanged,
overwrite=True)
self._refreshTools(overlay) def __showTools(self, overlay):
oldTools = self.GetTools()
def _refreshTools(self, overlay): # See long comment at bottom
def destroyOldTools():
for t in oldTools:
t.Destroy()
self._currentOverlay = overlay for t in oldTools:
t.Show(False)
log.debug('Showing tools for {}'.format(overlay)) self.ClearTools(destroy=False, postevent=False)
tools = self.GetTools() log.debug('Showing tools for {}'.format(overlay))
for widget in tools:
widget.Show(False)
self.ClearTools(postevent=False)
if overlay is None: display = self._displayCtx.getDisplay(overlay)
self.Layout() opts = display.getDisplayOpts()
dispSpecs = _TOOLBAR_PROPS[display]
optsSpecs = _TOOLBAR_PROPS[opts]
dispTools, optsTools = self._overlayTools[overlay] dispTools, dispLabels = zip(*self.GenerateTools(
dispSpecs, display, add=False))
optsTools, optsLabels = zip(*self.GenerateTools(
optsSpecs, opts, add=False))
dispTools, dispLabels = zip(*dispTools)
optsTools, optsLabels = zip(*optsTools)
tools = list(dispTools) + list(optsTools) tools = list(dispTools) + list(optsTools)
labels = list(dispLabels) + list(optsLabels) labels = list(dispLabels) + list(optsLabels)
for tool in tools: # Button which opens the OverlayDisplayPanel
tool.Show(True) more = props.buildGUI(
self,
self.SetTools(tools, labels) self,
view=actions.ActionButton(type(self), 'more'))
def _makeDisplayWidgets(self, overlay, parent):
"""Creates and returns panel containing widgets allowing
the user to edit the display properties of the given
overlay object.
"""
import fsl.fslview.layouts as layouts
display = self._displayCtx.getDisplay(overlay) tools .append(more)
toolSpecs = layouts.layouts[self, display] labels.append(None)
log.debug('Creating display tools for {}'.format(overlay))
return self.GenerateTools(toolSpecs, display, add=False)
def _makeOptsWidgets(self, overlay, parent):
import fsl.fslview.layouts as layouts
opts = self._displayCtx.getOpts(overlay) self.SetTools(tools, labels)
toolSpecs = layouts.layouts[self, opts]
targets = { s.key : self if s.key == 'more' else opts
for s in toolSpecs}
log.debug('Creating options tools for {}'.format(overlay)) # This method may have been called via an
# event handler an existing tool in the
return self.GenerateTools(toolSpecs, targets, add=False) # toolbar - in this situation, destroying
# that tool will result in nasty crashes,
# as the wx widget that generated the event
# will be destroyed while said event is
# being processed. So we destroy the old
# tools asynchronously, well after the event
# which triggered this method call will have
# returned.
wx.CallLater(1000, destroyOldTools)
...@@ -22,14 +22,6 @@ from fsl.fslview.views import LightBoxPanel ...@@ -22,14 +22,6 @@ from fsl.fslview.views import LightBoxPanel
from fsl.fslview.controls import OrthoToolBar from fsl.fslview.controls import OrthoToolBar
from fsl.fslview.controls import LightBoxToolBar from fsl.fslview.controls import LightBoxToolBar
from fsl.fslview.controls import OverlayDisplayToolBar
from fsl.fslview.displaycontext import Display
from fsl.fslview.displaycontext import VolumeOpts
from fsl.fslview.displaycontext import MaskOpts
from fsl.fslview.displaycontext import VectorOpts
from fsl.fslview.displaycontext import ModelOpts
from fsl.fslview.displaycontext import LabelOpts
from fsl.fslview.displaycontext import OrthoOpts from fsl.fslview.displaycontext import OrthoOpts
from fsl.fslview.displaycontext import LightBoxOpts from fsl.fslview.displaycontext import LightBoxOpts
...@@ -102,57 +94,8 @@ LightBoxToolBarLayout = [ ...@@ -102,57 +94,8 @@ LightBoxToolBarLayout = [
actions.ActionButton(LightBoxToolBar, 'more')] actions.ActionButton(LightBoxToolBar, 'more')]
##########################################
# Overlay display property panels/toolbars
##########################################
DisplayToolBarLayout = [
widget(Display, 'name'),
widget(Display, 'overlayType'),
widget(Display, 'alpha', spin=False, showLimits=False),
widget(Display, 'brightness', spin=False, showLimits=False),
widget(Display, 'contrast', spin=False, showLimits=False)]
VolumeOptsToolBarLayout = [
widget(VolumeOpts, 'cmap'),
actions.ActionButton(OverlayDisplayToolBar, 'more')]
MaskOptsToolBarLayout = [
widget(MaskOpts, 'colour'),
actions.ActionButton(OverlayDisplayToolBar, 'more')]
VectorOptsToolBarLayout = [
widget(VectorOpts, 'modulate'),
widget(VectorOpts, 'modThreshold', showLimits=False, spin=False),
actions.ActionButton(OverlayDisplayToolBar, 'more')]
ModelOptsToolBarLayout = [
widget(ModelOpts, 'colour'),
widget(ModelOpts, 'outline'),
widget(ModelOpts, 'outlineWidth', showLimits=False, spin=False),
actions.ActionButton(OverlayDisplayToolBar, 'more')]
LabelOptsToolBarLayout = [
widget(LabelOpts, 'lut'),
widget(LabelOpts, 'outline'),
widget(LabelOpts, 'outlineWidth', showLimits=False, spin=False),
actions.ActionButton(OverlayDisplayToolBar, 'more')]
layouts = td.TypeDict({ layouts = td.TypeDict({
('OverlayDisplayToolBar', 'Display') : DisplayToolBarLayout,
('OverlayDisplayToolBar', 'VolumeOpts') : VolumeOptsToolBarLayout,
('OverlayDisplayToolBar', 'MaskOpts') : MaskOptsToolBarLayout,
('OverlayDisplayToolBar', 'VectorOpts') : VectorOptsToolBarLayout,
('OverlayDisplayToolBar', 'ModelOpts') : ModelOptsToolBarLayout,
('OverlayDisplayToolBar', 'LabelOpts') : LabelOptsToolBarLayout,
'OrthoToolBar' : OrthoToolBarLayout, 'OrthoToolBar' : OrthoToolBarLayout,
'LightBoxToolBar' : LightBoxToolBarLayout, 'LightBoxToolBar' : LightBoxToolBarLayout,
......
...@@ -70,6 +70,13 @@ class FSLViewToolBar(fslpanel._FSLViewPanel, wx.PyPanel): ...@@ -70,6 +70,13 @@ class FSLViewToolBar(fslpanel._FSLViewPanel, wx.PyPanel):
type(self.label).__name__, type(self.label).__name__,
self.labelText) self.labelText)
def Enable(self, *args, **kwargs):
wx.Panel.Enable(self, *args, **kwargs)
self.tool.Enable(*args, **kwargs)
if self.label is not None:
self.label.Enable(*args, **kwargs)
def __init__(self, parent, overlayList, displayCtx, actionz=None): def __init__(self, parent, overlayList, displayCtx, actionz=None):
wx.PyPanel.__init__(self, parent) wx.PyPanel.__init__(self, parent)
...@@ -187,6 +194,12 @@ class FSLViewToolBar(fslpanel._FSLViewPanel, wx.PyPanel): ...@@ -187,6 +194,12 @@ class FSLViewToolBar(fslpanel._FSLViewPanel, wx.PyPanel):
self.Layout() self.Layout()
def Enable(self, *args, **kwargs):
wx.PyPanel.Enable(self, *args, **kwargs)
for t in self.__tools:
t.Enable(*args, **kwargs)
def GenerateTools(self, toolSpecs, targets, add=True): def GenerateTools(self, toolSpecs, targets, add=True):
""" """
Targets may be a single object, or a dict of [toolSpec : target] Targets may be a single object, or a dict of [toolSpec : target]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment