#
# Widget implementing functionality similar to that of OptionMenu widget
#
# The widget defines two components: label and menu, menu being Tkinter's
# OptionMenu
#
# The public methods are:
#
# get() - returns the current selection
# index(name) - returns the integer index of the item 'name'
# setitems(items, active = None)
# - set's the list of items displayed, selects the item indexed
# by 'active' as active (calls the callback too). Otherwise,
# first item in the list is selected.
# select(index) - selects the item indexed by index. If command option is given,
# the command is called
#
# If an option 'variable' is given, the current value of the menu will be
# available via the variable.
#
# Author Roman Sulzhyk
#
import Tkinter, Pmw
import string
# Dummy callback
class _dummy:
def __init__(self, f, pars):
self.f, self.pars = f, pars
def __call__(self):
apply ( self.f, (self.pars, ) )
class OptionMenu(Pmw.MegaWidget):
def __init__(self, parent = None, **kw):
# Define the megawidget options.
INITOPT = Pmw.INITOPT
optiondefs = (
('labelmargin', 0, INITOPT),
('labelpos', None, INITOPT),
('selectioncommand', '', None),
('items', [], INITOPT ),
('variable', Tkinter.StringVar(''), INITOPT ),
('command', None, None ),
('direction', 'flush', INITOPT ),
)
self.defineoptions(kw, optiondefs)
# Initialise the base class (after defining the options).
Pmw.MegaWidget.__init__(self, parent)
# Check that the direction is valid
dirs = [ 'left', 'right', 'above', 'below', 'flush' ]
if self['direction'] not in dirs:
raise ValueError, 'direction is %s, should be one of : %s' % \
( self['direction'], string.join ( dirs, ', ' ))
# A nuisance inherited from OptionMenu
if not len(self['items']):
raise ValueError, 'items must be a non-empty list'
interior = self.interior()
# Create OptionMenu
self._optionmenu = self.createcomponent('menu',
(), None,
Tkinter.OptionMenu, (interior, self['variable'],
self['items'][0], self['items'][1:]),
)
self._optionmenu.configure ( direction = self['direction'],)
self._optionmenu.grid ( row = 2, column = 2, sticky='nsew')
interior.grid_columnconfigure ( 2, weight = 1)
interior.grid_rowconfigure ( 2, weight = 1)
# Create the label.
self.createlabel(interior)
# Re-set the items to register proper callback
self.setitems ( self['items'] )
# Check keywords and initialise options.
self.initialiseoptions(OptionMenu)
#======================================================================
# Public methods
def get ( self ):
"Return the name of the menu item currently selected"
return self['variable'].get()
def setitems ( self, items, active = None ):
"Set the list of items to be displayed"
m = self._optionmenu['menu']
m.delete ( 0, 'end' )
for i in items:
m.add_command ( label = i, command = _dummy ( self._callback, i ))
if active:
self.select(active)
else:
self.select(items[0])
def index ( self, name ):
"Return integer index of item with name 'name'"
return self._optionmenu['menu'].index(name)
def select ( self, index ):
"Select the item with index"
ind = self.index ( index )
val = self._optionmenu['menu'].entrycget(ind, 'label')
self['variable'].set(val)
# Note that the callback is called:
if callable ( self['command'] ):
apply ( self['command'], (val, ) )
#======================================================================
# Private methods
def _callback ( self, tag ):
"Called when user selects an item"
self['variable'].set(tag)
if callable ( self['command'] ):
apply ( self['command'], (tag, ) )