You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
5.6 KiB

import wx
from gooey.gui.components.widgets.bases import BaseWidget
from gooey.gui.lang.i18n import _
from gooey.gui.util import wx_util
from gooey.gui.components.widgets import CheckBox
from gooey.util.functional import getin, findfirst, merge
class RadioGroup(BaseWidget):
def __init__(self, parent, widgetInfo, *args, **kwargs):
super(RadioGroup, self).__init__(parent, *args, **kwargs)
self._parent = parent
self.info = widgetInfo
self._id = widgetInfo['id']
self._options = widgetInfo['options']
self.widgetInfo = widgetInfo
self.error = wx.StaticText(self, label='')
self.radioButtons = self.createRadioButtons()
self.selected = None
self.widgets = self.createWidgets()
self.arrange()
self.applyStyleRules()
for button in self.radioButtons:
button.Bind(wx.EVT_LEFT_DOWN, self.handleButtonClick)
initialSelection = getin(self.info, ['options', 'initial_selection'], None)
if initialSelection is not None:
self.selected = self.radioButtons[initialSelection]
self.selected.SetValue(True)
self.handleImplicitCheck()
def getValue(self):
for button, widget in zip(self.radioButtons, self.widgets):
if button.GetValue(): # is Checked
return merge(widget.getValue(), {'id': self._id})
else:
# just return the first widget's value even though it's
# not active so that the expected interface is satisfied
return self.widgets[0].getValue()
def setErrorString(self, message):
for button, widget in zip(self.radioButtons, self.widgets):
if button.GetValue(): # is Checked
widget.setErrorString(message)
self.Layout()
def showErrorString(self, b):
for button, widget in zip(self.radioButtons, self.widgets):
if button.GetValue(): # is Checked
widget.showErrorString(b)
def arrange(self, *args, **kwargs):
title = getin(self.widgetInfo, ['options', 'title'], _('choose_one'))
if getin(self.widgetInfo, ['options', 'show_border'], False):
boxDetails = wx.StaticBox(self, -1, title)
boxSizer = wx.StaticBoxSizer(boxDetails, wx.VERTICAL)
else:
title = wx_util.h1(self, title)
title.SetForegroundColour(self._options['label_color'])
boxSizer = wx.BoxSizer(wx.VERTICAL)
boxSizer.AddSpacer(10)
boxSizer.Add(title, 0)
for btn, widget in zip(self.radioButtons, self.widgets):
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(btn,0, wx.RIGHT, 4)
sizer.Add(widget, 1, wx.EXPAND)
boxSizer.Add(sizer, 0, wx.ALL | wx.EXPAND, 5)
self.SetSizer(boxSizer)
def handleButtonClick(self, event):
currentSelection = self.selected
nextSelection = event.EventObject
if not self.isSameRadioButton(currentSelection, nextSelection):
self.selected = nextSelection
self.selected.SetValue(True)
else:
# user clicked on an already enabled radio button.
# if it is not in the required section, allow it to be deselected
if not self.widgetInfo['required']:
self.selected.SetValue(False)
self.applyStyleRules()
self.handleImplicitCheck()
def isSameRadioButton(self, radioButton1, radioButton2):
return (getattr(radioButton1, 'Id', 'r1-not-found') ==
getattr(radioButton2, 'Id', 'r2-not-found'))
def applyStyleRules(self):
"""
Conditionally disabled/enables form fields based on the current
section in the radio group
"""
for button, widget in zip(self.radioButtons, self.widgets):
if isinstance(widget, CheckBox):
widget.hideInput()
if not button.GetValue(): # not checked
widget.widget.Disable()
else:
widget.widget.Enable()
def handleImplicitCheck(self):
"""
Checkboxes are hidden when inside of a RadioGroup as a selection of
the Radio button is an implicit selection of the Checkbox. As such, we have
to manually "check" any checkbox as needed.
"""
for button, widget in zip(self.radioButtons, self.widgets):
if isinstance(widget, CheckBox):
if button.GetValue(): # checked
widget.setValue(True)
else:
widget.setValue(False)
def createRadioButtons(self):
# button groups in wx are statefully determined via a style flag
# on the first button (what???). All button instances are part of the
# same group until a new button is created with the style flag RG_GROUP
# https://wxpython.org/Phoenix/docs/html/wx.RadioButton.html
# (What???)
firstButton = wx.RadioButton(self, style=wx.RB_GROUP)
firstButton.SetValue(False)
buttons = [firstButton]
for _ in getin(self.widgetInfo, ['data','widgets'], [])[1:]:
buttons.append(wx.RadioButton(self))
return buttons
def createWidgets(self):
"""
Instantiate the Gooey Widgets that are used within the RadioGroup
"""
from gooey.gui.components import widgets
return [getattr(widgets, item['type'])(self, item)
for item in getin(self.widgetInfo, ['data', 'widgets'], [])]