1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
import types
import Tkinter
import Pmw
import sys
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):
# python version check
# python versions >= 2.5.4 automatically clean commands
# and manually cleaning them causes errors when deleting items
if sys.version_info[0] * 100 + sys.version_info[1] * 10 + \
sys.version_info[2] < 254:
# 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)
|