Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | import types |
2 | import Tkinter | |
3 | import Pmw | |
4 | ||
5 | class OptionMenu(Pmw.MegaWidget): | |
6 | ||
7 | def __init__(self, parent = None, **kw): | |
8 | ||
9 | # Define the megawidget options. | |
10 | INITOPT = Pmw.INITOPT | |
11 | optiondefs = ( | |
12 | ('command', None, None), | |
13 | ('items', (), INITOPT), | |
14 | ('initialitem', None, INITOPT), | |
15 | ('labelmargin', 0, INITOPT), | |
16 | ('labelpos', None, INITOPT), | |
17 | ('sticky', 'ew', INITOPT), | |
18 | ) | |
19 | self.defineoptions(kw, optiondefs) | |
20 | ||
21 | # Initialise the base class (after defining the options). | |
22 | Pmw.MegaWidget.__init__(self, parent) | |
23 | ||
24 | # Create the components. | |
25 | interior = self.interior() | |
26 | ||
27 | self._menubutton = self.createcomponent('menubutton', | |
28 | (), None, | |
29 | Tkinter.Menubutton, (interior,), | |
30 | borderwidth = 2, | |
31 | indicatoron = 1, | |
32 | relief = 'raised', | |
33 | anchor = 'c', | |
34 | highlightthickness = 2, | |
35 | direction = 'flush', | |
36 | takefocus = 1, | |
37 | ) | |
38 | self._menubutton.grid(column = 2, row = 2, sticky = self['sticky']) | |
39 | ||
40 | self._menu = self.createcomponent('menu', | |
41 | (), None, | |
42 | Tkinter.Menu, (self._menubutton,), | |
43 | tearoff=0 | |
44 | ) | |
45 | self._menubutton.configure(menu = self._menu) | |
46 | ||
47 | interior.grid_columnconfigure(2, weight = 1) | |
48 | interior.grid_rowconfigure(2, weight = 1) | |
49 | ||
50 | # Create the label. | |
51 | self.createlabel(interior) | |
52 | ||
53 | # Add the items specified by the initialisation option. | |
54 | self._itemList = [] | |
55 | self.setitems(self['items'], self['initialitem']) | |
56 | ||
57 | # Check keywords and initialise options. | |
58 | self.initialiseoptions() | |
59 | ||
60 | def setitems(self, items, index = None): | |
61 | ||
62 | # Clean up old items and callback commands. | |
63 | for oldIndex in range(len(self._itemList)): | |
64 | tclCommandName = str(self._menu.entrycget(oldIndex, 'command')) | |
65 | if tclCommandName != '': | |
66 | self._menu.deletecommand(tclCommandName) | |
67 | self._menu.delete(0, 'end') | |
68 | self._itemList = list(items) | |
69 | ||
70 | # Set the items in the menu component. | |
71 | for item in items: | |
72 | self._menu.add_command(label = item, | |
73 | command = lambda self = self, item = item: self._invoke(item)) | |
74 | ||
75 | # Set the currently selected value. | |
76 | if index is None: | |
77 | var = str(self._menubutton.cget('textvariable')) | |
78 | if var != '': | |
79 | # None means do not change text variable. | |
80 | return | |
81 | if len(items) == 0: | |
82 | text = '' | |
83 | elif str(self._menubutton.cget('text')) in items: | |
84 | # Do not change selection if it is still valid | |
85 | return | |
86 | else: | |
87 | text = items[0] | |
88 | else: | |
89 | index = self.index(index) | |
90 | text = self._itemList[index] | |
91 | ||
92 | self.setvalue(text) | |
93 | ||
94 | def getcurselection(self): | |
95 | var = str(self._menubutton.cget('textvariable')) | |
96 | if var == '': | |
97 | return str(self._menubutton.cget('text')) | |
98 | else: | |
99 | return self._menu.tk.globalgetvar(var) | |
100 | ||
101 | def getvalue(self): | |
102 | return self.getcurselection() | |
103 | ||
104 | def setvalue(self, text): | |
105 | var = str(self._menubutton.cget('textvariable')) | |
106 | if var == '': | |
107 | self._menubutton.configure(text = text) | |
108 | else: | |
109 | self._menu.tk.globalsetvar(var, text) | |
110 | ||
111 | def index(self, index): | |
112 | listLength = len(self._itemList) | |
113 | if type(index) == types.IntType: | |
114 | if index < listLength: | |
115 | return index | |
116 | else: | |
117 | raise ValueError, 'index "%s" is out of range' % index | |
118 | elif index is Pmw.END: | |
119 | if listLength > 0: | |
120 | return listLength - 1 | |
121 | else: | |
122 | raise ValueError, 'OptionMenu has no items' | |
123 | else: | |
124 | if index is Pmw.SELECT: | |
125 | if listLength > 0: | |
126 | index = self.getcurselection() | |
127 | else: | |
128 | raise ValueError, 'OptionMenu has no items' | |
129 | if index in self._itemList: | |
130 | return self._itemList.index(index) | |
131 | raise ValueError, \ | |
132 | 'bad index "%s": must be a ' \ | |
133 | 'name, a number, Pmw.END or Pmw.SELECT' % (index,) | |
134 | ||
135 | def invoke(self, index = Pmw.SELECT): | |
136 | index = self.index(index) | |
137 | text = self._itemList[index] | |
138 | ||
139 | return self._invoke(text) | |
140 | ||
141 | def _invoke(self, text): | |
142 | self.setvalue(text) | |
143 | ||
144 | command = self['command'] | |
145 | if callable(command): | |
146 | return command(text) |