Source code for fsleyes_widgets.bitmapradio

#!/usr/bin/env python
#
# bitmapradio.py - A radio control with bitmap buttons.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`BitmapRadioBox` class, a radio control
which uses bitmap toggle buttons.
"""

import wx
import wx.lib.newevent as wxevent

from . import bitmaptoggle


# TODO Button tooltips


[docs] class BitmapRadioBox(wx.Panel): """A radio control which displays a collection of :class:`wx.ToggleButton` controls, each of which displays an image. Each of these buttons corresponds to a mutually exclusive option - when the user clicks on a button, it is toggled *on*, and all of the others are toggled *off*. For example, here is a ``BitmapRadioBox`` which allows the user to switch between *view* mode and *edit* mode: .. image:: images/bitmapradiobox.png :scale: 50% :align: center When the user pushes a button, a :data:`EVT_BITMAP_RADIO_EVENT` is generated. """ def __init__(self, parent, style=None): """Create a ``BitmapRadioBox``. :arg parent: A parent window. :arg style: A combination of :attr:`BMPRADIO_ALLOW_DESELECTED`, and one of ``wx.HORIZONTAL`` (the default) or ``wx.VERTICAL``, to control the button layout direction """ wx.Panel.__init__(self, parent) if style is None: style = wx.HORIZONTAL if style & wx.VERTICAL: szorient = wx.VERTICAL else: szorient = wx.HORIZONTAL self.__allowDeselected = style & BMPRADIO_ALLOW_DESELECTED self.__selection = -1 self.__buttons = [] self.__clientData = [] self.__sizer = wx.BoxSizer(szorient) self.SetSizer(self.__sizer) @property def buttons(self): """Returns a list containing the :class:`.BitmapToggleButton` instances. Used for testing. """ return list(self.__buttons)
[docs] def AddChoice(self, selectedBmp, unselectedBmp=None, clientData=None): """Add a button to this ``BitmapRadioBox``. :arg selectedBmp: A :class:`wx.Bitmap` to display on the button when it is selected. :arg unselectedBmp: Optional. A :class:`wx.Bitmap` to display on the button when it is not selected. :arg clientData: Arbitrary data which is associated with the choice. """ style = wx.BU_EXACTFIT | wx.ALIGN_CENTRE | wx.BU_NOTEXT button = bitmaptoggle.BitmapToggleButton(self, trueBmp=selectedBmp, falseBmp=unselectedBmp, style=style) self.__buttons .append(button) self.__clientData.append(clientData) self.__sizer.Add(button, flag=wx.EXPAND, proportion=1) self.Layout() button.Bind(bitmaptoggle.EVT_BITMAP_TOGGLE, self.__onButton) if (not self.__allowDeselected) and (self.__selection == -1): self.SetSelection(0)
[docs] def Clear(self): """Remove all buttons from this ``BitmapRadioBox``.""" self.__sizer.Clear(True) self.__selection = -1 self.__buttons = [] self.__clientData = []
[docs] def EnableChoice(self, index, enable=True): """Enable or disable the button at the specified index. """ self.__buttons[index].Enable(enable)
[docs] def DisableChoice(self, index=None): """Disable the button at the specified index. """ self.EnableChoice(index, False)
[docs] def Set(self, bitmaps, clientData=None): """Set all buttons at once. :arg bitmaps: A list of :class:`wx.Bitmap` objects. :arg clientData: A list of arbitrary data to associate with each choice. """ if clientData is None: clientData = [None] * len(bitmaps) self.Clear() for bmp, cd in zip(bitmaps, clientData): self.AddChoice(bmp, clientData=cd)
[docs] def GetSelection(self): """Returns the index of the curently selected choice.""" return self.__selection
[docs] def SetSelection(self, index): """Sets the current selection.""" if index < -1 or index >= len(self.__buttons): raise IndexError('Invalid index {}'.format(index)) if (not self.__allowDeselected) and (index == -1): raise IndexError('Invalid index {}'.format(index)) self.__selection = index for i, button in enumerate(self.__buttons): if i == index: button.SetValue(True) else: button.SetValue(False)
def __onButton(self, ev): """Called when a button is pushed. Updates the selection, and emits a :data:`BitmapRadioEvent`. """ button = ev.GetEventObject() idx = self.__buttons.index(button) data = self.__clientData[idx] if self.__allowDeselected and (idx == self.GetSelection()): value = False self.SetSelection(-1) else: value = True self.SetSelection(idx) ev = BitmapRadioEvent(index=idx, clientData=data, value=value) wx.PostEvent(self, ev)
BMPRADIO_ALLOW_DESELECTED = 1 """Style flag which allows all buttons to be de-selected. If not specified (the default), one button must always be selected. """ _BitampRadioEvent, _EVT_BITMAP_RADIO_EVENT = wxevent.NewEvent() EVT_BITMAP_RADIO_EVENT = _EVT_BITMAP_RADIO_EVENT """Identifier for the :data:`BitmapRadioEvent`. """ BitmapRadioEvent = _BitampRadioEvent """Event emitted when the user changes the radio selection. Contains the following attributes: - ``index``: The index of the new selection. - ``clientData``: Client data associated with the new selection. - ``value``: ``False`` if :attr:`BMPRADIO_ALLOW_DESELECTED` is active, and the selected button was clicked on (thus deselecting it), ``True`` otherwise. """