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

Fixed LightBoxPanel scrollbar layout - colour bar is now always flush

with canvas, and scrollbar no longer appears in screenshots.
parent eded900f
No related branches found
No related tags found
No related merge requests found
...@@ -36,8 +36,8 @@ import fsl.fsleyes.controls.clusterpanel as clusterpanel ...@@ -36,8 +36,8 @@ import fsl.fsleyes.controls.clusterpanel as clusterpanel
import fsl.fsleyes.controls.lookuptablepanel as lookuptablepanel import fsl.fsleyes.controls.lookuptablepanel as lookuptablepanel
import fsl.fsleyes.controls.shellpanel as shellpanel import fsl.fsleyes.controls.shellpanel as shellpanel
import colourbarpanel import colourbarpanel
import viewpanel import viewpanel
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -64,10 +64,16 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -64,10 +64,16 @@ class CanvasPanel(viewpanel.ViewPanel):
Sub-classes of the ``CanvasPanel`` must do the following: Sub-classes of the ``CanvasPanel`` must do the following:
1. Add their content to the panel that is accessible via the 1. Add their content to the panel that is accessible via the
:meth:`getCanvasPanel` method (see the note on :meth:`getContentPanel` method (see the note on
:ref:`adding content <canvaspanel-adding-content>`). :ref:`adding content <canvaspanel-adding-content>`).
2. Override the :meth:`getGLCanvases` method. 2. Override the :meth:`getGLCanvases` method.
3. Call the :meth:`centrePanelLayout` method in their ``__init__``
method.
4. Override the :meth:`centrePanelLayout` method if any custom layout is
necessary.
**Actions** **Actions**
...@@ -104,14 +110,14 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -104,14 +110,14 @@ class CanvasPanel(viewpanel.ViewPanel):
.. _canvaspanel-adding-content: .. _canvaspanel-adding-content:
**Adding content** **Adding content**
To support colour bar functionality, the ``CanvasPanel`` uses a hierarchy To support colour bar and screenshot functionality, the ``CanvasPanel``
of ``wx.Panel`` instances, depicted in the following containment uses a hierarchy of ``wx.Panel`` instances, depicted in the following
hierarchy diagram: containment hierarchy diagram:
.. graphviz:: .. graphviz::
...@@ -127,23 +133,49 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -127,23 +133,49 @@ class CanvasPanel(viewpanel.ViewPanel):
rankdir="BT"; rankdir="BT";
1 [label="CanvasPanel"]; 1 [label="CanvasPanel"];
2 [label="Canvas container"]; 2 [label="Centre panel"];
3 [label="ColourBarPanel"]; 3 [label="Advanced layout"];
4 [label="Centre panel"]; 4 [label="Container panel"];
5 [label="Content added by sub-classes"]; 5 [label="ColourBarPanel"];
6 [label="Content panel"];
7 [label="Content added by sub-classes"];
2 -> 1; 2 -> 1;
3 -> 2; 3 -> 2;
4 -> 2; 4 -> 2;
5 -> 4; 5 -> 4;
6 -> 4;
7 -> 6;
} }
As depicted in the diagram, sub-classes need to add their content to the As depicted in the diagram, sub-classes need to add their content to the
*centre panel*. This panel is accessible via the :meth:`getCanvasPanel` *content panel*. This panel is accessible via the :meth:`getContentPanel`
method. The *container panel* is what gets passed to the method.
The *centre panel* is what gets passed to the
:meth:`.ViewPanel.setCentrePanel` method, and is accessible via the :meth:`.ViewPanel.setCentrePanel` method, and is accessible via the
:meth:`getCanvasContainer` method, if necessary. :meth:`getCentrePanel` method, if necessary. The *container panel* is
also available, via the :meth:`getContainerPanel`. Everything in the
container panel will appear in screenshots (see the :meth:`screenshot`
method).
The :meth:`centrePanelLayout` method lays out the centre panel, using the
:meth:`layoutContainerPanel` method to lay out the colour bar and the
content panel. The ``centrePanelLayout`` method simply adds the canvas
container directly to the centre panel. Sub-classes which have more
advanced layout requirements (e.g. the :class:`.LightBoxPanel` needs a
scrollbar) may override the :meth:`centrePanelLayout` method to implement
their own layout. These sub-class implementations must:
1. Call the :meth:`layoutCanvasContainer` method.
2. Add the container panel (accessed via :meth:`getContainerPanel`)
to the centre panel (:meth:`getCentrePanel`)
3. Add any other custom content to the centre panel.
""" """
...@@ -274,10 +306,11 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -274,10 +306,11 @@ class CanvasPanel(viewpanel.ViewPanel):
self.disableProperty('syncOverlayOrder') self.disableProperty('syncOverlayOrder')
self.disableProperty('syncOverlayDisplay') self.disableProperty('syncOverlayDisplay')
self.__canvasContainer = wx.Panel(self) self.__centrePanel = wx.Panel(self)
self.__canvasPanel = wx.Panel(self.__canvasContainer) self.__containerPanel = wx.Panel(self.__centrePanel)
self.__contentPanel = wx.Panel(self.__containerPanel)
self.setCentrePanel(self.__canvasContainer) self.setCentrePanel(self.__centrePanel)
# Stores a reference to a wx.Timer # Stores a reference to a wx.Timer
# when movie mode is enabled # when movie mode is enabled
...@@ -291,17 +324,18 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -291,17 +324,18 @@ class CanvasPanel(viewpanel.ViewPanel):
self.__movieRateChanged) self.__movieRateChanged)
# Canvas/colour bar layout is managed in # Canvas/colour bar layout is managed in
# the _layout/_toggleColourBar methods # the layoutColourBarAndCanvas method
self.__canvasSizer = None self.__colourBar = None
self.__colourBar = None
# Use a different listener name so that subclasses # Use a different listener name so that subclasses
# can register on the same properties with self._name # can register on the same properties with self._name
lName = 'CanvasPanel_{}'.format(self._name) lName = 'CanvasPanel_{}'.format(self._name)
self.__opts.addListener('colourBarLocation', lName, self.__layout) self.__opts.addListener('colourBarLocation',
self.__opts.addListener('showColourBar', lName, self.__layout) lName,
self.__colourBarPropsChanged)
self.__layout() self.__opts.addListener('showColourBar',
lName,
self.__colourBarPropsChanged)
def destroy(self): def destroy(self):
...@@ -337,20 +371,28 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -337,20 +371,28 @@ class CanvasPanel(viewpanel.ViewPanel):
return self.__opts return self.__opts
def getCanvasPanel(self): def getCentrePanel(self):
"""Returns the ``wx.Panel`` which is passed to
:meth:`.ViewPanel.setCentrePanel`. See the note on
:ref:`adding content <canvaspanel-adding-content>`.
"""
return self.__centrePanel
def getContentPanel(self):
"""Returns the ``wx.Panel`` to which sub-classes must add their content. """Returns the ``wx.Panel`` to which sub-classes must add their content.
See the note on :ref:`adding content <canvaspanel-adding-content>`. See the note on :ref:`adding content <canvaspanel-adding-content>`.
""" """
return self.__canvasPanel return self.__contentPanel
def getCanvasContainer(self): def getContainerPanel(self):
"""Returns the ``wx.Panel`` which contains the """Returns the ``wx.Panel`` which contains the
:class:`.ColourBarPanel` if it is being displayed, and the canvas :class:`.ColourBarPanel` if it is being displayed, and the content
panel. See the note on panel. See the note on
:ref:`adding content <canvaspanel-adding-content>`. :ref:`adding content <canvaspanel-adding-content>`.
""" """
return self.__canvasContainer return self.__containerPanel
def getGLCanvases(self): def getGLCanvases(self):
...@@ -375,11 +417,27 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -375,11 +417,27 @@ class CanvasPanel(viewpanel.ViewPanel):
return None return None
def __layout(self, *a): def centrePanelLayout(self):
"""Called when any colour bar display properties are changed (see """Lays out the centre panel. This method may be overridden by
:class:`.SceneOpts`). Lays out the container panel, which contains sub-classes which need more advanced layout logic. See the note on
the :class:`.ColourBarPanel` and all content added by the :ref:`adding content <canvaspanel-adding-content>`
``CanvasPanel`` sub-class implementation. """
self.layoutContainerPanel()
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.__containerPanel, flag=wx.EXPAND, proportion=1)
self.__centrePanel.SetSizer(sizer)
self.PostSizeEvent()
def layoutContainerPanel(self):
"""Creates a ``wx.Sizer``, and uses it to lay out the colour bar panel
and canvas panel. The sizer object is returned.
This method is used by the default :meth:`centrePanelLayout` method,
and is available for custom sub-class implementations to use.
""" """
if not self.__opts.showColourBar: if not self.__opts.showColourBar:
...@@ -391,19 +449,15 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -391,19 +449,15 @@ class CanvasPanel(viewpanel.ViewPanel):
self.__colourBar.destroy() self.__colourBar.destroy()
self.__colourBar.Destroy() self.__colourBar.Destroy()
self.__colourBar = None self.__colourBar = None
self.__canvasSizer = wx.BoxSizer(wx.HORIZONTAL)
self.__canvasSizer.Add(self.__canvasPanel,
flag=wx.EXPAND,
proportion=1)
self.__canvasContainer.SetSizer(self.__canvasSizer) sizer = wx.BoxSizer(wx.HORIZONTAL)
self.PostSizeEvent() sizer.Add(self.__contentPanel, flag=wx.EXPAND, proportion=1)
self.__containerPanel.SetSizer(sizer)
return return
if self.__colourBar is None: if self.__colourBar is None:
self.__colourBar = colourbarpanel.ColourBarPanel( self.__colourBar = colourbarpanel.ColourBarPanel(
self.__canvasContainer, self._overlayList, self._displayCtx) self.__containerPanel, self._overlayList, self._displayCtx)
self.__opts.bindProps('colourBarLabelSide', self.__opts.bindProps('colourBarLabelSide',
self.__colourBar, self.__colourBar,
...@@ -415,23 +469,18 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -415,23 +469,18 @@ class CanvasPanel(viewpanel.ViewPanel):
self.__colourBar.orientation = 'vertical' self.__colourBar.orientation = 'vertical'
if self.__opts.colourBarLocation in ('top', 'bottom'): if self.__opts.colourBarLocation in ('top', 'bottom'):
self.__canvasSizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.BoxSizer(wx.VERTICAL)
else: else:
self.__canvasSizer = wx.BoxSizer(wx.HORIZONTAL) sizer = wx.BoxSizer(wx.HORIZONTAL)
self.__canvasContainer.SetSizer(self.__canvasSizer)
if self.__opts.colourBarLocation in ('top', 'left'): if self.__opts.colourBarLocation in ('top', 'left'):
self.__canvasSizer.Add(self.__colourBar, flag=wx.EXPAND) sizer.Add(self.__colourBar, flag=wx.EXPAND)
self.__canvasSizer.Add(self.__canvasPanel, flag=wx.EXPAND, sizer.Add(self.__contentPanel, flag=wx.EXPAND, proportion=1)
proportion=1)
else: else:
self.__canvasSizer.Add(self.__canvasPanel, flag=wx.EXPAND, sizer.Add(self.__contentPanel, flag=wx.EXPAND, proportion=1)
proportion=1) sizer.Add(self.__colourBar, flag=wx.EXPAND)
self.__canvasSizer.Add(self.__colourBar, flag=wx.EXPAND)
# Force the canvas panel to resize itself self.__containerPanel.SetSizer(sizer)
self.PostSizeEvent()
def __movieModeChanged(self, *a): def __movieModeChanged(self, *a):
...@@ -455,6 +504,13 @@ class CanvasPanel(viewpanel.ViewPanel): ...@@ -455,6 +504,13 @@ class CanvasPanel(viewpanel.ViewPanel):
self.__movieTimer = wx.Timer(self) self.__movieTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.__movieUpdate) self.Bind(wx.EVT_TIMER, self.__movieUpdate)
self.__movieTimer.Start(rate) self.__movieTimer.Start(rate)
def __colourBarPropsChanged(self, *a):
"""Called when any colour bar display properties are changed (see
:class:`.SceneOpts`). Calls :meth:`canvasPanelLayout`.
"""
self.centrePanelLayout()
def __movieRateChanged(self, *a): def __movieRateChanged(self, *a):
...@@ -653,7 +709,7 @@ def _screenshot(overlayList, displayCtx, canvasPanel): ...@@ -653,7 +709,7 @@ def _screenshot(overlayList, displayCtx, canvasPanel):
# direct parent of the colour bar # direct parent of the colour bar
# canvas, and an ancestor of the # canvas, and an ancestor of the
# other GL canvases # other GL canvases
parent = canvasPanel.getCanvasContainer() parent = canvasPanel.getContainerPanel()
width, height = parent.GetClientSize().Get() width, height = parent.GetClientSize().Get()
windowDC = wx.WindowDC(parent) windowDC = wx.WindowDC(parent)
memoryDC = wx.MemoryDC() memoryDC = wx.MemoryDC()
......
...@@ -86,11 +86,11 @@ class LightBoxPanel(canvaspanel.CanvasPanel): ...@@ -86,11 +86,11 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
actionz) actionz)
self.__scrollbar = wx.ScrollBar( self.__scrollbar = wx.ScrollBar(
self.getCanvasPanel(), self.getCentrePanel(),
style=wx.SB_VERTICAL) style=wx.SB_VERTICAL)
self.__lbCanvas = lightboxcanvas.WXGLLightBoxCanvas( self.__lbCanvas = lightboxcanvas.WXGLLightBoxCanvas(
self.getCanvasPanel(), self.getContentPanel(),
overlayList, overlayList,
displayCtx) displayCtx)
...@@ -117,10 +117,9 @@ class LightBoxPanel(canvaspanel.CanvasPanel): ...@@ -117,10 +117,9 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
sceneOpts.bindProps('zrange', self.__lbCanvas) sceneOpts.bindProps('zrange', self.__lbCanvas)
self.__canvasSizer = wx.BoxSizer(wx.HORIZONTAL) self.__canvasSizer = wx.BoxSizer(wx.HORIZONTAL)
self.getCanvasPanel().SetSizer(self.__canvasSizer) self.getContentPanel().SetSizer(self.__canvasSizer)
self.__canvasSizer.Add(self.__lbCanvas, flag=wx.EXPAND, proportion=1) self.__canvasSizer.Add(self.__lbCanvas, flag=wx.EXPAND, proportion=1)
self.__canvasSizer.Add(self.__scrollbar, flag=wx.EXPAND)
# When the display context location changes, # When the display context location changes,
# make sure the location is shown on the canvas # make sure the location is shown on the canvas
...@@ -162,8 +161,9 @@ class LightBoxPanel(canvaspanel.CanvasPanel): ...@@ -162,8 +161,9 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
self.__onLightBoxChange() self.__onLightBoxChange()
self.__onZoom() self.__onZoom()
self.__selectedOverlayChanged() self.__selectedOverlayChanged()
self.Layout() self.centrePanelLayout()
self.initProfile() self.initProfile()
# The ViewPanel AuiManager seems to # The ViewPanel AuiManager seems to
...@@ -204,6 +204,25 @@ class LightBoxPanel(canvaspanel.CanvasPanel): ...@@ -204,6 +204,25 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
"""Returns a reference to the :class:`.LightBoxCanvas` instance. """ """Returns a reference to the :class:`.LightBoxCanvas` instance. """
return self.__lbCanvas return self.__lbCanvas
def centrePanelLayout(self):
"""Overrides :meth:`.CanvasPanel.centrePanelLayout`. Adds the
scrollbar to the centre panel.
"""
self.layoutContainerPanel()
centrePanel = self.getCentrePanel()
containerPanel = self.getContainerPanel()
sizer = wx.BoxSizer(wx.HORIZONTAL)
centrePanel.SetSizer(sizer)
sizer.Add(containerPanel, flag=wx.EXPAND, proportion=1)
sizer.Add(self.__scrollbar, flag=wx.EXPAND)
self.PostSizeEvent()
def __selectedOverlayChanged(self, *a): def __selectedOverlayChanged(self, *a):
"""Called when the :attr:`.DisplayContext.selectedOverlay` changes. """Called when the :attr:`.DisplayContext.selectedOverlay` changes.
......
...@@ -148,19 +148,19 @@ class OrthoPanel(canvaspanel.CanvasPanel): ...@@ -148,19 +148,19 @@ class OrthoPanel(canvaspanel.CanvasPanel):
sceneOpts, sceneOpts,
actionz) actionz)
canvasPanel = self.getCanvasPanel() contentPanel = self.getContentPanel()
# The canvases themselves - each one displays a # The canvases themselves - each one displays a
# slice along each of the three world axes # slice along each of the three world axes
self.__xcanvas = slicecanvas.WXGLSliceCanvas(canvasPanel, self.__xcanvas = slicecanvas.WXGLSliceCanvas(contentPanel,
overlayList, overlayList,
displayCtx, displayCtx,
zax=0) zax=0)
self.__ycanvas = slicecanvas.WXGLSliceCanvas(canvasPanel, self.__ycanvas = slicecanvas.WXGLSliceCanvas(contentPanel,
overlayList, overlayList,
displayCtx, displayCtx,
zax=1) zax=1)
self.__zcanvas = slicecanvas.WXGLSliceCanvas(canvasPanel, self.__zcanvas = slicecanvas.WXGLSliceCanvas(contentPanel,
overlayList, overlayList,
displayCtx, displayCtx,
zax=2) zax=2)
...@@ -172,9 +172,9 @@ class OrthoPanel(canvaspanel.CanvasPanel): ...@@ -172,9 +172,9 @@ class OrthoPanel(canvaspanel.CanvasPanel):
self.__zLabels = {} self.__zLabels = {}
for side in ('left', 'right', 'top', 'bottom'): for side in ('left', 'right', 'top', 'bottom'):
self.__xLabels[side] = wx.StaticText(canvasPanel) self.__xLabels[side] = wx.StaticText(contentPanel)
self.__yLabels[side] = wx.StaticText(canvasPanel) self.__yLabels[side] = wx.StaticText(contentPanel)
self.__zLabels[side] = wx.StaticText(canvasPanel) self.__zLabels[side] = wx.StaticText(contentPanel)
self.__xcanvas.bindProps('showCursor', sceneOpts) self.__xcanvas.bindProps('showCursor', sceneOpts)
self.__ycanvas.bindProps('showCursor', sceneOpts) self.__ycanvas.bindProps('showCursor', sceneOpts)
...@@ -236,13 +236,14 @@ class OrthoPanel(canvaspanel.CanvasPanel): ...@@ -236,13 +236,14 @@ class OrthoPanel(canvaspanel.CanvasPanel):
# the slice canvases when the canvas # the slice canvases when the canvas
# panel is resized, so aspect ratio # panel is resized, so aspect ratio
# is maintained # is maintained
canvasPanel.Bind(wx.EVT_SIZE, self.__onResize) contentPanel.Bind(wx.EVT_SIZE, self.__onResize)
# Initialise the panel # Initialise the panel
self.__refreshLayout() self.__refreshLayout()
self.__bgColourChanged() self.__bgColourChanged()
self.__overlayListChanged() self.__overlayListChanged()
self.__locationChanged() self.__locationChanged()
self.centrePanelLayout()
self.initProfile() self.initProfile()
# The ViewPanel AuiManager seems to # The ViewPanel AuiManager seems to
...@@ -328,8 +329,8 @@ class OrthoPanel(canvaspanel.CanvasPanel): ...@@ -328,8 +329,8 @@ class OrthoPanel(canvaspanel.CanvasPanel):
bg = [int(round(c * 255)) for c in bg] bg = [int(round(c * 255)) for c in bg]
fg = [int(round(c * 255)) for c in fg] fg = [int(round(c * 255)) for c in fg]
self.getCanvasPanel().SetBackgroundColour(bg) self.getContentPanel().SetBackgroundColour(bg)
self.getCanvasPanel().SetForegroundColour(fg) self.getContentPanel().SetForegroundColour(fg)
self.__xcanvas.SetBackgroundColour(bg) self.__xcanvas.SetBackgroundColour(bg)
self.__ycanvas.SetBackgroundColour(bg) self.__ycanvas.SetBackgroundColour(bg)
...@@ -539,7 +540,7 @@ class OrthoPanel(canvaspanel.CanvasPanel): ...@@ -539,7 +540,7 @@ class OrthoPanel(canvaspanel.CanvasPanel):
opts = self.getSceneOptions() opts = self.getSceneOptions()
layout = opts.layout layout = opts.layout
width, height = self.getCanvasPanel().GetClientSize().Get() width, height = self.getContentPanel().GetClientSize().Get()
show = [opts.showXCanvas, opts.showYCanvas, opts.showZCanvas] show = [opts.showXCanvas, opts.showYCanvas, opts.showZCanvas]
canvases = [self.__xcanvas, self.__ycanvas, self.__zcanvas] canvases = [self.__xcanvas, self.__ycanvas, self.__zcanvas]
...@@ -765,7 +766,7 @@ class OrthoPanel(canvaspanel.CanvasPanel): ...@@ -765,7 +766,7 @@ class OrthoPanel(canvaspanel.CanvasPanel):
for w in widgets: for w in widgets:
self.__canvasSizer.Add(w, flag=flag) self.__canvasSizer.Add(w, flag=flag)
self.getCanvasPanel().SetSizer(self.__canvasSizer) self.getContentPanel().SetSizer(self.__canvasSizer)
# Calculate/ adjust the appropriate sizes # Calculate/ adjust the appropriate sizes
# for each canvas, such that they are scaled # for each canvas, such that they are scaled
...@@ -775,7 +776,7 @@ class OrthoPanel(canvaspanel.CanvasPanel): ...@@ -775,7 +776,7 @@ class OrthoPanel(canvaspanel.CanvasPanel):
self.__calcCanvasSizes() self.__calcCanvasSizes()
self.Layout() self.Layout()
self.getCanvasPanel().Layout() self.getContentPanel().Layout()
self.Refresh() self.Refresh()
......
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