def _test_Create(): 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) frame = wx.GetApp().GetTopWindow() btn1 = bmpradio.BitmapRadioBox(frame) btn2 = bmpradio.BitmapRadioBox(frame, style=wx.HORIZONTAL) btn3 = bmpradio.BitmapRadioBox(frame, style=wx.VERTICAL) for btn in [btn1, btn2, btn3]: with pytest.raises(IndexError): btn.SetSelection(0) btn.Set([trueicon, falseicon]) btn.SetSelection(0) assert btn.GetSelection() == 0 btn.SetSelection(1) assert btn.GetSelection() == 1 with pytest.raises(IndexError): btn.SetSelection(-1) btn.EnableChoice(0) btn.EnableChoice(0, False) btn.DisableChoice(0) with pytest.raises(IndexError): btn.EnableChoice(2) with pytest.raises(IndexError): btn.SetSelection(2) btn.Clear() with pytest.raises(IndexError): btn.SetSelection(0) btn.AddChoice(trueicon, falseicon) btn.AddChoice(falseicon, trueicon) btn.SetSelection(0) assert btn.GetSelection() == 0 btn.SetSelection(1) assert btn.GetSelection() == 1 with pytest.raises(IndexError): btn.SetSelection(2)
def _test_Event(): falseicon = wx.Bitmap(op.join(datadir, 'false.png'), wx.BITMAP_TYPE_PNG) trueicon = wx.Bitmap(op.join(datadir, 'true.png'), wx.BITMAP_TYPE_PNG) sim = wx.UIActionSimulator() frame = wx.GetApp().GetTopWindow() panel = wx.Panel(frame) rad = bmpradio.BitmapRadioBox(panel) szr = wx.BoxSizer(wx.HORIZONTAL) szr.Add(rad, flag=wx.EXPAND) panel.SetSizer(szr) result = [None] def handler(ev): result[0] = (ev.index, ev.clientData) rad.Bind(bmpradio.EVT_BITMAP_RADIO_EVENT, handler) rad.Set([trueicon, falseicon], ['true', 'false']) panel.Layout() panel.Fit() wx.Yield() btns = [] for c in rad.GetChildren(): if isinstance(c, bmptoggle.BitmapToggleButton): btns.append(c) simclick(sim, btns[0]) assert result[0] == (0, 'true') simclick(sim, btns[1]) assert result[0] == (1, 'false')
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 _booleanRadio(parent, icons, style): """Create a :class:`.BitmapRadioBox` to link to the :class:`.Boolean` property. """ widget = bmpradio.BitmapRadioBox(parent, style) event = bmpradio.EVT_BITMAP_RADIO_EVENT widget.SetMinSize(widget.GetBestSize()) if len(icons) == 2: icons = [icons[0], None, icons[1], None] widget.AddChoice(icons[0], unselectedBmp=icons[1]) widget.AddChoice(icons[2], unselectedBmp=icons[3]) def wget(): return widget.GetSelection() == 0 def wset(val): if val: widget.SetSelection(0) else: widget.SetSelection(1) return widget, event, wget, wset
def _Choice(parent, hasProps, propObj, propVal, labels=None, icons=None, fixChoices=None, style=None, **kwargs): """Creates and returns a widget allowing the user to modify the given :class:`.Choice` property value. By default, ``wx.Choice`` widget is used. However, if the ``icons`` argument is specified, a :class:`.BitmapRadioBox` is used instead. :arg labels: A dict of ``{choice : label}`` mappings, specifying the label to be displayed for each choice. If not provided, the string representation of each choice is used. Not used if the ``icons`` argument is specified. .. note:: If the ``Choice`` property is dynamic (i.e. choices are going to be added/removed during program execution), you must ensure that the ``labels`` dictionary contains a value for all possible choices, not just the initial choices. As an alternative to passing in a ``dict``, you may also set ``labels`` to a function. In this case, the ``labels`` function must accept a single choice value as its only argument, and return a label for that choice. :arg icons: If provided, a :class:`.BitmapRadioBox` is used instead of a ``wx.Choice`` widget. The ``icons`` should be a dictionary of ``{ choice : imageFile}`` mappings, containing an icon files to be used for each choice. The ``icons`` dictionary may alternately contain ``{ choice : (selectedImageFile, unselectedImageFile) }`` mappings, which specifies separate icons to be used when the corresponding choice is selected or not selected. :arg fixChoices: If provided, must be a sequence of valid choice values. If provided, the widget will be limited to displaying only these choices. All other possible choice values will be ignored. :arg style: Passed through to the :meth:`.BitmapRadioBox.__init__` method. Not used if no ``icons`` were provided. See the :func:`.widgets._String` documentation for details on the other parameters. """ # A reference to the choices - this is # shared by the inner functions defined # below, and updated in choicesChanged choices = [propObj.getChoices(hasProps)] # If fixChoices is provided, the choices # are fixed (and the fixChoices variable # is turned into a boolean). if fixChoices is not None: choices = [list(fixChoices)] fixChoices = True # If we have been given some icons, we will use # a BitmapRadioBox, which has a toggle button # for each choice if icons is not None: event = bmpradio.EVT_BITMAP_RADIO_EVENT widget = bmpradio.BitmapRadioBox(parent, style=style) # Otherwise we use a regular drop down # box, via the wx.Choice widget. else: event = wx.EVT_CHOICE widget = wx.Choice(parent) # Under linux/GTK, choice widgets absorb # mousewheel events. I don't want this. if wx.Platform == '__WXGTK__': def wheel(ev): widget.GetParent().GetEventHandler().ProcessEvent(ev) widget.Bind(wx.EVT_MOUSEWHEEL, wheel) # When the widget value changes, # return the corresponding choice # value def widgetGet(): if len(choices[0]) > 0: return choices[0][widget.GetSelection()] else: return None # When the property value changes, # update the widget value def widgetSet(value): log.debug('Updating widget value: {}'.format(value)) if len(choices[0]) > 0: return widget.SetSelection(choices[0].index(value)) else: return None # Update the combobox choices # when they change. def choicesChanged(ctx, name, *a): if name not in ('choices', 'choiceEnabled'): return if not fixChoices: choices[0] = propObj.getChoices(hasProps) curLabels = [] if labels is None: curLabels = [str(c) for c in choices[0]] # labels can either be a dict # of {choice : label} mappings elif isinstance(labels, dict): curLabels = [labels[c] for c in choices[0]] # or a function which, given a # choice, returns a label for it else: curLabels = [labels(c) for c in choices[0]] # If we're using a wx.Choice widget, remove # any disabled choices from the list. # It would be nice if wx.Choice allowed # us to enable/disable individual items, but # it doesn't, so our only option is to hide # the disabled ones. if icons is None: for ci, choice in enumerate(choices[0]): if not propObj.choiceEnabled(choice, hasProps): curLabels.pop(ci) log.debug('Updating options for Widget ' '{} ({}) from {}.{} ({}): {}'.format( widget.__class__.__name__, id(widget), hasProps.__class__.__name__, propVal._name, id(hasProps), curLabels)) if icons is None: widget.Set(list(curLabels)) else: widget.Clear() # If using a BitmapRadio widget, we can # show all choices, but disable the # buttons for disabled choices for ci, choice in enumerate(choices[0]): choiceIcons = icons[choice] if not isinstance(choiceIcons, (tuple, list)): choiceIcons = [choiceIcons] else: choiceIcons = list(choiceIcons) # Load the image file for each choice # if they have not already been loaded for cii, icon in enumerate(choiceIcons): if isinstance(icon, str): choiceIcons[cii] = wx.Bitmap(icon, type=wx.BITMAP_TYPE_PNG) # Only one bitmap specified - add # a placeholder for the unselected # bitmap if len(choiceIcons) == 1: choiceIcons = choiceIcons + [None] # Replace the mapping in the # icon dict with the bitmaps icons[choice] = choiceIcons selBmp, deselBmp = choiceIcons widget.AddChoice(selBmp, deselBmp) if not propObj.choiceEnabled(choice, hasProps): widget.DisableChoice(ci) # Make sure the widget # selection is up to date if len(choices[0]) > 0: widget.SetSelection(choices[0].index(propVal.get())) listenerName = 'WidgetChoiceUpdate_{}'.format(id(widget)) propVal.addAttributeListener(listenerName, choicesChanged, weak=False) # Initialise the widget choicesChanged(None, 'choices') widgetSet(propVal.get()) widget.SetMinSize(widget.GetBestSize()) def onDestroy(ev): log.debug('Removing attribute listener {}'.format(listenerName)) propVal.removeAttributeListener(listenerName) widgets._propBind(hasProps, propObj, propVal, widget, event, widgetGet=widgetGet, widgetSet=widgetSet, widgetDestroy=onDestroy) return widget