blob: 61dba26e5d9883e0cab9e658a2db99be8f460029 [file] [log] [blame]
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +00001"A sort of application framework for the Mac"
2
Jack Jansen7a583361995-08-14 12:39:54 +00003DEBUG=0
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +00004
5import MacOS
6import traceback
7
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +00008from AE import *
9from AppleEvents import *
Jack Jansen7a583361995-08-14 12:39:54 +000010from Ctl import *
11from Controls import *
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000012from Dlg import *
13from Dialogs import *
14from Evt import *
15from Events import *
16from Menu import *
17from Menus import *
Jack Jansen7a583361995-08-14 12:39:54 +000018from Qd import *
19from QuickDraw import *
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000020#from Res import *
21#from Resources import *
22#from Snd import *
23#from Sound import *
24from Win import *
25from Windows import *
26
27import EasyDialogs
28
29kHighLevelEvent = 23 # Don't know what header file this should come from
Jack Jansene3532151996-04-12 16:24:44 +000030SCROLLBARWIDTH = 16 # Again, not a clue...
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000031
32
33# Map event 'what' field to strings
34eventname = {}
35eventname[1] = 'mouseDown'
36eventname[2] = 'mouseUp'
37eventname[3] = 'keyDown'
38eventname[4] = 'keyUp'
39eventname[5] = 'autoKey'
40eventname[6] = 'updateEvt'
41eventname[7] = 'diskEvt'
42eventname[8] = 'activateEvt'
43eventname[15] = 'osEvt'
44eventname[23] = 'kHighLevelEvent'
45
46# Map part codes returned by WhichWindow() to strings
47partname = {}
48partname[0] = 'inDesk'
49partname[1] = 'inMenuBar'
50partname[2] = 'inSysWindow'
51partname[3] = 'inContent'
52partname[4] = 'inDrag'
53partname[5] = 'inGrow'
54partname[6] = 'inGoAway'
55partname[7] = 'inZoomIn'
56partname[8] = 'inZoomOut'
57
58# A rectangle that's bigger than the screen,
59# but not so big that adding the screen size to it will cause 16-bit overflow
60everywhere = (-16000, -16000, 16000, 16000)
61
62
63class Application:
64
65 "Application framework -- your application should be a derived class"
66
67 def __init__(self):
Jack Jansen7e0da901995-08-17 14:18:20 +000068 self._windows = {}
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000069 self.makemenubar()
70
71 def makemenubar(self):
72 self.menubar = MenuBar()
73 AppleMenu(self.menubar, self.getabouttext(), self.do_about)
74 self.makeusermenus()
Jack Jansenc8a99491996-01-08 23:50:13 +000075
76 def makeusermenus(self):
77 self.filemenu = m = Menu(self.menubar, "File")
78 self._quititem = MenuItem(m, "Quit", "Q", self._quit)
79
80 def _quit(self, *args):
81 raise self
Jack Jansen7e0da901995-08-17 14:18:20 +000082
83 def appendwindow(self, wid, window):
84 self._windows[wid] = window
85
86 def removewindow(self, wid):
87 del self._windows[wid]
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000088
89 def getabouttext(self):
90 return "About %s..." % self.__class__.__name__
91
92 def do_about(self, id, item, window, event):
93 EasyDialogs.Message("Hello, world!" + "\015(%s)" % self.__class__.__name__)
94
95 # The main event loop is broken up in several simple steps.
96 # This is done so you can override each individual part,
97 # if you have a need to do extra processing independent of the
98 # event type.
99 # Normally, however, you'd just define handlers for individual
100 # events.
101 # (XXX I'm not sure if using default parameter values is the right
102 # way to define the mask and wait time passed to WaitNextEvent.)
103
104 def mainloop(self, mask = everyEvent, wait = 0):
105 saveyield = MacOS.EnableAppswitch(self.yield)
106 try:
107 while 1:
108 try:
109 self.do1event(mask, wait)
110 except (Application, SystemExit):
111 break
112 finally:
113 MacOS.EnableAppswitch(saveyield)
114
115 yield = -1
116
117 def do1event(self, mask = everyEvent, wait = 0):
Jack Jansen13dc4f71995-08-31 13:38:01 +0000118 ok, event = self.getevent(mask, wait)
119 if IsDialogEvent(event):
120 if self.do_dialogevent(event):
121 return
122 if ok:
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000123 self.dispatch(event)
Jack Jansen38186781995-11-10 14:48:36 +0000124 else:
125 self.idle()
126
127 def idle(self):
128 pass
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000129
130 def getevent(self, mask = everyEvent, wait = 0):
131 ok, event = WaitNextEvent(mask, wait)
Jack Jansen13dc4f71995-08-31 13:38:01 +0000132 return ok, event
133
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000134 def dispatch(self, event):
135 (what, message, when, where, modifiers) = event
136 if eventname.has_key(what):
137 name = "do_" + eventname[what]
138 else:
139 name = "do_%d" % what
140 try:
141 handler = getattr(self, name)
142 except AttributeError:
143 handler = self.do_unknownevent
144 handler(event)
Jack Jansen7e0da901995-08-17 14:18:20 +0000145
146 def do_dialogevent(self, event):
147 gotone, window, item = DialogSelect(event)
148 if gotone:
149 if self._windows.has_key(window):
Jack Jansen13dc4f71995-08-31 13:38:01 +0000150 self._windows[window].do_itemhit(item, event)
Jack Jansen7e0da901995-08-17 14:18:20 +0000151 else:
152 print 'Dialog event for unknown dialog'
Jack Jansen13dc4f71995-08-31 13:38:01 +0000153 return 1
154 return 0
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000155
156 def do_mouseDown(self, event):
157 (what, message, when, where, modifiers) = event
Jack Jansen7e0da901995-08-17 14:18:20 +0000158 partcode, wid = FindWindow(where)
159
160 #
161 # Find the correct name.
162 #
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000163 if partname.has_key(partcode):
164 name = "do_" + partname[partcode]
165 else:
166 name = "do_%d" % partcode
Jack Jansen7e0da901995-08-17 14:18:20 +0000167
168 if wid == None:
169 # No window, or a non-python window
170 try:
171 handler = getattr(self, name)
172 except AttributeError:
173 # Not menubar or something, so assume someone
174 # else's window
175 MacOS.HandleEvent(event)
176 return
177 elif self._windows.has_key(wid):
178 # It is a window. Hand off to correct window.
179 window = self._windows[wid]
180 try:
181 handler = getattr(window, name)
182 except AttributeError:
183 handler = self.do_unknownpartcode
184 else:
185 # It is a python-toolbox window, but not ours.
186 handler = self.do_unknownwindow
187 handler(partcode, wid, event)
188
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000189 def do_inSysWindow(self, partcode, window, event):
Jack Jansen7a583361995-08-14 12:39:54 +0000190 MacOS.HandleEvent(event)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000191
192 def do_inDesk(self, partcode, window, event):
Jack Jansen7a583361995-08-14 12:39:54 +0000193 MacOS.HandleEvent(event)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000194
195 def do_inMenuBar(self, partcode, window, event):
196 (what, message, when, where, modifiers) = event
197 result = MenuSelect(where)
198 id = (result>>16) & 0xffff # Hi word
199 item = result & 0xffff # Lo word
200 self.do_rawmenu(id, item, window, event)
201
202 def do_rawmenu(self, id, item, window, event):
203 try:
204 self.do_menu(id, item, window, event)
205 finally:
206 HiliteMenu(0)
207
208 def do_menu(self, id, item, window, event):
209 self.menubar.dispatch(id, item, window, event)
210
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000211
212 def do_unknownpartcode(self, partcode, window, event):
213 (what, message, when, where, modifiers) = event
Jack Jansen7a583361995-08-14 12:39:54 +0000214 if DEBUG: print "Mouse down at global:", where
215 if DEBUG: print "\tUnknown part code:", partcode
Jack Jansen7e0da901995-08-17 14:18:20 +0000216 if DEBUG: print "\tEvent:", self.printevent(event)
217 MacOS.HandleEvent(event)
218
219 def do_unknownwindow(self, partcode, window, event):
220 if DEBUG: print 'Unknown window:', window
Jack Jansen7a583361995-08-14 12:39:54 +0000221 MacOS.HandleEvent(event)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000222
223 def do_keyDown(self, event):
224 self.do_key(event)
225
226 def do_autoKey(self, event):
227 if not event[-1] & cmdKey:
228 self.do_key(event)
229
230 def do_key(self, event):
231 (what, message, when, where, modifiers) = event
232 c = chr(message & charCodeMask)
233 if modifiers & cmdKey:
234 if c == '.':
235 raise self
236 else:
237 result = MenuKey(ord(c))
238 id = (result>>16) & 0xffff # Hi word
239 item = result & 0xffff # Lo word
240 if id:
241 self.do_rawmenu(id, item, None, event)
Jack Jansen7e0da901995-08-17 14:18:20 +0000242# elif c == 'w':
243# w = FrontWindow()
244# if w:
245# self.do_close(w)
246# else:
247# if DEBUG: print 'Command-W without front window'
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000248 else:
Jack Jansen7a583361995-08-14 12:39:54 +0000249 if DEBUG: print "Command-" +`c`
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000250 else:
Jack Jansen7e0da901995-08-17 14:18:20 +0000251 # See whether the front window wants it
252 w = FrontWindow()
253 if w and self._windows.has_key(w):
254 window = self._windows[w]
255 try:
256 do_char = window.do_char
257 except AttributeError:
258 do_char = self.do_char
Jack Jansen6f47bf41995-12-12 15:03:35 +0000259 do_char(c, event)
260 # else it wasn't for us, sigh...
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000261
262 def do_char(self, c, event):
Jack Jansen7a583361995-08-14 12:39:54 +0000263 if DEBUG: print "Character", `c`
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000264
265 def do_updateEvt(self, event):
Jack Jansen7e0da901995-08-17 14:18:20 +0000266 (what, message, when, where, modifiers) = event
267 wid = WhichWindow(message)
268 if wid and self._windows.has_key(wid):
269 window = self._windows[wid]
270 window.do_rawupdate(wid, event)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000271 else:
Jack Jansen7a583361995-08-14 12:39:54 +0000272 MacOS.HandleEvent(event)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000273
Jack Jansen7e0da901995-08-17 14:18:20 +0000274 def do_activateEvt(self, event):
275 (what, message, when, where, modifiers) = event
Jack Jansenc8a99491996-01-08 23:50:13 +0000276 # XXXX Incorrect, should be fixed in suspendresume
277 if type(message) == type(1):
278 wid = WhichWindow(message)
279 else:
280 wid = message
Jack Jansen7e0da901995-08-17 14:18:20 +0000281 if wid and self._windows.has_key(wid):
282 window = self._windows[wid]
283 window.do_activate(modifiers & 1, event)
284 else:
285 MacOS.HandleEvent(event)
286
287 def do_osEvt(self, event):
288 (what, message, when, where, modifiers) = event
289 which = (message >> 24) & 0xff
290 if which == 1: # suspend/resume
291 self.do_suspendresume(event)
292 else:
293 if DEBUG:
294 print 'unknown osEvt:',
295 self.printevent(event)
296
297 def do_suspendresume(self, event):
298 # Is this a good idea???
299 (what, message, when, where, modifiers) = event
300 w = FrontWindow()
301 if w:
Jack Jansenc8a99491996-01-08 23:50:13 +0000302 # XXXX Incorrect, should stuff windowptr into message field
Jack Jansen7e0da901995-08-17 14:18:20 +0000303 nev = (activateEvt, w, when, where, message&1)
Jack Jansenc8a99491996-01-08 23:50:13 +0000304 self.do_activateEvt(nev)
Jack Jansen7e0da901995-08-17 14:18:20 +0000305
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000306 def do_kHighLevelEvent(self, event):
307 (what, message, when, where, modifiers) = event
Jack Jansen7a583361995-08-14 12:39:54 +0000308 if DEBUG:
309 print "High Level Event:",
310 self.printevent(event)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000311 try:
312 AEProcessAppleEvent(event)
313 except:
314 print "AEProcessAppleEvent error:"
315 traceback.print_exc()
316
317 def do_unknownevent(self, event):
Jack Jansen7e0da901995-08-17 14:18:20 +0000318 if DEBUG:
319 print "Unhandled event:",
320 self.printevent(event)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000321
322 def printevent(self, event):
323 (what, message, when, where, modifiers) = event
324 nicewhat = `what`
325 if eventname.has_key(what):
326 nicewhat = eventname[what]
327 print nicewhat,
328 if what == kHighLevelEvent:
329 h, v = where
330 print `ostypecode(message)`, hex(when), `ostypecode(h | (v<<16))`,
331 else:
332 print hex(message), hex(when), where,
333 print hex(modifiers)
334
335
336class MenuBar:
337 """Represent a set of menus in a menu bar.
338
339 Interface:
340
341 - (constructor)
342 - (destructor)
343 - addmenu
344 - addpopup (normally used internally)
345 - dispatch (called from Application)
346 """
347
348 nextid = 1 # Necessarily a class variable
349
350 def getnextid(self):
351 id = self.nextid
352 self.nextid = id+1
353 return id
354
355 def __init__(self):
356 ClearMenuBar()
357 self.bar = GetMenuBar()
358 self.menus = {}
359
360 def addmenu(self, title, after = 0):
361 id = self.getnextid()
Jack Jansene3532151996-04-12 16:24:44 +0000362 if DEBUG: print 'Newmenu', title, id # XXXX
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000363 m = NewMenu(id, title)
364 m.InsertMenu(after)
365 DrawMenuBar()
366 return id, m
Jack Jansendb9ff361996-03-12 13:32:03 +0000367
368 def delmenu(self, id):
Jack Jansene3532151996-04-12 16:24:44 +0000369 if DEBUG: print 'Delmenu', id # XXXX
Jack Jansendb9ff361996-03-12 13:32:03 +0000370 DeleteMenu(id)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000371
372 def addpopup(self, title = ''):
373 return self.addmenu(title, -1)
374
375 def install(self):
376 self.bar.SetMenuBar()
377 DrawMenuBar()
378
379 def dispatch(self, id, item, window, event):
380 if self.menus.has_key(id):
381 self.menus[id].dispatch(id, item, window, event)
382 else:
Jack Jansen7a583361995-08-14 12:39:54 +0000383 if DEBUG: print "MenuBar.dispatch(%d, %d, %s, %s)" % \
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000384 (id, item, window, event)
385
386
387# XXX Need a way to get menus as resources and bind them to callbacks
388
389class Menu:
390 "One menu."
391
392 def __init__(self, bar, title, after=0):
393 self.bar = bar
394 self.id, self.menu = self.bar.addmenu(title, after)
395 bar.menus[self.id] = self
396 self.items = []
Jack Jansendb9ff361996-03-12 13:32:03 +0000397
398 def delete(self):
399 self.bar.delmenu(self.id)
400 del self.bar.menus[self.id]
401 del self.bar
402 del self.items
403 del self.menu
404 del self.id
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000405
406 def additem(self, label, shortcut=None, callback=None, kind=None):
407 self.menu.AppendMenu('x') # add a dummy string
408 self.items.append(label, shortcut, callback, kind)
409 item = len(self.items)
Jack Jansene4b40381995-07-17 13:25:15 +0000410 self.menu.SetMenuItemText(item, label) # set the actual text
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000411 if shortcut:
412 self.menu.SetItemCmd(item, ord(shortcut))
413 return item
414
415 def addcheck(self, label, shortcut=None, callback=None):
416 return self.additem(label, shortcut, callback, 'check')
417
418 def addradio(self, label, shortcut=None, callback=None):
419 return self.additem(label, shortcut, callback, 'radio')
420
421 def addseparator(self):
422 self.menu.AppendMenu('(-')
423 self.items.append('', None, None, 'separator')
424
425 def addsubmenu(self, label, title=''):
426 sub = Menu(self.bar, title, -1)
427 item = self.additem(label, '\x1B', None, 'submenu')
428 self.menu.SetItemMark(item, sub.id)
429 return sub
430
431 def dispatch(self, id, item, window, event):
432 title, shortcut, callback, type = self.items[item-1]
433 if callback:
434 callback(id, item, window, event)
435
Jack Jansencef2c591996-04-11 15:39:01 +0000436 def enable(self, onoff):
437 if onoff:
438 self.menu.EnableItem(0)
439 else:
440 self.menu.DisableItem(0)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000441
442class MenuItem:
443 def __init__(self, menu, title, shortcut=None, callback=None, kind=None):
444 self.item = menu.additem(title, shortcut, callback)
Jack Jansendb9ff361996-03-12 13:32:03 +0000445 self.menu = menu
446
447 def check(self, onoff):
448 self.menu.menu.CheckItem(self.item, onoff)
Jack Jansencef2c591996-04-11 15:39:01 +0000449
450 def enable(self, onoff):
451 if onoff:
452 self.menu.menu.EnableItem(self.item)
453 else:
454 self.menu.menu.DisableItem(self.item)
Jack Jansendb9ff361996-03-12 13:32:03 +0000455
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000456
457class RadioItem(MenuItem):
458 def __init__(self, menu, title, shortcut=None, callback=None):
459 MenuItem.__init__(self, menu, title, shortcut, callback, 'radio')
460
461class CheckItem(MenuItem):
462 def __init__(self, menu, title, shortcut=None, callback=None):
463 MenuItem.__init__(self, menu, title, shortcut, callback, 'check')
464
465def Separator(menu):
466 menu.addseparator()
467
468def SubMenu(menu, label, title=''):
469 return menu.addsubmenu(label, title)
470
471
472class AppleMenu(Menu):
473
474 def __init__(self, bar, abouttext="About me...", aboutcallback=None):
475 Menu.__init__(self, bar, "\024")
476 self.additem(abouttext, None, aboutcallback)
477 self.addseparator()
Jack Jansene4b40381995-07-17 13:25:15 +0000478 self.menu.AppendResMenu('DRVR')
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000479
480 def dispatch(self, id, item, window, event):
481 if item == 1:
482 Menu.dispatch(self, id, item, window, event)
483 else:
Jack Jansenc8a99491996-01-08 23:50:13 +0000484 name = self.menu.GetMenuItemText(item)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000485 OpenDeskAcc(name)
486
Jack Jansen7e0da901995-08-17 14:18:20 +0000487class Window:
488 """A single window belonging to an application"""
489
490 def __init__(self, parent):
491 self.wid = None
492 self.parent = parent
493
Jack Jansenc8a99491996-01-08 23:50:13 +0000494 def open(self, bounds=(40, 40, 400, 400), resid=None):
495 if resid <> None:
496 self.wid = GetNewWindow(resid, -1)
497 else:
498 self.wid = NewWindow(bounds, self.__class__.__name__, 1,
Jack Jansen7e0da901995-08-17 14:18:20 +0000499 0, -1, 1, 0)
500 self.do_postopen()
501
502 def do_postopen(self):
503 """Tell our parent we exist"""
504 self.parent.appendwindow(self.wid, self)
505
506 def close(self):
Jack Jansen7e0da901995-08-17 14:18:20 +0000507 self.do_postclose()
508
509 def do_postclose(self):
510 self.parent.removewindow(self.wid)
511 self.parent = None
512 self.wid = None
Jack Jansenc8a99491996-01-08 23:50:13 +0000513
514 def SetPort(self):
515 # Convinience method
516 SetPort(self.wid)
Jack Jansen7e0da901995-08-17 14:18:20 +0000517
518 def do_inDrag(self, partcode, window, event):
519 where = event[3]
520 window.DragWindow(where, self.draglimit)
521
522 draglimit = everywhere
523
524 def do_inGoAway(self, partcode, window, event):
525 where = event[3]
526 if window.TrackGoAway(where):
527 self.close()
528
529 def do_inZoom(self, partcode, window, event):
530 (what, message, when, where, modifiers) = event
531 if window.TrackBox(where, partcode):
532 window.ZoomWindow(partcode, 1)
533
534 def do_inZoomIn(self, partcode, window, event):
535 SetPort(window) # !!!
536 self.do_inZoom(partcode, window, event)
537
538 def do_inZoomOut(self, partcode, window, event):
539 SetPort(window) # !!!
540 self.do_inZoom(partcode, window, event)
541
542 def do_inGrow(self, partcode, window, event):
543 (what, message, when, where, modifiers) = event
544 result = window.GrowWindow(where, self.growlimit)
545 if result:
546 height = (result>>16) & 0xffff # Hi word
547 width = result & 0xffff # Lo word
548 self.do_resize(width, height, window)
549
550 growlimit = everywhere
551
552 def do_resize(self, width, height, window):
553 window.SizeWindow(width, height, 0)
554 self.do_postresize(width, height, window)
555
556 def do_postresize(self, width, height, window):
557 SetPort(window)
558 InvalRect(everywhere)
559
560 def do_inContent(self, partcode, window, event):
561 #
562 # If we're not frontmost, select ourselves and wait for
563 # the activate event.
564 #
565 if FrontWindow() <> window:
566 window.SelectWindow()
567 return
568 # We are. Handle the event.
569 (what, message, when, where, modifiers) = event
570 SetPort(window)
571 local = GlobalToLocal(where)
572 self.do_contentclick(local, modifiers, event)
573
574 def do_contentclick(self, local, modifiers, event):
575 print 'Click in contents at %s, modifiers %s'%(local, modifiers)
576
577 def do_rawupdate(self, window, event):
578 if DEBUG: print "raw update for", window
Jack Jansenda38f2d1995-11-14 10:15:42 +0000579 SetPort(window)
Jack Jansen7e0da901995-08-17 14:18:20 +0000580 window.BeginUpdate()
581 self.do_update(window, event)
582 window.EndUpdate()
583
584 def do_update(self, window, event):
585 EraseRect(everywhere)
586
587 def do_activate(self, activate, event):
588 if DEBUG: print 'Activate %d for %s'%(activate, self.wid)
589
590class ControlsWindow(Window):
591
592 def do_rawupdate(self, window, event):
593 if DEBUG: print "raw update for", window
594 window.BeginUpdate()
595 self.do_update(window, event)
596 DrawControls(window)
597 window.DrawGrowIcon()
598 window.EndUpdate()
599
600 def do_controlhit(self, window, control, pcode, event):
601 if DEBUG: print "control hit in", window, "on", control, "; pcode =", pcode
602
603 def do_inContent(self, partcode, window, event):
604 (what, message, when, where, modifiers) = event
Jack Jansenda38f2d1995-11-14 10:15:42 +0000605 SetPort(window) # XXXX Needed?
Jack Jansen7e0da901995-08-17 14:18:20 +0000606 local = GlobalToLocal(where)
607 ctltype, control = FindControl(local, window)
608 if ctltype and control:
609 pcode = control.TrackControl(local)
610 if pcode:
611 self.do_controlhit(window, control, pcode, event)
612 else:
613 if DEBUG: print "FindControl(%s, %s) -> (%s, %s)" % \
614 (local, window, ctltype, control)
Jack Jansene3532151996-04-12 16:24:44 +0000615 self.do_contentclick(local, modifiers, event)
616
617class ScrolledWindow(ControlsWindow):
618 def __init__(self, parent):
619 self.barx = self.bary = None
Jack Jansen7bfc8751996-04-16 14:35:43 +0000620 self.barx_enabled = self.bary_enabled = 1
621 self.activated = 1
Jack Jansene3532151996-04-12 16:24:44 +0000622 ControlsWindow.__init__(self, parent)
623
624 def scrollbars(self, wantx=1, wanty=1):
625 SetPort(self.wid)
626 self.barx = self.bary = None
Jack Jansen7bfc8751996-04-16 14:35:43 +0000627 self.barx_enabled = self.bary_enabled = 1
Jack Jansene3532151996-04-12 16:24:44 +0000628 x0, y0, x1, y1 = self.wid.GetWindowPort().portRect
629 vx, vy = self.getscrollbarvalues()
Jack Jansen7bfc8751996-04-16 14:35:43 +0000630 if vx == None: self.barx_enabled, vx = 0, 0
631 if vy == None: self.bary_enabled, vy = 0, 0
Jack Jansene3532151996-04-12 16:24:44 +0000632 if wantx:
633 rect = x0-1, y1-(SCROLLBARWIDTH-1), x1-(SCROLLBARWIDTH-2), y1+1
634 self.barx = NewControl(self.wid, rect, "", 1, vx, 0, 32767, 16, 0)
Jack Jansen7bfc8751996-04-16 14:35:43 +0000635 if not self.barx_enabled: self.barx.HiliteControl(255)
636## InvalRect(rect)
Jack Jansene3532151996-04-12 16:24:44 +0000637 if wanty:
638 rect = x1-(SCROLLBARWIDTH-1), y0-1, x1+1, y1-(SCROLLBARWIDTH-2)
639 self.bary = NewControl(self.wid, rect, "", 1, vy, 0, 32767, 16, 0)
Jack Jansen7bfc8751996-04-16 14:35:43 +0000640 if not self.bary_enabled: self.bary.HiliteControl(255)
641## InvalRect(rect)
Jack Jansene3532151996-04-12 16:24:44 +0000642
643 def do_postclose(self):
644 self.barx = self.bary = None
645 ControlsWindow.do_postclose(self)
646
647 def do_activate(self, onoff, event):
Jack Jansen7bfc8751996-04-16 14:35:43 +0000648 self.activated = onoff
Jack Jansene3532151996-04-12 16:24:44 +0000649 if onoff:
Jack Jansen7bfc8751996-04-16 14:35:43 +0000650 if self.barx and self.barx_enabled:
651 self.barx.HiliteControl(0)
652 if self.bary and self.bary_enabled:
653 self.bary.HiliteControl(0)
Jack Jansene3532151996-04-12 16:24:44 +0000654 else:
Jack Jansen7bfc8751996-04-16 14:35:43 +0000655 if self.barx:
656 self.barx.HiliteControl(255)
657 if self.bary:
658 self.bary.HiliteControl(255)
Jack Jansene3532151996-04-12 16:24:44 +0000659
660 def do_postresize(self, width, height, window):
661 l, t, r, b = self.wid.GetWindowPort().portRect
662 if self.barx:
663 self.barx.MoveControl(l-1, b-(SCROLLBARWIDTH-1))
664 self.barx.SizeControl((r-l)-(SCROLLBARWIDTH-2), SCROLLBARWIDTH)
665 if self.bary:
666 self.bary.MoveControl(r-(SCROLLBARWIDTH-1), t-1)
667 self.bary.SizeControl(SCROLLBARWIDTH, (b-t)-(SCROLLBARWIDTH-2))
668 InvalRect((l, t, r, b))
669
670 def do_controlhit(self, window, control, pcode, event):
671 if control == self.barx:
672 bar = self.barx
673 which = 'x'
674 elif control == self.bary:
675 bar = self.bary
676 which = 'y'
677 else:
678 return 0
679 value = None
680 if pcode == inUpButton:
681 what = '-'
682 elif pcode == inDownButton:
683 what = '+'
684 elif pcode == inPageUp:
685 what = '--'
686 elif pcode == inPageDown:
687 what = '++'
688 else:
689 what = 'set'
690 value = bar.GetControlValue()
691 self.scrollbar_callback(which, what, value)
692 self.updatescrollbars()
693 return 1
694
695 def updatescrollbars(self):
696 SetPort(self.wid)
697 vx, vy = self.getscrollbarvalues()
698 if self.barx:
Jack Jansen7bfc8751996-04-16 14:35:43 +0000699 if vx == None:
700 self.barx.HiliteControl(255)
701 self.barx_enabled = 0
702 else:
703 if not self.barx_enabled:
704 self.barx_enabled = 1
705 if self.activated:
706 self.barx.HiliteControl(0)
707 self.barx.SetControlValue(vx)
Jack Jansene3532151996-04-12 16:24:44 +0000708 if self.bary:
Jack Jansen7bfc8751996-04-16 14:35:43 +0000709 if vy == None:
710 self.bary.HiliteControl(255)
711 self.bary_enabled = 0
712 else:
713 if not self.bary_enabled:
714 self.bary_enabled = 1
715 if self.activated:
716 self.bary.HiliteControl(0)
717 self.bary.SetControlValue(vy)
718
719 # Auxiliary function: convert standard text/image/etc coordinate
720 # to something palatable as getscrollbarvalues() return
721 def scalebarvalue(self, absmin, absmax, curmin, curmax):
722 if curmin <= absmin and curmax >= absmax:
723 return None
724 if curmin <= absmin:
725 return 0
726 if curmax >= absmax:
727 return 32767
728 perc = float(curmin-absmin)/float(absmax-absmin)
729 return int(perc*32767)
Jack Jansene3532151996-04-12 16:24:44 +0000730
731 # To be overridden:
732
733 def getscrollbarvalues(self):
734 return 0, 0
735
736 def scrollbar_callback(self, which, what, value):
737 print 'scroll', which, what, value
Jack Jansen7e0da901995-08-17 14:18:20 +0000738
739class DialogWindow(Window):
740 """A modeless dialog window"""
741
742 def open(self, resid):
743 self.wid = GetNewDialog(resid, -1)
744 self.do_postopen()
745
746 def close(self):
Jack Jansen7e0da901995-08-17 14:18:20 +0000747 self.do_postclose()
748
749 def do_itemhit(self, item, event):
750 print 'Dialog %s, item %d hit'%(self.wid, item)
751
752 def do_rawupdate(self, window, event):
753 pass
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000754
755def ostypecode(x):
756 "Convert a long int to the 4-character code it really is"
757 s = ''
758 for i in range(4):
759 x, c = divmod(x, 256)
760 s = chr(c) + s
761 return s
762
763
764class TestApp(Application):
765
766 "This class is used by the test() function"
767
768 def makeusermenus(self):
769 self.filemenu = m = Menu(self.menubar, "File")
770 self.saveitem = MenuItem(m, "Save", "S", self.save)
771 Separator(m)
772 self.optionsmenu = mm = SubMenu(m, "Options")
773 self.opt1 = CheckItem(mm, "Arguments")
774 self.opt2 = CheckItem(mm, "Being hit on the head lessons")
775 self.opt3 = CheckItem(mm, "Complaints")
776 Separator(m)
777 self.quititem = MenuItem(m, "Quit", "Q", self.quit)
778
779 def save(self, *args):
780 print "Save"
781
782 def quit(self, *args):
783 raise self
784
785
786def test():
787 "Test program"
788 app = TestApp()
789 app.mainloop()
790
791
792if __name__ == '__main__':
793 test()