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 = ( ('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.selection = None elif self['selectmode'] == 'multiple': self.selection = [] else: raise ValueError, 'bad selectmode option "' + \ self['selectmode'] + '": should be single or multiple' # 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) == type(1): 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 button = apply(self.createcomponent, (name, (), 'Button', Tkinter.Button, (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['selectmode'] == 'single': self.selection = None else: self.selection = [] def invoke(self, index): index = self.index(index) name = self._buttonList[index] if self['selectmode'] == 'single': for button in self._buttonList: if button == name: self.component(button).configure(relief='sunken') else: self.component(button).configure(relief='raised') self.selection = name command = self['command'] if callable(command): return command(name) else: # Multiple selections allowed if name in self.selection: self.component(name).configure(relief='raised') self.selection.remove(name) state = 0 else: self.component(name).configure(relief='sunken') self.selection.append(name) state = 1 command = self['command'] if callable(command): return command(name, state)