import types import Tkinter import Pmw class RadioSelect(Pmw.MegaWidget): # A collection of several buttons. In single mode, only one # button may be selected. In multiple mode, any number of buttons # may be selected. def __init__(self, parent = None, **kw): # Define the megawidget options. INITOPT = Pmw.INITOPT optiondefs = ( ('buttontype', 'button', INITOPT), ('command', None, None), ('labelmargin', 0, INITOPT), ('labelpos', None, INITOPT), ('orient', 'horizontal', INITOPT), ('padx', 5, INITOPT), ('pady', 5, INITOPT), ('selectmode', 'single', INITOPT), ) self.defineoptions(kw, optiondefs) # Initialise the base class (after defining the options). Pmw.MegaWidget.__init__(self, parent) # Create the components. interior = self.interior() if self['labelpos'] is None: self._radioSelectFrame = self._hull else: self._radioSelectFrame = self.createcomponent('frame', (), None, Tkinter.Frame, (interior,)) self._radioSelectFrame.grid(column=2, row=2, sticky='nsew') interior.grid_columnconfigure(2, weight=1) interior.grid_rowconfigure(2, weight=1) self.createlabel(interior) # Initialise instance variables. self._buttonList = [] if self['selectmode'] == 'single': self._singleSelect = 1 elif self['selectmode'] == 'multiple': self._singleSelect = 0 else: raise ValueError, 'bad selectmode option "' + \ self['selectmode'] + '": should be single or multiple' if self['buttontype'] == 'button': self.buttonClass = Tkinter.Button elif self['buttontype'] == 'radiobutton': self._singleSelect = 1 self.var = Tkinter.StringVar() self.buttonClass = Tkinter.Radiobutton elif self['buttontype'] == 'checkbutton': self._singleSelect = 0 self.buttonClass = Tkinter.Checkbutton else: raise ValueError, 'bad buttontype option "' + \ self['buttontype'] + \ '": should be button, radiobutton or checkbutton' if self._singleSelect: self.selection = None else: self.selection = [] if self['orient'] not in ('horizontal', 'vertical'): raise ValueError, 'bad orient option ' + repr(self['orient']) + \ ': must be either \'horizontal\' or \'vertical\'' # Check keywords and initialise options. self.initialiseoptions(RadioSelect) def getcurselection(self): return self.selection def numbuttons(self): return len(self._buttonList) def index(self, index): # Return the integer index of the button with the given index. listLength = len(self._buttonList) if type(index) == types.IntType: if index < listLength: return index else: raise ValueError, 'index "%s" is out of range' % index elif index == 'end': if listLength > 0: return listLength - 1 else: raise ValueError, 'RadioSelect has no buttons' else: for count in range(listLength): name = self._buttonList[count] if index == name: return count validValues = 'number, end or a name' raise ValueError, \ 'bad index "%s": must be %s' % (index, validValues) def add(self, name, **kw): if name in self._buttonList: raise ValueError, 'name "%s" already exists' % name kw['command'] = lambda self=self, name=name: self.invoke(name) if not kw.has_key('text'): kw['text'] = name if self['buttontype'] == 'radiobutton': if not kw.has_key('anchor'): kw['anchor'] = 'w' if not kw.has_key('variable'): kw['variable'] = self.var if not kw.has_key('value'): kw['value'] = kw['text'] elif self['buttontype'] == 'checkbutton': if not kw.has_key('anchor'): kw['anchor'] = 'w' button = apply(self.createcomponent, (name, (), 'Button', self.buttonClass, (self._radioSelectFrame,)), kw) if self['orient'] == 'horizontal': self._radioSelectFrame.grid_rowconfigure(0, weight=1) col = len(self._buttonList) button.grid(column=col, row=0, padx = self['padx'], pady = self['pady'], sticky='nsew') self._radioSelectFrame.grid_columnconfigure(col, weight=1) else: self._radioSelectFrame.grid_columnconfigure(0, weight=1) row = len(self._buttonList) button.grid(column=0, row=row, padx = self['padx'], pady = self['pady'], sticky='ew') self._radioSelectFrame.grid_rowconfigure(row, weight=1) self._buttonList.append(name) return button def deleteall(self): for name in self._buttonList: self.destroycomponent(name) self._buttonList = [] if self._singleSelect: self.selection = None else: self.selection = [] def invoke(self, index): index = self.index(index) name = self._buttonList[index] if self._singleSelect: self.selection = name if self['buttontype'] == 'radiobutton': widget = self.component(name) widget.select() else: for button in self._buttonList: widget = self.component(button) if button == name: widget.configure(relief='sunken') else: widget.configure(relief='raised') command = self['command'] if callable(command): return command(name) else: # Multiple selections widget = self.component(name) if name in self.selection: if self['buttontype'] == 'checkbutton': widget.deselect() else: widget.configure(relief='raised') self.selection.remove(name) state = 0 else: if self['buttontype'] == 'checkbutton': widget.select() else: widget.configure(relief='sunken') self.selection.append(name) state = 1 command = self['command'] if callable(command): return command(name, state)