ยปCore Development>Code coverage>Lib/plat-mac/FrameWork.py

Python code coverage for Lib/plat-mac/FrameWork.py

#countcontent
1n/a"A sort of application framework for the Mac"
2n/a
3n/aDEBUG=0
4n/a
5n/afrom warnings import warnpy3k
6n/awarnpy3k("In 3.x, the FrameWork module is removed.", stacklevel=2)
7n/a
8n/aimport MacOS
9n/aimport traceback
10n/a
11n/afrom Carbon.AE import *
12n/afrom Carbon.AppleEvents import *
13n/afrom Carbon.Ctl import *
14n/afrom Carbon.Controls import *
15n/afrom Carbon.Dlg import *
16n/afrom Carbon.Dialogs import *
17n/afrom Carbon.Evt import *
18n/afrom Carbon.Events import *
19n/afrom Carbon.Help import *
20n/afrom Carbon.Menu import *
21n/afrom Carbon.Menus import *
22n/afrom Carbon.Qd import *
23n/afrom Carbon.QuickDraw import *
24n/a#from Carbon.Res import *
25n/a#from Carbon.Resources import *
26n/a#from Carbon.Snd import *
27n/a#from Carbon.Sound import *
28n/afrom Carbon.Win import *
29n/afrom Carbon.Windows import *
30n/aimport types
31n/a
32n/aimport EasyDialogs
33n/a
34n/atry:
35n/a MyFrontWindow = FrontNonFloatingWindow
36n/aexcept NameError:
37n/a MyFrontWindow = FrontWindow
38n/a
39n/akHighLevelEvent = 23 # Don't know what header file this should come from
40n/aSCROLLBARWIDTH = 16 # Again, not a clue...
41n/a
42n/a# Trick to forestall a set of SIOUX menus being added to our menubar
43n/aSIOUX_APPLEMENU_ID=32000
44n/a
45n/a
46n/a# Map event 'what' field to strings
47n/aeventname = {}
48n/aeventname[1] = 'mouseDown'
49n/aeventname[2] = 'mouseUp'
50n/aeventname[3] = 'keyDown'
51n/aeventname[4] = 'keyUp'
52n/aeventname[5] = 'autoKey'
53n/aeventname[6] = 'updateEvt'
54n/aeventname[7] = 'diskEvt'
55n/aeventname[8] = 'activateEvt'
56n/aeventname[15] = 'osEvt'
57n/aeventname[23] = 'kHighLevelEvent'
58n/a
59n/a# Map part codes returned by WhichWindow() to strings
60n/apartname = {}
61n/apartname[0] = 'inDesk'
62n/apartname[1] = 'inMenuBar'
63n/apartname[2] = 'inSysWindow'
64n/apartname[3] = 'inContent'
65n/apartname[4] = 'inDrag'
66n/apartname[5] = 'inGrow'
67n/apartname[6] = 'inGoAway'
68n/apartname[7] = 'inZoomIn'
69n/apartname[8] = 'inZoomOut'
70n/a
71n/a#
72n/a# The useable portion of the screen
73n/a# ## but what happens with multiple screens? jvr
74n/ascreenbounds = GetQDGlobalsScreenBits().bounds
75n/ascreenbounds = screenbounds[0]+4, screenbounds[1]+4, \
76n/a screenbounds[2]-4, screenbounds[3]-4
77n/a
78n/anext_window_x = 16 # jvr
79n/anext_window_y = 44 # jvr
80n/a
81n/adef windowbounds(width, height):
82n/a "Return sensible window bounds"
83n/a global next_window_x, next_window_y
84n/a r, b = next_window_x+width, next_window_y+height
85n/a if r > screenbounds[2]:
86n/a next_window_x = 16
87n/a if b > screenbounds[3]:
88n/a next_window_y = 44
89n/a l, t = next_window_x, next_window_y
90n/a r, b = next_window_x+width, next_window_y+height
91n/a next_window_x, next_window_y = next_window_x + 8, next_window_y + 20 # jvr
92n/a return l, t, r, b
93n/a
94n/a_watch = None
95n/adef setwatchcursor():
96n/a global _watch
97n/a
98n/a if _watch is None:
99n/a _watch = GetCursor(4).data
100n/a SetCursor(_watch)
101n/a
102n/adef setarrowcursor():
103n/a SetCursor(GetQDGlobalsArrow())
104n/a
105n/aclass Application:
106n/a
107n/a "Application framework -- your application should be a derived class"
108n/a
109n/a def __init__(self, nomenubar=0):
110n/a self._doing_asyncevents = 0
111n/a self.quitting = 0
112n/a self.needmenubarredraw = 0
113n/a self._windows = {}
114n/a self._helpmenu = None
115n/a if nomenubar:
116n/a self.menubar = None
117n/a else:
118n/a self.makemenubar()
119n/a
120n/a def __del__(self):
121n/a if self._doing_asyncevents:
122n/a self._doing_asyncevents = 0
123n/a MacOS.SetEventHandler()
124n/a
125n/a def makemenubar(self):
126n/a self.menubar = MenuBar(self)
127n/a AppleMenu(self.menubar, self.getabouttext(), self.do_about)
128n/a self.makeusermenus()
129n/a
130n/a def makeusermenus(self):
131n/a self.filemenu = m = Menu(self.menubar, "File")
132n/a self._quititem = MenuItem(m, "Quit", "Q", self._quit)
133n/a
134n/a def gethelpmenu(self):
135n/a if self._helpmenu is None:
136n/a self._helpmenu = HelpMenu(self.menubar)
137n/a return self._helpmenu
138n/a
139n/a def _quit(self, *args):
140n/a self.quitting = 1
141n/a
142n/a def cleanup(self):
143n/a for w in self._windows.values():
144n/a w.do_close()
145n/a return self._windows == {}
146n/a
147n/a def appendwindow(self, wid, window):
148n/a self._windows[wid] = window
149n/a
150n/a def removewindow(self, wid):
151n/a del self._windows[wid]
152n/a
153n/a def getabouttext(self):
154n/a return "About %s..." % self.__class__.__name__
155n/a
156n/a def do_about(self, id, item, window, event):
157n/a EasyDialogs.Message("Hello, world!" + "\015(%s)" % self.__class__.__name__)
158n/a
159n/a # The main event loop is broken up in several simple steps.
160n/a # This is done so you can override each individual part,
161n/a # if you have a need to do extra processing independent of the
162n/a # event type.
163n/a # Normally, however, you'd just define handlers for individual
164n/a # events.
165n/a
166n/a schedparams = (0, 0) # By default disable Python's event handling
167n/a default_wait = None # By default we wait GetCaretTime in WaitNextEvent
168n/a
169n/a def mainloop(self, mask = everyEvent, wait = None):
170n/a self.quitting = 0
171n/a if hasattr(MacOS, 'SchedParams'):
172n/a saveparams = MacOS.SchedParams(*self.schedparams)
173n/a try:
174n/a while not self.quitting:
175n/a try:
176n/a self.do1event(mask, wait)
177n/a except (Application, SystemExit):
178n/a # Note: the raising of "self" is old-fashioned idiom to
179n/a # exit the mainloop. Calling _quit() is better for new
180n/a # applications.
181n/a break
182n/a finally:
183n/a if hasattr(MacOS, 'SchedParams'):
184n/a MacOS.SchedParams(*saveparams)
185n/a
186n/a def dopendingevents(self, mask = everyEvent):
187n/a """dopendingevents - Handle all pending events"""
188n/a while self.do1event(mask, wait=0):
189n/a pass
190n/a
191n/a def do1event(self, mask = everyEvent, wait = None):
192n/a ok, event = self.getevent(mask, wait)
193n/a if IsDialogEvent(event):
194n/a if self.do_dialogevent(event):
195n/a return
196n/a if ok:
197n/a self.dispatch(event)
198n/a else:
199n/a self.idle(event)
200n/a
201n/a def idle(self, event):
202n/a pass
203n/a
204n/a def getevent(self, mask = everyEvent, wait = None):
205n/a if self.needmenubarredraw:
206n/a DrawMenuBar()
207n/a self.needmenubarredraw = 0
208n/a if wait is None:
209n/a wait = self.default_wait
210n/a if wait is None:
211n/a wait = GetCaretTime()
212n/a ok, event = WaitNextEvent(mask, wait)
213n/a return ok, event
214n/a
215n/a def dispatch(self, event):
216n/a # The following appears to be double work (already done in do1event)
217n/a # but we need it for asynchronous event handling
218n/a if IsDialogEvent(event):
219n/a if self.do_dialogevent(event):
220n/a return
221n/a (what, message, when, where, modifiers) = event
222n/a if what in eventname:
223n/a name = "do_" + eventname[what]
224n/a else:
225n/a name = "do_%d" % what
226n/a try:
227n/a handler = getattr(self, name)
228n/a except AttributeError:
229n/a handler = self.do_unknownevent
230n/a handler(event)
231n/a
232n/a def asyncevents(self, onoff):
233n/a """asyncevents - Set asynchronous event handling on or off"""
234n/a if MacOS.runtimemodel == 'macho':
235n/a raise 'Unsupported in MachoPython'
236n/a old = self._doing_asyncevents
237n/a if old:
238n/a MacOS.SetEventHandler()
239n/a MacOS.SchedParams(*self.schedparams)
240n/a if onoff:
241n/a MacOS.SetEventHandler(self.dispatch)
242n/a doint, dummymask, benice, howoften, bgyield = \
243n/a self.schedparams
244n/a MacOS.SchedParams(doint, everyEvent, benice,
245n/a howoften, bgyield)
246n/a self._doing_asyncevents = onoff
247n/a return old
248n/a
249n/a def do_dialogevent(self, event):
250n/a gotone, dlg, item = DialogSelect(event)
251n/a if gotone:
252n/a window = dlg.GetDialogWindow()
253n/a if window in self._windows:
254n/a self._windows[window].do_itemhit(item, event)
255n/a else:
256n/a print 'Dialog event for unknown dialog'
257n/a return 1
258n/a return 0
259n/a
260n/a def do_mouseDown(self, event):
261n/a (what, message, when, where, modifiers) = event
262n/a partcode, wid = FindWindow(where)
263n/a
264n/a #
265n/a # Find the correct name.
266n/a #
267n/a if partcode in partname:
268n/a name = "do_" + partname[partcode]
269n/a else:
270n/a name = "do_%d" % partcode
271n/a
272n/a if wid is None:
273n/a # No window, or a non-python window
274n/a try:
275n/a handler = getattr(self, name)
276n/a except AttributeError:
277n/a # Not menubar or something, so assume someone
278n/a # else's window
279n/a if hasattr(MacOS, 'HandleEvent'):
280n/a MacOS.HandleEvent(event)
281n/a return
282n/a elif wid in self._windows:
283n/a # It is a window. Hand off to correct window.
284n/a window = self._windows[wid]
285n/a try:
286n/a handler = getattr(window, name)
287n/a except AttributeError:
288n/a handler = self.do_unknownpartcode
289n/a else:
290n/a # It is a python-toolbox window, but not ours.
291n/a handler = self.do_unknownwindow
292n/a handler(partcode, wid, event)
293n/a
294n/a def do_inSysWindow(self, partcode, window, event):
295n/a if hasattr(MacOS, 'HandleEvent'):
296n/a MacOS.HandleEvent(event)
297n/a
298n/a def do_inDesk(self, partcode, window, event):
299n/a if hasattr(MacOS, 'HandleEvent'):
300n/a MacOS.HandleEvent(event)
301n/a
302n/a def do_inMenuBar(self, partcode, window, event):
303n/a if not self.menubar:
304n/a if hasattr(MacOS, 'HandleEvent'):
305n/a MacOS.HandleEvent(event)
306n/a return
307n/a (what, message, when, where, modifiers) = event
308n/a result = MenuSelect(where)
309n/a id = (result>>16) & 0xffff # Hi word
310n/a if id >= 0x8000:
311n/a id = -65536 + id
312n/a item = result & 0xffff # Lo word
313n/a self.do_rawmenu(id, item, window, event)
314n/a
315n/a def do_rawmenu(self, id, item, window, event):
316n/a try:
317n/a self.do_menu(id, item, window, event)
318n/a finally:
319n/a HiliteMenu(0)
320n/a
321n/a def do_menu(self, id, item, window, event):
322n/a if hasattr(MacOS, 'OutputSeen'):
323n/a MacOS.OutputSeen()
324n/a self.menubar.dispatch(id, item, window, event)
325n/a
326n/a
327n/a def do_unknownpartcode(self, partcode, window, event):
328n/a (what, message, when, where, modifiers) = event
329n/a if DEBUG: print "Mouse down at global:", where
330n/a if DEBUG: print "\tUnknown part code:", partcode
331n/a if DEBUG: print "\tEvent:", self.printevent(event)
332n/a if hasattr(MacOS, 'HandleEvent'):
333n/a MacOS.HandleEvent(event)
334n/a
335n/a def do_unknownwindow(self, partcode, window, event):
336n/a if DEBUG: print 'Unknown window:', window
337n/a if hasattr(MacOS, 'HandleEvent'):
338n/a MacOS.HandleEvent(event)
339n/a
340n/a def do_keyDown(self, event):
341n/a self.do_key(event)
342n/a
343n/a def do_autoKey(self, event):
344n/a if not event[-1] & cmdKey:
345n/a self.do_key(event)
346n/a
347n/a def do_key(self, event):
348n/a (what, message, when, where, modifiers) = event
349n/a c = chr(message & charCodeMask)
350n/a if self.menubar:
351n/a result = MenuEvent(event)
352n/a id = (result>>16) & 0xffff # Hi word
353n/a item = result & 0xffff # Lo word
354n/a if id:
355n/a self.do_rawmenu(id, item, None, event)
356n/a return
357n/a # Otherwise we fall-through
358n/a if modifiers & cmdKey:
359n/a if c == '.':
360n/a raise self
361n/a else:
362n/a if not self.menubar:
363n/a if hasattr(MacOS, 'HandleEvent'):
364n/a MacOS.HandleEvent(event)
365n/a return
366n/a else:
367n/a # See whether the front window wants it
368n/a w = MyFrontWindow()
369n/a if w and w in self._windows:
370n/a window = self._windows[w]
371n/a try:
372n/a do_char = window.do_char
373n/a except AttributeError:
374n/a do_char = self.do_char
375n/a do_char(c, event)
376n/a # else it wasn't for us, sigh...
377n/a
378n/a def do_char(self, c, event):
379n/a if DEBUG: print "Character", repr(c)
380n/a
381n/a def do_updateEvt(self, event):
382n/a (what, message, when, where, modifiers) = event
383n/a wid = WhichWindow(message)
384n/a if wid and wid in self._windows:
385n/a window = self._windows[wid]
386n/a window.do_rawupdate(wid, event)
387n/a else:
388n/a if hasattr(MacOS, 'HandleEvent'):
389n/a MacOS.HandleEvent(event)
390n/a
391n/a def do_activateEvt(self, event):
392n/a (what, message, when, where, modifiers) = event
393n/a wid = WhichWindow(message)
394n/a if wid and wid in self._windows:
395n/a window = self._windows[wid]
396n/a window.do_activate(modifiers & 1, event)
397n/a else:
398n/a if hasattr(MacOS, 'HandleEvent'):
399n/a MacOS.HandleEvent(event)
400n/a
401n/a def do_osEvt(self, event):
402n/a (what, message, when, where, modifiers) = event
403n/a which = (message >> 24) & 0xff
404n/a if which == 1: # suspend/resume
405n/a self.do_suspendresume(event)
406n/a else:
407n/a if DEBUG:
408n/a print 'unknown osEvt:',
409n/a self.printevent(event)
410n/a
411n/a def do_suspendresume(self, event):
412n/a (what, message, when, where, modifiers) = event
413n/a wid = MyFrontWindow()
414n/a if wid and wid in self._windows:
415n/a window = self._windows[wid]
416n/a window.do_activate(message & 1, event)
417n/a
418n/a def do_kHighLevelEvent(self, event):
419n/a (what, message, when, where, modifiers) = event
420n/a if DEBUG:
421n/a print "High Level Event:",
422n/a self.printevent(event)
423n/a try:
424n/a AEProcessAppleEvent(event)
425n/a except:
426n/a pass
427n/a #print "AEProcessAppleEvent error:"
428n/a #traceback.print_exc()
429n/a
430n/a def do_unknownevent(self, event):
431n/a if DEBUG:
432n/a print "Unhandled event:",
433n/a self.printevent(event)
434n/a
435n/a def printevent(self, event):
436n/a (what, message, when, where, modifiers) = event
437n/a nicewhat = repr(what)
438n/a if what in eventname:
439n/a nicewhat = eventname[what]
440n/a print nicewhat,
441n/a if what == kHighLevelEvent:
442n/a h, v = where
443n/a print repr(ostypecode(message)), hex(when), repr(ostypecode(h | (v<<16))),
444n/a else:
445n/a print hex(message), hex(when), where,
446n/a print hex(modifiers)
447n/a
448n/a
449n/aclass MenuBar:
450n/a """Represent a set of menus in a menu bar.
451n/a
452n/a Interface:
453n/a
454n/a - (constructor)
455n/a - (destructor)
456n/a - addmenu
457n/a - addpopup (normally used internally)
458n/a - dispatch (called from Application)
459n/a """
460n/a
461n/a nextid = 1 # Necessarily a class variable
462n/a
463n/a def getnextid(self):
464n/a id = MenuBar.nextid
465n/a MenuBar.nextid = id+1
466n/a return id
467n/a
468n/a def __init__(self, parent=None):
469n/a self.parent = parent
470n/a ClearMenuBar()
471n/a self.bar = GetMenuBar()
472n/a self.menus = {}
473n/a
474n/a # XXX necessary?
475n/a def close(self):
476n/a self.parent = None
477n/a self.bar = None
478n/a self.menus = None
479n/a
480n/a def addmenu(self, title, after = 0, id=None):
481n/a if id is None:
482n/a id = self.getnextid()
483n/a if DEBUG: print 'Newmenu', title, id # XXXX
484n/a m = NewMenu(id, title)
485n/a m.InsertMenu(after)
486n/a if after >= 0:
487n/a if self.parent:
488n/a self.parent.needmenubarredraw = 1
489n/a else:
490n/a DrawMenuBar()
491n/a return id, m
492n/a
493n/a def delmenu(self, id):
494n/a if DEBUG: print 'Delmenu', id # XXXX
495n/a DeleteMenu(id)
496n/a
497n/a def addpopup(self, title = ''):
498n/a return self.addmenu(title, -1)
499n/a
500n/a# Useless:
501n/a# def install(self):
502n/a# if not self.bar: return
503n/a# SetMenuBar(self.bar)
504n/a# if self.parent:
505n/a# self.parent.needmenubarredraw = 1
506n/a# else:
507n/a# DrawMenuBar()
508n/a
509n/a def fixmenudimstate(self):
510n/a for m in self.menus.keys():
511n/a menu = self.menus[m]
512n/a if menu.__class__ == FrameWork.AppleMenu:
513n/a continue
514n/a for i in range(len(menu.items)):
515n/a label, shortcut, callback, kind = menu.items[i]
516n/a if type(callback) == types.StringType:
517n/a wid = MyFrontWindow()
518n/a if wid and wid in self.parent._windows:
519n/a window = self.parent._windows[wid]
520n/a if hasattr(window, "domenu_" + callback):
521n/a menu.menu.EnableMenuItem(i + 1)
522n/a elif hasattr(self.parent, "domenu_" + callback):
523n/a menu.menu.EnableMenuItem(i + 1)
524n/a else:
525n/a menu.menu.DisableMenuItem(i + 1)
526n/a elif hasattr(self.parent, "domenu_" + callback):
527n/a menu.menu.EnableMenuItem(i + 1)
528n/a else:
529n/a menu.menu.DisableMenuItem(i + 1)
530n/a elif callback:
531n/a pass
532n/a
533n/a def dispatch(self, id, item, window, event):
534n/a if id in self.menus:
535n/a self.menus[id].dispatch(id, item, window, event)
536n/a else:
537n/a if DEBUG: print "MenuBar.dispatch(%d, %d, %s, %s)" % \
538n/a (id, item, window, event)
539n/a
540n/a
541n/a# XXX Need a way to get menus as resources and bind them to callbacks
542n/a
543n/aclass Menu:
544n/a "One menu."
545n/a
546n/a def __init__(self, bar, title, after=0, id=None):
547n/a self.bar = bar
548n/a self.id, self.menu = self.bar.addmenu(title, after, id)
549n/a bar.menus[self.id] = self
550n/a self.items = []
551n/a self._parent = None
552n/a
553n/a def delete(self):
554n/a self.bar.delmenu(self.id)
555n/a del self.bar.menus[self.id]
556n/a self.menu.DisposeMenu()
557n/a del self.bar
558n/a del self.items
559n/a del self.menu
560n/a del self.id
561n/a del self._parent
562n/a
563n/a def additem(self, label, shortcut=None, callback=None, kind=None):
564n/a self.menu.AppendMenu('x') # add a dummy string
565n/a self.items.append((label, shortcut, callback, kind))
566n/a item = len(self.items)
567n/a if isinstance(label, unicode):
568n/a self.menu.SetMenuItemTextWithCFString(item, label)
569n/a else:
570n/a self.menu.SetMenuItemText(item, label)
571n/a if shortcut and type(shortcut) == type(()):
572n/a modifiers, char = shortcut[:2]
573n/a self.menu.SetItemCmd(item, ord(char))
574n/a self.menu.SetMenuItemModifiers(item, modifiers)
575n/a if len(shortcut) > 2:
576n/a self.menu.SetMenuItemKeyGlyph(item, shortcut[2])
577n/a elif shortcut:
578n/a self.menu.SetItemCmd(item, ord(shortcut))
579n/a return item
580n/a
581n/a def delitem(self, item):
582n/a if item != len(self.items):
583n/a raise 'Can only delete last item of a menu'
584n/a self.menu.DeleteMenuItem(item)
585n/a del self.items[item-1]
586n/a
587n/a def addcheck(self, label, shortcut=None, callback=None):
588n/a return self.additem(label, shortcut, callback, 'check')
589n/a
590n/a def addradio(self, label, shortcut=None, callback=None):
591n/a return self.additem(label, shortcut, callback, 'radio')
592n/a
593n/a def addseparator(self):
594n/a self.menu.AppendMenu('(-')
595n/a self.items.append(('', None, None, 'separator'))
596n/a
597n/a def addsubmenu(self, label, title=''):
598n/a sub = Menu(self.bar, title, -1)
599n/a item = self.additem(label, '\x1B', None, 'submenu')
600n/a self.menu.SetItemMark(item, sub.id)
601n/a sub._parent = self
602n/a sub._parent_item = item
603n/a return sub
604n/a
605n/a def dispatch(self, id, item, window, event):
606n/a title, shortcut, callback, mtype = self.items[item-1]
607n/a if callback:
608n/a if not self.bar.parent or type(callback) != types.StringType:
609n/a menuhandler = callback
610n/a else:
611n/a # callback is string
612n/a wid = MyFrontWindow()
613n/a if wid and wid in self.bar.parent._windows:
614n/a window = self.bar.parent._windows[wid]
615n/a if hasattr(window, "domenu_" + callback):
616n/a menuhandler = getattr(window, "domenu_" + callback)
617n/a elif hasattr(self.bar.parent, "domenu_" + callback):
618n/a menuhandler = getattr(self.bar.parent, "domenu_" + callback)
619n/a else:
620n/a # nothing we can do. we shouldn't have come this far
621n/a # since the menu item should have been disabled...
622n/a return
623n/a elif hasattr(self.bar.parent, "domenu_" + callback):
624n/a menuhandler = getattr(self.bar.parent, "domenu_" + callback)
625n/a else:
626n/a # nothing we can do. we shouldn't have come this far
627n/a # since the menu item should have been disabled...
628n/a return
629n/a menuhandler(id, item, window, event)
630n/a
631n/a def enable(self, onoff):
632n/a if onoff:
633n/a self.menu.EnableMenuItem(0)
634n/a if self._parent:
635n/a self._parent.menu.EnableMenuItem(self._parent_item)
636n/a else:
637n/a self.menu.DisableMenuItem(0)
638n/a if self._parent:
639n/a self._parent.menu.DisableMenuItem(self._parent_item)
640n/a if self.bar and self.bar.parent:
641n/a self.bar.parent.needmenubarredraw = 1
642n/a
643n/aclass PopupMenu(Menu):
644n/a def __init__(self, bar):
645n/a Menu.__init__(self, bar, '(popup)', -1)
646n/a
647n/a def popup(self, x, y, event, default=1, window=None):
648n/a # NOTE that x and y are global coordinates, and they should probably
649n/a # be topleft of the button the user clicked (not mouse-coordinates),
650n/a # so the popup nicely overlaps.
651n/a reply = self.menu.PopUpMenuSelect(x, y, default)
652n/a if not reply:
653n/a return
654n/a id = (reply >> 16) & 0xffff
655n/a item = reply & 0xffff
656n/a if not window:
657n/a wid = MyFrontWindow()
658n/a try:
659n/a window = self.bar.parent._windows[wid]
660n/a except:
661n/a pass # If we can't find the window we pass None
662n/a self.dispatch(id, item, window, event)
663n/a
664n/aclass MenuItem:
665n/a def __init__(self, menu, title, shortcut=None, callback=None, kind=None):
666n/a self.item = menu.additem(title, shortcut, callback)
667n/a self.menu = menu
668n/a
669n/a def delete(self):
670n/a self.menu.delitem(self.item)
671n/a del self.menu
672n/a del self.item
673n/a
674n/a def check(self, onoff):
675n/a self.menu.menu.CheckMenuItem(self.item, onoff)
676n/a
677n/a def enable(self, onoff):
678n/a if onoff:
679n/a self.menu.menu.EnableMenuItem(self.item)
680n/a else:
681n/a self.menu.menu.DisableMenuItem(self.item)
682n/a
683n/a def settext(self, text):
684n/a self.menu.menu.SetMenuItemText(self.item, text)
685n/a
686n/a def setstyle(self, style):
687n/a self.menu.menu.SetItemStyle(self.item, style)
688n/a
689n/a def seticon(self, icon):
690n/a self.menu.menu.SetItemIcon(self.item, icon)
691n/a
692n/a def setcmd(self, cmd):
693n/a self.menu.menu.SetItemCmd(self.item, cmd)
694n/a
695n/a def setmark(self, cmd):
696n/a self.menu.menu.SetItemMark(self.item, cmd)
697n/a
698n/a
699n/aclass RadioItem(MenuItem):
700n/a def __init__(self, menu, title, shortcut=None, callback=None):
701n/a MenuItem.__init__(self, menu, title, shortcut, callback, 'radio')
702n/a
703n/aclass CheckItem(MenuItem):
704n/a def __init__(self, menu, title, shortcut=None, callback=None):
705n/a MenuItem.__init__(self, menu, title, shortcut, callback, 'check')
706n/a
707n/adef Separator(menu):
708n/a menu.addseparator()
709n/a
710n/adef SubMenu(menu, label, title=''):
711n/a return menu.addsubmenu(label, title)
712n/a
713n/a
714n/aclass AppleMenu(Menu):
715n/a
716n/a def __init__(self, bar, abouttext="About me...", aboutcallback=None):
717n/a Menu.__init__(self, bar, "\024", id=SIOUX_APPLEMENU_ID)
718n/a if MacOS.runtimemodel == 'ppc':
719n/a self.additem(abouttext, None, aboutcallback)
720n/a self.addseparator()
721n/a self.menu.AppendResMenu('DRVR')
722n/a else:
723n/a # Additem()'s tricks do not work for "apple" menu under Carbon
724n/a self.menu.InsertMenuItem(abouttext, 0)
725n/a self.items.append((abouttext, None, aboutcallback, None))
726n/a
727n/a def dispatch(self, id, item, window, event):
728n/a if item == 1:
729n/a Menu.dispatch(self, id, item, window, event)
730n/a elif MacOS.runtimemodel == 'ppc':
731n/a name = self.menu.GetMenuItemText(item)
732n/a OpenDeskAcc(name)
733n/a
734n/aclass HelpMenu(Menu):
735n/a def __init__(self, bar):
736n/a # Note we don't call Menu.__init__, we do the necessary things by hand
737n/a self.bar = bar
738n/a self.menu, index = HMGetHelpMenu()
739n/a self.id = self.menu.GetMenuID()
740n/a bar.menus[self.id] = self
741n/a # The next line caters for the entries the system already handles for us
742n/a self.items = [None]*(index-1)
743n/a self._parent = None
744n/a
745n/a
746n/aclass Window:
747n/a """A single window belonging to an application"""
748n/a
749n/a def __init__(self, parent):
750n/a self.wid = None
751n/a self.parent = parent
752n/a
753n/a def open(self, bounds=(40, 40, 400, 400), resid=None):
754n/a if resid != None:
755n/a self.wid = GetNewWindow(resid, -1)
756n/a else:
757n/a self.wid = NewWindow(bounds, self.__class__.__name__, 1,
758n/a 8, -1, 1, 0) # changed to proc id 8 to include zoom box. jvr
759n/a self.do_postopen()
760n/a
761n/a def do_postopen(self):
762n/a """Tell our parent we exist"""
763n/a self.parent.appendwindow(self.wid, self)
764n/a
765n/a def close(self):
766n/a self.do_postclose()
767n/a
768n/a def do_postclose(self):
769n/a self.parent.removewindow(self.wid)
770n/a self.parent = None
771n/a self.wid = None
772n/a
773n/a def SetPort(self):
774n/a # Convinience method
775n/a SetPort(self.wid)
776n/a
777n/a def GetWindow(self):
778n/a return self.wid
779n/a
780n/a def do_inDrag(self, partcode, window, event):
781n/a where = event[3]
782n/a window.DragWindow(where, self.draglimit)
783n/a
784n/a draglimit = screenbounds
785n/a
786n/a def do_inGoAway(self, partcode, window, event):
787n/a where = event[3]
788n/a if window.TrackGoAway(where):
789n/a self.close()
790n/a
791n/a def do_inZoom(self, partcode, window, event):
792n/a (what, message, when, where, modifiers) = event
793n/a if window.TrackBox(where, partcode):
794n/a window.ZoomWindow(partcode, 1)
795n/a rect = window.GetWindowUserState() # so that zoom really works... jvr
796n/a self.do_postresize(rect[2] - rect[0], rect[3] - rect[1], window) # jvr
797n/a
798n/a def do_inZoomIn(self, partcode, window, event):
799n/a SetPort(window) # !!!
800n/a self.do_inZoom(partcode, window, event)
801n/a
802n/a def do_inZoomOut(self, partcode, window, event):
803n/a SetPort(window) # !!!
804n/a self.do_inZoom(partcode, window, event)
805n/a
806n/a def do_inGrow(self, partcode, window, event):
807n/a (what, message, when, where, modifiers) = event
808n/a result = window.GrowWindow(where, self.growlimit)
809n/a if result:
810n/a height = (result>>16) & 0xffff # Hi word
811n/a width = result & 0xffff # Lo word
812n/a self.do_resize(width, height, window)
813n/a
814n/a growlimit = (50, 50, screenbounds[2] - screenbounds[0], screenbounds[3] - screenbounds[1]) # jvr
815n/a
816n/a def do_resize(self, width, height, window):
817n/a l, t, r, b = self.wid.GetWindowPort().GetPortBounds() # jvr, forGrowIcon
818n/a self.SetPort() # jvr
819n/a self.wid.InvalWindowRect((r - SCROLLBARWIDTH + 1, b - SCROLLBARWIDTH + 1, r, b)) # jvr
820n/a window.SizeWindow(width, height, 1) # changed updateFlag to true jvr
821n/a self.do_postresize(width, height, window)
822n/a
823n/a def do_postresize(self, width, height, window):
824n/a SetPort(window)
825n/a self.wid.InvalWindowRect(window.GetWindowPort().GetPortBounds())
826n/a
827n/a def do_inContent(self, partcode, window, event):
828n/a #
829n/a # If we're not frontmost, select ourselves and wait for
830n/a # the activate event.
831n/a #
832n/a if MyFrontWindow() != window:
833n/a window.SelectWindow()
834n/a return
835n/a # We are. Handle the event.
836n/a (what, message, when, where, modifiers) = event
837n/a SetPort(window)
838n/a local = GlobalToLocal(where)
839n/a self.do_contentclick(local, modifiers, event)
840n/a
841n/a def do_contentclick(self, local, modifiers, event):
842n/a if DEBUG:
843n/a print 'Click in contents at %s, modifiers %s'%(local, modifiers)
844n/a
845n/a def do_rawupdate(self, window, event):
846n/a if DEBUG: print "raw update for", window
847n/a SetPort(window)
848n/a window.BeginUpdate()
849n/a self.do_update(window, event)
850n/a window.EndUpdate()
851n/a
852n/a def do_update(self, window, event):
853n/a if DEBUG:
854n/a import time
855n/a for i in range(8):
856n/a time.sleep(0.1)
857n/a InvertRgn(window.GetWindowPort().visRgn)
858n/a FillRgn(window.GetWindowPort().visRgn, GetQDGlobalsGray())
859n/a else:
860n/a EraseRgn(window.GetWindowPort().visRgn)
861n/a
862n/a def do_activate(self, activate, event):
863n/a if DEBUG: print 'Activate %d for %s'%(activate, self.wid)
864n/a
865n/aclass ControlsWindow(Window):
866n/a
867n/a def do_rawupdate(self, window, event):
868n/a if DEBUG: print "raw update for", window
869n/a SetPort(window)
870n/a window.BeginUpdate()
871n/a self.do_update(window, event)
872n/a #DrawControls(window) # jvr
873n/a UpdateControls(window, window.GetWindowPort().visRgn) # jvr
874n/a window.DrawGrowIcon()
875n/a window.EndUpdate()
876n/a
877n/a def do_controlhit(self, window, control, pcode, event):
878n/a if DEBUG: print "control hit in", window, "on", control, "; pcode =", pcode
879n/a
880n/a def do_inContent(self, partcode, window, event):
881n/a if MyFrontWindow() != window:
882n/a window.SelectWindow()
883n/a return
884n/a (what, message, when, where, modifiers) = event
885n/a SetPort(window) # XXXX Needed?
886n/a local = GlobalToLocal(where)
887n/a pcode, control = FindControl(local, window)
888n/a if pcode and control:
889n/a self.do_rawcontrolhit(window, control, pcode, local, event)
890n/a else:
891n/a if DEBUG: print "FindControl(%s, %s) -> (%s, %s)" % \
892n/a (local, window, pcode, control)
893n/a self.do_contentclick(local, modifiers, event)
894n/a
895n/a def do_rawcontrolhit(self, window, control, pcode, local, event):
896n/a pcode = control.TrackControl(local)
897n/a if pcode:
898n/a self.do_controlhit(window, control, pcode, event)
899n/a
900n/aclass ScrolledWindow(ControlsWindow):
901n/a def __init__(self, parent):
902n/a self.barx = self.bary = None
903n/a self.barx_enabled = self.bary_enabled = 1
904n/a self.activated = 1
905n/a ControlsWindow.__init__(self, parent)
906n/a
907n/a def scrollbars(self, wantx=1, wanty=1):
908n/a SetPort(self.wid)
909n/a self.barx = self.bary = None
910n/a self.barx_enabled = self.bary_enabled = 1
911n/a x0, y0, x1, y1 = self.wid.GetWindowPort().GetPortBounds()
912n/a vx, vy = self.getscrollbarvalues()
913n/a if vx is None: self.barx_enabled, vx = 0, 0
914n/a if vy is None: self.bary_enabled, vy = 0, 0
915n/a if wantx:
916n/a rect = x0-1, y1-(SCROLLBARWIDTH-1), x1-(SCROLLBARWIDTH-2), y1+1
917n/a self.barx = NewControl(self.wid, rect, "", 1, vx, 0, 32767, 16, 0)
918n/a if not self.barx_enabled: self.barx.HiliteControl(255)
919n/a## self.wid.InvalWindowRect(rect)
920n/a if wanty:
921n/a rect = x1-(SCROLLBARWIDTH-1), y0-1, x1+1, y1-(SCROLLBARWIDTH-2)
922n/a self.bary = NewControl(self.wid, rect, "", 1, vy, 0, 32767, 16, 0)
923n/a if not self.bary_enabled: self.bary.HiliteControl(255)
924n/a## self.wid.InvalWindowRect(rect)
925n/a
926n/a def do_postclose(self):
927n/a self.barx = self.bary = None
928n/a ControlsWindow.do_postclose(self)
929n/a
930n/a def do_activate(self, onoff, event):
931n/a self.activated = onoff
932n/a if onoff:
933n/a if self.barx and self.barx_enabled:
934n/a self.barx.ShowControl() # jvr
935n/a if self.bary and self.bary_enabled:
936n/a self.bary.ShowControl() # jvr
937n/a else:
938n/a if self.barx:
939n/a self.barx.HideControl() # jvr; An inactive window should have *hidden*
940n/a # scrollbars, not just dimmed (no matter what
941n/a # BBEdit does... look at the Finder)
942n/a if self.bary:
943n/a self.bary.HideControl() # jvr
944n/a self.wid.DrawGrowIcon() # jvr
945n/a
946n/a def do_postresize(self, width, height, window):
947n/a l, t, r, b = self.wid.GetWindowPort().GetPortBounds()
948n/a self.SetPort()
949n/a if self.barx:
950n/a self.barx.HideControl() # jvr
951n/a self.barx.MoveControl(l-1, b-(SCROLLBARWIDTH-1))
952n/a self.barx.SizeControl((r-l)-(SCROLLBARWIDTH-3), SCROLLBARWIDTH) # jvr
953n/a if self.bary:
954n/a self.bary.HideControl() # jvr
955n/a self.bary.MoveControl(r-(SCROLLBARWIDTH-1), t-1)
956n/a self.bary.SizeControl(SCROLLBARWIDTH, (b-t)-(SCROLLBARWIDTH-3)) # jvr
957n/a if self.barx:
958n/a self.barx.ShowControl() # jvr
959n/a self.wid.ValidWindowRect((l, b - SCROLLBARWIDTH + 1, r - SCROLLBARWIDTH + 2, b)) # jvr
960n/a if self.bary:
961n/a self.bary.ShowControl() # jvr
962n/a self.wid.ValidWindowRect((r - SCROLLBARWIDTH + 1, t, r, b - SCROLLBARWIDTH + 2)) # jvr
963n/a self.wid.InvalWindowRect((r - SCROLLBARWIDTH + 1, b - SCROLLBARWIDTH + 1, r, b)) # jvr, growicon
964n/a
965n/a
966n/a def do_rawcontrolhit(self, window, control, pcode, local, event):
967n/a if control == self.barx:
968n/a which = 'x'
969n/a elif control == self.bary:
970n/a which = 'y'
971n/a else:
972n/a return 0
973n/a if pcode in (inUpButton, inDownButton, inPageUp, inPageDown):
974n/a # We do the work for the buttons and grey area in the tracker
975n/a dummy = control.TrackControl(local, self.do_controltrack)
976n/a else:
977n/a # but the thumb is handled here
978n/a pcode = control.TrackControl(local)
979n/a if pcode == inThumb:
980n/a value = control.GetControlValue()
981n/a print 'setbars', which, value #DBG
982n/a self.scrollbar_callback(which, 'set', value)
983n/a self.updatescrollbars()
984n/a else:
985n/a print 'funny part', pcode #DBG
986n/a return 1
987n/a
988n/a def do_controltrack(self, control, pcode):
989n/a if control == self.barx:
990n/a which = 'x'
991n/a elif control == self.bary:
992n/a which = 'y'
993n/a else:
994n/a return
995n/a
996n/a if pcode == inUpButton:
997n/a what = '-'
998n/a elif pcode == inDownButton:
999n/a what = '+'
1000n/a elif pcode == inPageUp:
1001n/a what = '--'
1002n/a elif pcode == inPageDown:
1003n/a what = '++'
1004n/a else:
1005n/a return
1006n/a self.scrollbar_callback(which, what, None)
1007n/a self.updatescrollbars()
1008n/a
1009n/a def updatescrollbars(self):
1010n/a SetPort(self.wid)
1011n/a vx, vy = self.getscrollbarvalues()
1012n/a if self.barx:
1013n/a if vx is None:
1014n/a self.barx.HiliteControl(255)
1015n/a self.barx_enabled = 0
1016n/a else:
1017n/a if not self.barx_enabled:
1018n/a self.barx_enabled = 1
1019n/a if self.activated:
1020n/a self.barx.HiliteControl(0)
1021n/a self.barx.SetControlValue(vx)
1022n/a if self.bary:
1023n/a if vy is None:
1024n/a self.bary.HiliteControl(255)
1025n/a self.bary_enabled = 0
1026n/a else:
1027n/a if not self.bary_enabled:
1028n/a self.bary_enabled = 1
1029n/a if self.activated:
1030n/a self.bary.HiliteControl(0)
1031n/a self.bary.SetControlValue(vy)
1032n/a
1033n/a # Auxiliary function: convert standard text/image/etc coordinate
1034n/a # to something palatable as getscrollbarvalues() return
1035n/a def scalebarvalue(self, absmin, absmax, curmin, curmax):
1036n/a if curmin <= absmin and curmax >= absmax:
1037n/a return None
1038n/a if curmin <= absmin:
1039n/a return 0
1040n/a if curmax >= absmax:
1041n/a return 32767
1042n/a perc = float(curmin-absmin)/float(absmax-absmin)
1043n/a return int(perc*32767)
1044n/a
1045n/a # To be overridden:
1046n/a
1047n/a def getscrollbarvalues(self):
1048n/a return 0, 0
1049n/a
1050n/a def scrollbar_callback(self, which, what, value):
1051n/a print 'scroll', which, what, value
1052n/a
1053n/aclass DialogWindow(Window):
1054n/a """A modeless dialog window"""
1055n/a
1056n/a def open(self, resid):
1057n/a self.dlg = GetNewDialog(resid, -1)
1058n/a self.wid = self.dlg.GetDialogWindow()
1059n/a self.do_postopen()
1060n/a
1061n/a def close(self):
1062n/a self.do_postclose()
1063n/a
1064n/a def do_postclose(self):
1065n/a self.dlg = None
1066n/a Window.do_postclose(self)
1067n/a
1068n/a def do_itemhit(self, item, event):
1069n/a print 'Dialog %s, item %d hit'%(self.dlg, item)
1070n/a
1071n/a def do_rawupdate(self, window, event):
1072n/a pass
1073n/a
1074n/adef ostypecode(x):
1075n/a "Convert a long int to the 4-character code it really is"
1076n/a s = ''
1077n/a for i in range(4):
1078n/a x, c = divmod(x, 256)
1079n/a s = chr(c) + s
1080n/a return s
1081n/a
1082n/a
1083n/aclass TestApp(Application):
1084n/a
1085n/a "This class is used by the test() function"
1086n/a
1087n/a def makeusermenus(self):
1088n/a self.filemenu = m = Menu(self.menubar, "File")
1089n/a self.saveitem = MenuItem(m, "Save", "S", self.save)
1090n/a Separator(m)
1091n/a self.optionsmenu = mm = SubMenu(m, "Options")
1092n/a self.opt1 = CheckItem(mm, "Arguments", "A")
1093n/a self.opt2 = CheckItem(mm, "Being hit on the head lessons", (kMenuOptionModifier, "A"))
1094n/a self.opt3 = CheckItem(mm, "Complaints", (kMenuOptionModifier|kMenuNoCommandModifier, "A"))
1095n/a Separator(m)
1096n/a self.itemeh = MenuItem(m, "Enable Help", None, self.enablehelp)
1097n/a self.itemdbg = MenuItem(m, "Debug", None, self.debug)
1098n/a Separator(m)
1099n/a self.quititem = MenuItem(m, "Quit", "Q", self.quit)
1100n/a
1101n/a def save(self, *args):
1102n/a print "Save"
1103n/a
1104n/a def quit(self, *args):
1105n/a raise self
1106n/a
1107n/a def enablehelp(self, *args):
1108n/a hm = self.gethelpmenu()
1109n/a self.nohelpitem = MenuItem(hm, "There isn't any", None, self.nohelp)
1110n/a
1111n/a def nohelp(self, *args):
1112n/a print "I told you there isn't any!"
1113n/a
1114n/a def debug(self, *args):
1115n/a import pdb
1116n/a pdb.set_trace()
1117n/a
1118n/a
1119n/adef test():
1120n/a "Test program"
1121n/a app = TestApp()
1122n/a app.mainloop()
1123n/a
1124n/a
1125n/aif __name__ == '__main__':
1126n/a test()