146 lines
3.9 KiB
Python
146 lines
3.9 KiB
Python
import types
|
|
import Tkinter
|
|
import Pmw
|
|
|
|
class OptionMenu(Pmw.MegaWidget):
|
|
|
|
def __init__(self, parent = None, **kw):
|
|
|
|
# Define the megawidget options.
|
|
INITOPT = Pmw.INITOPT
|
|
optiondefs = (
|
|
('command', None, None),
|
|
('items', (), INITOPT),
|
|
('initialitem', None, INITOPT),
|
|
('labelmargin', 0, INITOPT),
|
|
('labelpos', None, INITOPT),
|
|
('sticky', 'ew', INITOPT),
|
|
)
|
|
self.defineoptions(kw, optiondefs)
|
|
|
|
# Initialise the base class (after defining the options).
|
|
Pmw.MegaWidget.__init__(self, parent)
|
|
|
|
# Create the components.
|
|
interior = self.interior()
|
|
|
|
self._menubutton = self.createcomponent('menubutton',
|
|
(), None,
|
|
Tkinter.Menubutton, (interior,),
|
|
borderwidth = 2,
|
|
indicatoron = 1,
|
|
relief = 'raised',
|
|
anchor = 'c',
|
|
highlightthickness = 2,
|
|
direction = 'flush',
|
|
takefocus = 1,
|
|
)
|
|
self._menubutton.grid(column = 2, row = 2, sticky = self['sticky'])
|
|
|
|
self._menu = self.createcomponent('menu',
|
|
(), None,
|
|
Tkinter.Menu, (self._menubutton,),
|
|
tearoff=0
|
|
)
|
|
self._menubutton.configure(menu = self._menu)
|
|
|
|
interior.grid_columnconfigure(2, weight = 1)
|
|
interior.grid_rowconfigure(2, weight = 1)
|
|
|
|
# Create the label.
|
|
self.createlabel(interior)
|
|
|
|
# Add the items specified by the initialisation option.
|
|
self._itemList = []
|
|
self.setitems(self['items'], self['initialitem'])
|
|
|
|
# Check keywords and initialise options.
|
|
self.initialiseoptions()
|
|
|
|
def setitems(self, items, index = None):
|
|
|
|
# Clean up old items and callback commands.
|
|
for oldIndex in range(len(self._itemList)):
|
|
tclCommandName = str(self._menu.entrycget(oldIndex, 'command'))
|
|
if tclCommandName != '':
|
|
self._menu.deletecommand(tclCommandName)
|
|
self._menu.delete(0, 'end')
|
|
self._itemList = list(items)
|
|
|
|
# Set the items in the menu component.
|
|
for item in items:
|
|
self._menu.add_command(label = item,
|
|
command = lambda self = self, item = item: self._invoke(item))
|
|
|
|
# Set the currently selected value.
|
|
if index is None:
|
|
var = str(self._menubutton.cget('textvariable'))
|
|
if var != '':
|
|
# None means do not change text variable.
|
|
return
|
|
if len(items) == 0:
|
|
text = ''
|
|
elif str(self._menubutton.cget('text')) in items:
|
|
# Do not change selection if it is still valid
|
|
return
|
|
else:
|
|
text = items[0]
|
|
else:
|
|
index = self.index(index)
|
|
text = self._itemList[index]
|
|
|
|
self.setvalue(text)
|
|
|
|
def getcurselection(self):
|
|
var = str(self._menubutton.cget('textvariable'))
|
|
if var == '':
|
|
return str(self._menubutton.cget('text'))
|
|
else:
|
|
return self._menu.tk.globalgetvar(var)
|
|
|
|
def getvalue(self):
|
|
return self.getcurselection()
|
|
|
|
def setvalue(self, text):
|
|
var = str(self._menubutton.cget('textvariable'))
|
|
if var == '':
|
|
self._menubutton.configure(text = text)
|
|
else:
|
|
self._menu.tk.globalsetvar(var, text)
|
|
|
|
def index(self, index):
|
|
listLength = len(self._itemList)
|
|
if type(index) == types.IntType:
|
|
if index < listLength:
|
|
return index
|
|
else:
|
|
raise ValueError, 'index "%s" is out of range' % index
|
|
elif index is Pmw.END:
|
|
if listLength > 0:
|
|
return listLength - 1
|
|
else:
|
|
raise ValueError, 'OptionMenu has no items'
|
|
else:
|
|
if index is Pmw.SELECT:
|
|
if listLength > 0:
|
|
index = self.getcurselection()
|
|
else:
|
|
raise ValueError, 'OptionMenu has no items'
|
|
if index in self._itemList:
|
|
return self._itemList.index(index)
|
|
raise ValueError, \
|
|
'bad index "%s": must be a ' \
|
|
'name, a number, Pmw.END or Pmw.SELECT' % (index,)
|
|
|
|
def invoke(self, index = Pmw.SELECT):
|
|
index = self.index(index)
|
|
text = self._itemList[index]
|
|
|
|
return self._invoke(text)
|
|
|
|
def _invoke(self, text):
|
|
self.setvalue(text)
|
|
|
|
command = self['command']
|
|
if callable(command):
|
|
return command(text)
|