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)