diff --git a/doc/fsl.fsleyes.widgets.rst b/doc/fsl.fsleyes.widgets.rst index 18cbb7ab1718e4924ceb5b2e2656ce96ecca9b90..0041edee01bbe48781a9dff69ed284cc4bf283c0 100644 --- a/doc/fsl.fsleyes.widgets.rst +++ b/doc/fsl.fsleyes.widgets.rst @@ -1,19 +1,6 @@ fsl.fsleyes.widgets package =========================== -Submodules ----------- - -.. toctree:: - - fsl.fsleyes.widgets.imagepanel - fsl.fsleyes.widgets.swappanel - fsl.fsleyes.widgets.textpanel - fsl.fsleyes.widgets.togglepanel - -Module contents ---------------- - .. automodule:: fsl.fsleyes.widgets :members: :undoc-members: diff --git a/fsl/fsleyes/widgets/__init__.py b/fsl/fsleyes/widgets/__init__.py index 81e45d26470a5afb30739ac7080b31b5a7c74de8..58fc471de87d1ec63a359f32f18e7aa6c204d702 100644 --- a/fsl/fsleyes/widgets/__init__.py +++ b/fsl/fsleyes/widgets/__init__.py @@ -4,12 +4,13 @@ # # Author: Paul McCarthy <pauldmccarthy@gmail.com> # -"""This package contains a collection of generic custom WX widgets. No more, -no less. -""" +"""This package contains a collection of generic custom :mod:`wx` widgets. No +more, no less. -import logging -log = logging.getLogger(__name__) +.. autosummary:: -from textpanel import TextPanel -from imagepanel import ImagePanel + ~fsl.fsleyes.widgets.imagepanel + ~fsl.fsleyes.widgets.swappanel + ~fsl.fsleyes.widgets.togglepanel + ~fsl.fsleyes.widgets.textpanel +""" diff --git a/fsl/fsleyes/widgets/imagepanel.py b/fsl/fsleyes/widgets/imagepanel.py index f42086cc24155424de7802d6fc2fb1bad537a2d2..cf74b453fcc3fcc5265c8312f7dc791f988103fe 100644 --- a/fsl/fsleyes/widgets/imagepanel.py +++ b/fsl/fsleyes/widgets/imagepanel.py @@ -9,46 +9,70 @@ """ import logging -log = logging.getLogger(__name__) import wx + +log = logging.getLogger(__name__) + + class ImagePanel(wx.PyPanel): - """A :class:`wx.Panel` which may be used to display a resizeable + """A :class:`wx.PyPanel` which may be used to display a resizeable :class:`wx.Image`. The image is scaled to the size of the panel. """ def __init__(self, parent, image=None): + """Create an ``ImagePanel``. + + If the ``image`` is not passed in here, it can be set later with the + :meth:`SetImage` method. + + :arg parent: The :mod:`wx` parent object. + + :arg image: The :class:`wx.Image` object to display. + """ wx.PyPanel.__init__(self, parent) self.Bind(wx.EVT_PAINT, self.Draw) - self.Bind(wx.EVT_SIZE, self._onSize) + self.Bind(wx.EVT_SIZE, self.__onSize) self.SetImage(image) def SetImage(self, image): - self._image = image + """Set the image that is displayed on this ``ImagePanel``. + + :arg image: The :class:`wx.Image` object to display. + """ + self.__image = image self.Refresh() - def _onSize(self, ev): + def __onSize(self, ev): + """Redraw this panel when it is sized, so the image is scaled + appropriately - see the :meth:`Draw` method. + """ self.Refresh() ev.Skip() def DoGetBestSize(self): + """Returns the size of the image being displayed. + """ - if self._image is None: return (0, 0) - else: return self._image.GetSize() + if self.__image is None: return (0, 0) + else: return self.__image.GetSize() def Draw(self, ev=None): + """Draws this ``ImagePanel``. The image is scaled to the current panel + size. + """ self.ClearBackground() - if self._image is None: + if self.__image is None: return if ev is None: dc = wx.ClientDC(self) @@ -62,6 +86,6 @@ class ImagePanel(wx.PyPanel): if width == 0 or height == 0: return - bitmap = wx.BitmapFromImage(self._image.Scale(width, height)) + bitmap = wx.BitmapFromImage(self.__image.Scale(width, height)) dc.DrawBitmap(bitmap, 0, 0, False) diff --git a/fsl/fsleyes/widgets/swappanel.py b/fsl/fsleyes/widgets/swappanel.py index 6b864ed644b2bc9f4fc5a749b4d3690eae403b41..2ef34e1c891f2eaa51235cbefc54e5e8c24d3424 100644 --- a/fsl/fsleyes/widgets/swappanel.py +++ b/fsl/fsleyes/widgets/swappanel.py @@ -1,27 +1,37 @@ #!/usr/bin/env python # # swappanel.py - A wx.Panel which can contain many panels, but only displays -# one at a time. Pushing a button toggles the panel that is displayed. +# one at a time. # # Author: Paul McCarthy <pauldmccarthy@gmail.com> # +"""This module provides the :class:`SwapPanel` class, which is a +:class:`wx.PyPanel` that can contain many child panels, but only displays one +at a time. +""" import wx -import wx.lib.newevent as wxevent -_SwapPanelEvent, _EVT_SWAPPANEL_EVENT = wxevent.NewEvent() -EVT_SWAPPANEL_EVENT = _EVT_SWAPPANEL_EVENT - -SwapPanelEvent = _SwapPanelEvent +class SwapPanel(wx.PyPanel): + """The ``SwapPanel`` is a panel which can contain many cvhild panels, but + only displays one of them at a time. A button push allows the user to + change the currently displayed child panel. + """ + + def __init__(self, parent, buttonSide=wx.TOP): + """Create a ``SwapPanel``. -class SwapPanel(wx.Panel): + :arg parent: The :mod:`wx` parent object. - def __init__(self, parent, buttonSide=wx.TOP): + :arg buttonSide: Which side to put the toggle button - one of + ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, or + ``wx.RIGHT``. + """ - wx.Panel.__init__(self, parent) + wx.PyPanel.__init__(self, parent) self.__panels = [] self.__labels = [] @@ -46,14 +56,25 @@ class SwapPanel(wx.Panel): def Add(self, panel, label): + """Add a new panel to this ``SwapPanel``. + + :arg panel: The panel. + + :arg label: An identifier label for the panel - this may be passed to + the :meth:`Remove` and :meth:`Show` methods to refer to + this panel. + """ self.__panels.append(panel) self.__labels.append(label) + panel.Reparent(self) + if len(self.__panels) == 1: self.__Show(0) def Remove(self, label): + """Remove the panel with the specified ``label``. """ idx = self.__labels.index(label) self.__panels.pop(idx) @@ -61,11 +82,13 @@ class SwapPanel(wx.Panel): def Show(self, label): + """Show the panel with the specified ``label``. """ idx = self.__labels.index(label) self.__Show(idx) def __Show(self, index): + """Show the panel at the specified ``index``. """ panel = self.__panels[index] @@ -83,4 +106,5 @@ class SwapPanel(wx.Panel): def __onSwap(self, ev): + """Called when the toggle button is pushed. Shows the next panel.""" self.__Show((self.__showing + 1) % len(self.__labels)) diff --git a/fsl/fsleyes/widgets/textpanel.py b/fsl/fsleyes/widgets/textpanel.py index f1d48a1318cdc33be2cd6995aa96c5e70bc07411..76e4ddad70e6c3a521e8a325b493e040df2c051f 100644 --- a/fsl/fsleyes/widgets/textpanel.py +++ b/fsl/fsleyes/widgets/textpanel.py @@ -8,44 +8,59 @@ some text, oriented either horizontally or vertically. """ -import logging -log = logging.getLogger(__name__) import wx -class TextPanel(wx.Panel): - """A :class:`wx.Panel` which may be used to display a string of + +class TextPanel(wx.PyPanel): + """A :class:`wx.PyPanel` which may be used to display a string of text, oriented either horizotnally or vertically. """ - def __init__(self, parent, text=None, orient='horizontal'): - wx.Panel.__init__(self, parent) + def __init__(self, parent, text=None, orient=wx.HORIZONTAL): + """Create a ``TextPanel``. + + :arg parent: The :mod:`wx` parent object. + + :arg text: The text to display. This can be changed via + :meth:`SetText`. + + :arg orient: Text orientation - either ``wx.HORIZONTAL`` (the + default) or ``wx.VERTICAL``. This can be changed + later via :meth:`SetOrient`. + """ + wx.PyPanel.__init__(self, parent) self.Bind(wx.EVT_PAINT, self.Draw) - self.Bind(wx.EVT_SIZE, self._onSize) + self.Bind(wx.EVT_SIZE, self.__onSize) - self._text = text + self.__text = text self.SetOrient(orient) def SetOrient(self, orient): + """Sets the orientatino of the text on this ``TextPanel``. + + :arg orient: Either ``wx.HORIZONTAL`` or ``wx.VERTICAL``. + """ - if orient not in ('horizontal', 'vertical'): - raise RuntimeError('TextPanel orient must be ' - 'horizontal or vertical') + if orient not in (wx.HORIZONTAL, wx.VERTICAL): + raise ValueError('TextPanel orient must be ' + 'wx.HORIZONTAL or wx.VERTICAL') - self._orient = orient + self.__orient = orient # trigger re-calculation of # text extents and a refresh - self.SetText(self._text) + self.SetText(self.__text) def SetText(self, text): + """Sets the text shown on this ``TextPanel``.""" dc = wx.ClientDC(self) - self._text = text + self.__text = text if text is None: self.SetMinSize((0, 0)) @@ -56,23 +71,25 @@ class TextPanel(wx.Panel): if self._orient == 'vertical': width, height = height, width - self._textExtent = (width, height) + self.__textExtent = (width, height) self.SetMinSize((width, height)) self.Refresh() - def _onSize(self, ev): + def __onSize(self, ev): + """Called when this ``TextPanel`` is resized. Triggers a refresh. """ self.Refresh() ev.Skip() def Draw(self, ev=None): + """Draws this ``TextPanel``. """ self.ClearBackground() - if self._text is None or self._text == '': + if self.__text is None or self.__text == '': return if ev is None: dc = wx.ClientDC(self) @@ -82,12 +99,12 @@ class TextPanel(wx.Panel): return paneW, paneH = dc.GetSize().Get() - textW, textH = self._textExtent + textW, textH = self.__textExtent x = (paneW - textW) / 2.0 y = (paneH - textH) / 2.0 if self._orient == 'vertical': - dc.DrawRotatedText(self._text, x, paneH - y, 90) + dc.DrawRotatedText(self.__text, x, paneH - y, 90) else: - dc.DrawText(self._text, x, y) + dc.DrawText(self.__text, x, y) diff --git a/fsl/fsleyes/widgets/togglepanel.py b/fsl/fsleyes/widgets/togglepanel.py index 9093a1d138b9cf55428cf07b67acd5e89ec7bc07..d42d7d416df14eb18abe892231eee84fb849b638 100644 --- a/fsl/fsleyes/widgets/togglepanel.py +++ b/fsl/fsleyes/widgets/togglepanel.py @@ -6,7 +6,7 @@ # Author: Paul McCarthy <pauldmccarthy@gmail.com> # """This module provides the :class:`TogglePanel` class, which is a -:class:`wx.Panel` that contains a button and some content. Pushing +:class:`wx.PyPanel` that contains a button and some content. Pushing the button toggles the visibility of the content. """ @@ -15,32 +15,17 @@ import wx import wx.lib.newevent as wxevent -_TogglePanelEvent, _EVT_TOGGLEPANEL_EVENT = wxevent.NewEvent() - - -EVT_TOGGLEPANEL_EVENT = _EVT_TOGGLEPANEL_EVENT -"""Identifier for the :data:`TogglePanelEvent` event.""" - - -TogglePanelEvent = _TogglePanelEvent -"""Event emitted when the toggle button is pushed. Contains the -following attributes: - - - ``newState``: The new visibility state of the toggle panel - ``True`` - corresponds to visible, ``False`` to invisible. -""" - - -class TogglePanel(wx.Panel): - """A :class:`TogglePanel` is a :class:`wx.Panel` that contains +class TogglePanel(wx.PyPanel): + """A :class:`TogglePanel` is a :class:`wx.PyPanel` that contains a button and some content. Pushing the button toggles the visibility of the content. - All of the content should be added to the :class:`wx.Panel` which - is returned by the :meth:`getContentPanel` method. + All of the content should be added to the :class:`wx.PyPanel` which + is returned by the :meth:`GetContentPanel` method. """ + def __init__(self, parent, toggleSide=wx.TOP, @@ -60,7 +45,7 @@ class TogglePanel(wx.Panel): :arg label: A label to be displayed on the toggle button. """ - wx.Panel.__init__(self, parent) + wx.PyPanel.__init__(self, parent) self.__contentPanel = wx.Panel(self) @@ -86,7 +71,7 @@ class TogglePanel(wx.Panel): elif toggleSide == wx.BOTTOM: showLabel = u'\u25B2' elif toggleSide == wx.LEFT: showLabel = u'\u25B6' elif toggleSide == wx.RIGHT: showLabel = u'\u25C0' - + self.__showLabel = showLabel self.__hideLabel = hideLabel @@ -108,7 +93,7 @@ class TogglePanel(wx.Panel): self.toggle() - def toggle(self, ev=None): + def Toggle(self, ev=None): """Toggles visibility of the panel content.""" isShown = self.__sizer.IsShown(self.__contentPanel) @@ -124,8 +109,24 @@ class TogglePanel(wx.Panel): self.__contentPanel.Layout() - def getContentPanel(self): + def GetContentPanel(self): """Returns the :class:`wx.Panel` to which all content should be added. """ return self.__contentPanel + + +_TogglePanelEvent, _EVT_TOGGLEPANEL_EVENT = wxevent.NewEvent() + + +EVT_TOGGLEPANEL_EVENT = _EVT_TOGGLEPANEL_EVENT +"""Identifier for the :data:`TogglePanelEvent` event.""" + + +TogglePanelEvent = _TogglePanelEvent +"""Event emitted when the toggle button is pushed. Contains the +following attributes: + + - ``newState``: The new visibility state of the toggle panel - ``True`` + corresponds to visible, ``False`` to invisible. +"""