Commit 610169e6 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'enh/bmpradio' into 'master'

Enh/bmpradio

See merge request fsl/fsleyes/widgets!68
parents 484a14dc 72288d32
......@@ -2,6 +2,18 @@ This document contains the ``fsleyes-widgets`` release history in reverse
chronological order.
0.11.2 (Saturday March 27th 2021)
---------------------------------
Changed
^^^^^^^
* The :class:`.BitmapRadioBox` now allows all items to be de-selected,
by using the :attr:`.BMPRADIO_ALLOW_DESELECTED` style.
0.11.1 (Tuesday March 9th 2021)
-------------------------------
......
......@@ -41,8 +41,9 @@ class BitmapRadioBox(wx.Panel):
:arg parent: A parent window.
:arg style: Either ``wx.HORIZONTAL`` (the default) or ``wx.VERTICAL``,
to control the button layout direction.
: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)
......@@ -52,14 +53,23 @@ class BitmapRadioBox(wx.Panel):
if style & wx.VERTICAL: szorient = wx.VERTICAL
else: szorient = wx.HORIZONTAL
self.__selection = -1
self.__buttons = []
self.__clientData = []
self.__sizer = wx.BoxSizer(szorient)
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)
def AddChoice(self, selectedBmp, unselectedBmp=None, clientData=None):
"""Add a button to this ``BitmapRadioBox``.
......@@ -81,12 +91,12 @@ class BitmapRadioBox(wx.Panel):
self.__buttons .append(button)
self.__clientData.append(clientData)
self.__sizer.Add(button, flag=wx.EXPAND)
self.__sizer.Add(button, flag=wx.EXPAND, proportion=1)
self.Layout()
button.Bind(bitmaptoggle.EVT_BITMAP_TOGGLE, self.__onButton)
if self.__selection == -1:
if (not self.__allowDeselected) and (self.__selection == -1):
self.SetSelection(0)
......@@ -134,7 +144,10 @@ class BitmapRadioBox(wx.Panel):
def SetSelection(self, index):
"""Sets the current selection."""
if index < 0 or index >= len(self.__buttons):
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
......@@ -150,12 +163,25 @@ class BitmapRadioBox(wx.Panel):
and emits a :data:`BitmapRadioEvent`.
"""
idx = self.__buttons.index(ev.GetEventObject())
data = self.__clientData[idx]
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)
self.SetSelection(idx)
ev = BitmapRadioEvent(index=idx, clientData=data, value=value)
wx.PostEvent(self, ev)
wx.PostEvent(self, BitmapRadioEvent(index=idx, clientData=data))
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()
......@@ -171,4 +197,7 @@ 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.
"""
......@@ -46,6 +46,9 @@ def _test_Create():
btn.SetSelection(1)
assert btn.GetSelection() == 1
with pytest.raises(IndexError):
btn.SetSelection(-1)
btn.EnableChoice(0)
btn.EnableChoice(0, False)
btn.DisableChoice(0)
......@@ -72,6 +75,49 @@ def _test_Create():
btn.SetSelection(2)
def test_allow_deselected():
run_with_wx(_test_allow_deselected)
def _test_allow_deselected():
falseicon = op.join(datadir, 'false.png')
trueicon = op.join(datadir, 'true.png')
falseicon = wx.Bitmap(falseicon, wx.BITMAP_TYPE_PNG)
trueicon = wx.Bitmap(trueicon, wx.BITMAP_TYPE_PNG)
sim = wx.UIActionSimulator()
frame = wx.GetApp().GetTopWindow()
panel = wx.Panel(frame)
szr = wx.BoxSizer(wx.HORIZONTAL)
rad = bmpradio.BitmapRadioBox(
panel, style=bmpradio.BMPRADIO_ALLOW_DESELECTED)
rad.Set([trueicon, falseicon])
szr.Add(rad, flag=wx.EXPAND)
panel.SetSizer(szr)
panel.Layout()
panel.Fit()
realYield()
assert rad.GetSelection() == -1
rad.SetSelection(1)
assert rad.GetSelection() == 1
rad.SetSelection(-1)
assert rad.GetSelection() == -1
btns = rad.buttons
simclick(sim, btns[0])
realYield()
assert rad.GetSelection() == 0
simclick(sim, btns[0])
realYield()
assert rad.GetSelection() == -1
simclick(sim, btns[1])
realYield()
assert rad.GetSelection() == 1
simclick(sim, btns[1])
realYield()
assert rad.GetSelection() == -1
def test_Event():
run_with_wx(_test_Event)
def _test_Event():
......@@ -99,10 +145,7 @@ def _test_Event():
panel.Fit()
realYield()
btns = []
for c in rad.GetChildren():
if isinstance(c, bmptoggle.BitmapToggleButton):
btns.append(c)
btns = rad.buttons
simclick(sim, btns[0])
assert result[0] == (0, 'true')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment