#
# displayspacewarning.py - The DisplaySpaceWarning class
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`DisplaySpaceWarning`, a FSLeyes
control widget which displays a warning when the
:attr:`.DisplayContext.displaySpace` has a value which is preventing
the user from seeing or doing something.
"""
import logging
import wx
import wx.lib.agw.aui as wxaui
import fsl.utils.idle as idle
import fsleyes.panel as fslpanel
import fsleyes.strings as strings
log = logging.getLogger(__name__)
[docs]class DisplaySpaceWarning(fslpanel.FSLeyesPanel):
"""The ``DisplaySpaceWarning`` is a panel which contains a message and a
button. When the :attr:`.DisplayContext.displaySpace` is set to a value
that matches the ``warnCondition`` passed to ``__init__``, the warning
message and button are shown, otherwise the entire panel is hidden. When
the user pushes the button, the ``displaySpace`` is changed to the value
specified by ``changeTo``.
"""
[docs] def __init__(self,
parent,
overlayList,
displayCtx,
frame,
msg,
warnCondition,
changeTo):
"""Create a ``DisplaySpaceWarning``.
:arg parent: ``wx`` parent object
:arg overlayList: The :class:`.OverlayList`
:arg displayCtx: The :class:`.DisplayContext`
:arg frame: The :class:`.FSLeyesFrame`
:arg msg: Message to display
:arg warnCondition: One of ``'world'``, ``'overlay'``,
``'not overlay'``, or ``'not like overlay'``
:arg changeTo: One of ``'world'`` or ``'overlay'``
"""
fslpanel.FSLeyesPanel.__init__(
self, parent, overlayList, displayCtx, frame)
self.__warnCondition = warnCondition
self.__changeTo = changeTo
self.__dsWarning = wx.StaticText(self)
self.__changeDS = wx.Button( self)
self.__dsWarning.SetLabel(msg)
self.__changeDS .SetLabel(strings.labels[self, 'changeDS'])
self.__dsWarning.SetForegroundColour((192, 0, 0, 255))
self.__sizer = wx.BoxSizer(wx.HORIZONTAL)
self.__realSizer = wx.BoxSizer(wx.HORIZONTAL)
self.__realSizer.Add((1, 1), flag=wx.EXPAND)
self.__realSizer.Add(self.__dsWarning)
self.__realSizer.Add((10, 1))
self.__realSizer.Add(self.__changeDS, flag=wx.ALIGN_CENTRE_VERTICAL)
self.__realSizer.Add((1, 1), flag=wx.EXPAND)
self.__sizer .Add(self.__realSizer, flag=wx.EXPAND)
self.SetSizer(self.__sizer)
self.Fit()
self.__size = self.GetBestSize()
self.__changeDS .Bind(wx.EVT_BUTTON, self.__onChangeDS)
displayCtx .addListener('displaySpace',
self.name,
self.__displaySpaceChanged)
displayCtx .addListener('selectedOverlay',
self.name,
self.__displaySpaceChanged)
overlayList.addListener('overlays',
self.name,
self.__displaySpaceChanged)
idle.idle(self.__displaySpaceChanged)
[docs] def destroy(self):
"""Must be called when this ``DisplaySpaceWarning`` is no longer
needed. De-registers listeners.
"""
displayCtx = self.displayCtx
overlayList = self.overlayList
displayCtx .removeListener('displaySpace', self.name)
displayCtx .removeListener('selectedOverlay', self.name)
overlayList.removeListener('overlays', self.name)
fslpanel.FSLeyesPanel.destroy(self)
def __displaySpaceChanged(self, *a):
"""Called when the :attr:`.DisplayContext.displaySpace` property
changes. If it has been given a setting that would cause the
transformation changes to have no effect on the display, a warning
message is shown.
"""
if self.destroyed:
return
parent = self.GetParent()
condition = self.__warnCondition
displayCtx = self.displayCtx
displaySpace = displayCtx.displaySpace
overlay = displayCtx.getSelectedOverlay()
if overlay is not None:
overlay = displayCtx.getOpts(overlay).referenceImage
if condition == 'overlay': show = displaySpace is overlay
elif condition == 'not overlay': show = displaySpace is not overlay
elif condition == 'world': show = displaySpace == 'world'
elif condition == 'like overlay':
if displaySpace == 'world':
show = False
else:
show = (overlay is not None) and \
overlay.sameSpace(displaySpace)
elif condition == 'not like overlay':
if displaySpace == 'world':
show = True
else:
show = (overlay is not None) and \
(not overlay.sameSpace(displaySpace))
else:
show = False
if show: size = self.__size
else: size = (0, 0)
if show:
log.debug('Showing display space warning ({} / {})'.format(
displaySpace, condition))
self.SetMinSize( size)
self.CacheBestSize(size)
self.__sizer.Show(self.__realSizer, show)
self.Layout()
self.Fit()
sizer = parent.GetSizer()
parent.SetInitialSize(sizer.GetMinSize())
parent = parent.GetTopLevelParent()
sizer = parent.GetSizer()
if isinstance(parent, wxaui.AuiFloatingFrame):
parent.SetInitialSize(sizer.GetMinSize())
parent.Layout()
parent.Fit()
def __onChangeDS(self, ev):
"""Called when the *Change display space* button is pushed. This button
is only shown if the :attr:`.DisplayContext.displaySpace` is set to
something which causes the transformation change to have no effect on
the display. This method changes the ``displaySpace`` to that
specified by the ``changeTo`` argument passed to :meth:`__init__`.
"""
changeTo = self.__changeTo
displayCtx = self.displayCtx
if changeTo == 'world':
newSpace = 'world'
elif changeTo == 'overlay' and len(self.overlayList) > 0:
newSpace = displayCtx.getSelectedOverlay()
newSpace = displayCtx.getReferenceImage(newSpace)
log.debug('Changing displaySpace to {}'.format(newSpace))
displayCtx.displaySpace = newSpace