Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / v8plus / lib / python2.4 / site-packages / Pmw / Pmw_1_2 / lib / PmwCounter.py
CommitLineData
920dae64
AT
1import string
2import sys
3import types
4import Tkinter
5import Pmw
6
7class Counter(Pmw.MegaWidget):
8
9 def __init__(self, parent = None, **kw):
10
11 # Define the megawidget options.
12 INITOPT = Pmw.INITOPT
13 optiondefs = (
14 ('autorepeat', 1, None),
15 ('buttonaspect', 1.0, INITOPT),
16 ('datatype', 'numeric', self._datatype),
17 ('increment', 1, None),
18 ('initwait', 300, None),
19 ('labelmargin', 0, INITOPT),
20 ('labelpos', None, INITOPT),
21 ('orient', 'horizontal', INITOPT),
22 ('padx', 0, INITOPT),
23 ('pady', 0, INITOPT),
24 ('repeatrate', 50, None),
25 ('sticky', 'ew', INITOPT),
26 )
27 self.defineoptions(kw, optiondefs)
28
29 # Initialise the base class (after defining the options).
30 Pmw.MegaWidget.__init__(self, parent)
31
32 # Initialise instance variables.
33 self._timerId = None
34 self._normalRelief = None
35
36 # Create the components.
37 interior = self.interior()
38
39 # If there is no label, put the arrows and the entry directly
40 # into the interior, otherwise create a frame for them. In
41 # either case the border around the arrows and the entry will
42 # be raised (but not around the label).
43 if self['labelpos'] is None:
44 frame = interior
45 if not kw.has_key('hull_relief'):
46 frame.configure(relief = 'raised')
47 if not kw.has_key('hull_borderwidth'):
48 frame.configure(borderwidth = 1)
49 else:
50 frame = self.createcomponent('frame',
51 (), None,
52 Tkinter.Frame, (interior,),
53 relief = 'raised', borderwidth = 1)
54 frame.grid(column=2, row=2, sticky=self['sticky'])
55 interior.grid_columnconfigure(2, weight=1)
56 interior.grid_rowconfigure(2, weight=1)
57
58 # Create the down arrow.
59 self._downArrowBtn = self.createcomponent('downarrow',
60 (), 'Arrow',
61 Tkinter.Canvas, (frame,),
62 width = 16, height = 16, relief = 'raised', borderwidth = 2)
63
64 # Create the entry field.
65 self._counterEntry = self.createcomponent('entryfield',
66 (('entry', 'entryfield_entry'),), None,
67 Pmw.EntryField, (frame,))
68
69 # Create the up arrow.
70 self._upArrowBtn = self.createcomponent('uparrow',
71 (), 'Arrow',
72 Tkinter.Canvas, (frame,),
73 width = 16, height = 16, relief = 'raised', borderwidth = 2)
74
75 padx = self['padx']
76 pady = self['pady']
77 orient = self['orient']
78 if orient == 'horizontal':
79 self._downArrowBtn.grid(column = 0, row = 0)
80 self._counterEntry.grid(column = 1, row = 0,
81 sticky = self['sticky'])
82 self._upArrowBtn.grid(column = 2, row = 0)
83 frame.grid_columnconfigure(1, weight = 1)
84 frame.grid_rowconfigure(0, weight = 1)
85 if Tkinter.TkVersion >= 4.2:
86 frame.grid_columnconfigure(0, pad = padx)
87 frame.grid_columnconfigure(2, pad = padx)
88 frame.grid_rowconfigure(0, pad = pady)
89 elif orient == 'vertical':
90 self._upArrowBtn.grid(column = 0, row = 0, sticky = 's')
91 self._counterEntry.grid(column = 0, row = 1,
92 sticky = self['sticky'])
93 self._downArrowBtn.grid(column = 0, row = 2, sticky = 'n')
94 frame.grid_columnconfigure(0, weight = 1)
95 frame.grid_rowconfigure(0, weight = 1)
96 frame.grid_rowconfigure(2, weight = 1)
97 if Tkinter.TkVersion >= 4.2:
98 frame.grid_rowconfigure(0, pad = pady)
99 frame.grid_rowconfigure(2, pad = pady)
100 frame.grid_columnconfigure(0, pad = padx)
101 else:
102 raise ValueError, 'bad orient option ' + repr(orient) + \
103 ': must be either \'horizontal\' or \'vertical\''
104
105 self.createlabel(interior)
106
107 self._upArrowBtn.bind('<Configure>', self._drawUpArrow)
108 self._upArrowBtn.bind('<1>', self._countUp)
109 self._upArrowBtn.bind('<Any-ButtonRelease-1>', self._stopCounting)
110 self._downArrowBtn.bind('<Configure>', self._drawDownArrow)
111 self._downArrowBtn.bind('<1>', self._countDown)
112 self._downArrowBtn.bind('<Any-ButtonRelease-1>', self._stopCounting)
113 self._counterEntry.bind('<Configure>', self._resizeArrow)
114 entry = self._counterEntry.component('entry')
115 entry.bind('<Down>', lambda event, s = self: s._key_decrement(event))
116 entry.bind('<Up>', lambda event, s = self: s._key_increment(event))
117
118 # Need to cancel the timer if an arrow button is unmapped (eg:
119 # its toplevel window is withdrawn) while the mouse button is
120 # held down. The canvas will not get the ButtonRelease event
121 # if it is not mapped, since the implicit grab is cancelled.
122 self._upArrowBtn.bind('<Unmap>', self._stopCounting)
123 self._downArrowBtn.bind('<Unmap>', self._stopCounting)
124
125 # Check keywords and initialise options.
126 self.initialiseoptions()
127
128 def _resizeArrow(self, event):
129 for btn in (self._upArrowBtn, self._downArrowBtn):
130 bw = (string.atoi(btn['borderwidth']) +
131 string.atoi(btn['highlightthickness']))
132 newHeight = self._counterEntry.winfo_reqheight() - 2 * bw
133 newWidth = int(newHeight * self['buttonaspect'])
134 btn.configure(width=newWidth, height=newHeight)
135 self._drawArrow(btn)
136
137 def _drawUpArrow(self, event):
138 self._drawArrow(self._upArrowBtn)
139
140 def _drawDownArrow(self, event):
141 self._drawArrow(self._downArrowBtn)
142
143 def _drawArrow(self, arrow):
144 if self['orient'] == 'vertical':
145 if arrow == self._upArrowBtn:
146 direction = 'up'
147 else:
148 direction = 'down'
149 else:
150 if arrow == self._upArrowBtn:
151 direction = 'right'
152 else:
153 direction = 'left'
154 Pmw.drawarrow(arrow, self['entry_foreground'], direction, 'arrow')
155
156 def _stopCounting(self, event = None):
157 if self._timerId is not None:
158 self.after_cancel(self._timerId)
159 self._timerId = None
160 if self._normalRelief is not None:
161 button, relief = self._normalRelief
162 button.configure(relief=relief)
163 self._normalRelief = None
164
165 def _countUp(self, event):
166 self._normalRelief = (self._upArrowBtn, self._upArrowBtn.cget('relief'))
167 self._upArrowBtn.configure(relief='sunken')
168 # Force arrow down (it may come up immediately, if increment fails).
169 self._upArrowBtn.update_idletasks()
170 self._count(1, 1)
171
172 def _countDown(self, event):
173 self._normalRelief = (self._downArrowBtn, self._downArrowBtn.cget('relief'))
174 self._downArrowBtn.configure(relief='sunken')
175 # Force arrow down (it may come up immediately, if increment fails).
176 self._downArrowBtn.update_idletasks()
177 self._count(-1, 1)
178
179 def increment(self):
180 self._forceCount(1)
181
182 def decrement(self):
183 self._forceCount(-1)
184
185 def _key_increment(self, event):
186 self._forceCount(1)
187 self.update_idletasks()
188
189 def _key_decrement(self, event):
190 self._forceCount(-1)
191 self.update_idletasks()
192
193 def _datatype(self):
194 datatype = self['datatype']
195
196 if type(datatype) is types.DictionaryType:
197 self._counterArgs = datatype.copy()
198 if self._counterArgs.has_key('counter'):
199 datatype = self._counterArgs['counter']
200 del self._counterArgs['counter']
201 else:
202 datatype = 'numeric'
203 else:
204 self._counterArgs = {}
205
206 if _counterCommands.has_key(datatype):
207 self._counterCommand = _counterCommands[datatype]
208 elif callable(datatype):
209 self._counterCommand = datatype
210 else:
211 validValues = _counterCommands.keys()
212 validValues.sort()
213 raise ValueError, ('bad datatype value "%s": must be a' +
214 ' function or one of %s') % (datatype, validValues)
215
216 def _forceCount(self, factor):
217 if not self.valid():
218 self.bell()
219 return
220
221 text = self._counterEntry.get()
222 try:
223 value = apply(self._counterCommand,
224 (text, factor, self['increment']), self._counterArgs)
225 except ValueError:
226 self.bell()
227 return
228
229 previousICursor = self._counterEntry.index('insert')
230 if self._counterEntry.setentry(value) == Pmw.OK:
231 self._counterEntry.xview('end')
232 self._counterEntry.icursor(previousICursor)
233
234 def _count(self, factor, first):
235 if not self.valid():
236 self.bell()
237 return
238
239 self._timerId = None
240 origtext = self._counterEntry.get()
241 try:
242 value = apply(self._counterCommand,
243 (origtext, factor, self['increment']), self._counterArgs)
244 except ValueError:
245 # If text is invalid, stop counting.
246 self._stopCounting()
247 self.bell()
248 return
249
250 # If incrementing produces an invalid value, restore previous
251 # text and stop counting.
252 previousICursor = self._counterEntry.index('insert')
253 valid = self._counterEntry.setentry(value)
254 if valid != Pmw.OK:
255 self._stopCounting()
256 self._counterEntry.setentry(origtext)
257 if valid == Pmw.PARTIAL:
258 self.bell()
259 return
260 self._counterEntry.xview('end')
261 self._counterEntry.icursor(previousICursor)
262
263 if self['autorepeat']:
264 if first:
265 delay = self['initwait']
266 else:
267 delay = self['repeatrate']
268 self._timerId = self.after(delay,
269 lambda self=self, factor=factor: self._count(factor, 0))
270
271 def destroy(self):
272 self._stopCounting()
273 Pmw.MegaWidget.destroy(self)
274
275Pmw.forwardmethods(Counter, Pmw.EntryField, '_counterEntry')
276
277def _changeNumber(text, factor, increment):
278 value = string.atol(text)
279 if factor > 0:
280 value = (value / increment) * increment + increment
281 else:
282 value = ((value - 1) / increment) * increment
283
284 # Get rid of the 'L' at the end of longs (in python up to 1.5.2).
285 rtn = str(value)
286 if rtn[-1] == 'L':
287 return rtn[:-1]
288 else:
289 return rtn
290
291def _changeReal(text, factor, increment, separator = '.'):
292 value = Pmw.stringtoreal(text, separator)
293 div = value / increment
294
295 # Compare reals using str() to avoid problems caused by binary
296 # numbers being only approximations to decimal numbers.
297 # For example, if value is -0.3 and increment is 0.1, then
298 # int(value/increment) = -2, not -3 as one would expect.
299 if str(div)[-2:] == '.0':
300 # value is an even multiple of increment.
301 div = round(div) + factor
302 else:
303 # value is not an even multiple of increment.
304 div = int(div) * 1.0
305 if value < 0:
306 div = div - 1
307 if factor > 0:
308 div = (div + 1)
309
310 value = div * increment
311
312 text = str(value)
313 if separator != '.':
314 index = string.find(text, '.')
315 if index >= 0:
316 text = text[:index] + separator + text[index + 1:]
317 return text
318
319def _changeDate(value, factor, increment, format = 'ymd',
320 separator = '/', yyyy = 0):
321
322 jdn = Pmw.datestringtojdn(value, format, separator) + factor * increment
323
324 y, m, d = Pmw.jdntoymd(jdn)
325 result = ''
326 for index in range(3):
327 if index > 0:
328 result = result + separator
329 f = format[index]
330 if f == 'y':
331 if yyyy:
332 result = result + '%02d' % y
333 else:
334 result = result + '%02d' % (y % 100)
335 elif f == 'm':
336 result = result + '%02d' % m
337 elif f == 'd':
338 result = result + '%02d' % d
339
340 return result
341
342_SECSPERDAY = 24 * 60 * 60
343def _changeTime(value, factor, increment, separator = ':', time24 = 0):
344 unixTime = Pmw.timestringtoseconds(value, separator)
345 if factor > 0:
346 chunks = unixTime / increment + 1
347 else:
348 chunks = (unixTime - 1) / increment
349 unixTime = chunks * increment
350 if time24:
351 while unixTime < 0:
352 unixTime = unixTime + _SECSPERDAY
353 while unixTime >= _SECSPERDAY:
354 unixTime = unixTime - _SECSPERDAY
355 if unixTime < 0:
356 unixTime = -unixTime
357 sign = '-'
358 else:
359 sign = ''
360 secs = unixTime % 60
361 unixTime = unixTime / 60
362 mins = unixTime % 60
363 hours = unixTime / 60
364 return '%s%02d%s%02d%s%02d' % (sign, hours, separator, mins, separator, secs)
365
366# hexadecimal, alphabetic, alphanumeric not implemented
367_counterCommands = {
368 'numeric' : _changeNumber, # } integer
369 'integer' : _changeNumber, # } these two use the same function
370 'real' : _changeReal, # real number
371 'time' : _changeTime,
372 'date' : _changeDate,
373}