blob: ec0071f22bb72439cd6e00d007b2a2f992f28d51 [file] [log] [blame]
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001import FrameWork
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00002from Carbon import Win
3from Carbon import Qd
4from Carbon import Evt
Just van Rossum40f9b7b1999-01-30 22:39:17 +00005import MacOS
Jack Jansendc4d9252001-08-27 10:55:41 +00006from Carbon import Events
Just van Rossum40f9b7b1999-01-30 22:39:17 +00007import traceback
8from types import *
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00009from Carbon import Menu; MenuToolbox = Menu; del Menu
Just van Rossum40f9b7b1999-01-30 22:39:17 +000010
Just van Rossum40144012002-02-04 12:52:44 +000011if hasattr(Win, "FrontNonFloatingWindow"):
12 MyFrontWindow = Win.FrontNonFloatingWindow
13else:
14 MyFrontWindow = Win.FrontWindow
15
16
Just van Rossumf376ef02001-11-18 14:12:43 +000017KILLUNKNOWNWINDOWS = 0 # Set to 0 for debugging.
Just van Rossum40f9b7b1999-01-30 22:39:17 +000018
19class Application(FrameWork.Application):
20
21 def __init__(self, signature='Pyth'):
22 import W
23 W.setapplication(self, signature)
24 FrameWork.Application.__init__(self)
25 self._suspended = 0
26 self.quitting = 0
27 self.debugger_quitting = 1
28 self.DebuggerQuit = 'DebuggerQuitDummyException'
29 self._idlefuncs = []
30 # map certain F key codes to equivalent command-letter combos (JJS)
31 self.fkeymaps = {122:"z", 120:"x", 99:"c", 118:"v"}
32
Jack Jansene5c94742001-03-08 23:10:37 +000033 def mainloop(self, mask=FrameWork.everyEvent, wait=None):
Just van Rossum40f9b7b1999-01-30 22:39:17 +000034 import W
35 self.quitting = 0
Jack Jansen815d2bf2002-01-21 23:00:52 +000036 if hasattr(MacOS, 'EnableAppswitch'):
37 saveyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000038 try:
39 while not self.quitting:
40 try:
41 self.do1event(mask, wait)
42 except W.AlertError, detail:
Jack Jansen815d2bf2002-01-21 23:00:52 +000043 if hasattr(MacOS, 'EnableAppswitch'):
44 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000045 W.Message(detail)
46 except self.DebuggerQuit:
Jack Jansen815d2bf2002-01-21 23:00:52 +000047 if hasattr(MacOS, 'EnableAppswitch'):
48 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000049 except:
Jack Jansen815d2bf2002-01-21 23:00:52 +000050 if hasattr(MacOS, 'EnableAppswitch'):
51 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000052 import PyEdit
53 PyEdit.tracebackwindow.traceback()
54 finally:
Jack Jansen815d2bf2002-01-21 23:00:52 +000055 if hasattr(MacOS, 'EnableAppswitch'):
56 MacOS.EnableAppswitch(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000057
Jack Jansene5c94742001-03-08 23:10:37 +000058 def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=None):
Just van Rossum40f9b7b1999-01-30 22:39:17 +000059 import W
60 self.debugger_quitting = 0
Jack Jansen815d2bf2002-01-21 23:00:52 +000061 if hasattr(MacOS, 'EnableAppswitch'):
62 saveyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000063 try:
64 while not self.quitting and not self.debugger_quitting:
65 try:
66 self.do1event(mask, wait)
67 except W.AlertError, detail:
68 W.Message(detail)
69 except:
70 import PyEdit
71 PyEdit.tracebackwindow.traceback()
72 finally:
Jack Jansen815d2bf2002-01-21 23:00:52 +000073 if hasattr(MacOS, 'EnableAppswitch'):
74 MacOS.EnableAppswitch(saveyield)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000075
76 def breathe(self, wait=1):
77 import W
78 ok, event = Evt.WaitNextEvent(FrameWork.updateMask |
79 FrameWork.mDownMask | FrameWork.osMask |
80 FrameWork.activMask,
81 wait)
82 if ok:
83 (what, message, when, where, modifiers) = event
84 #print FrameWork.eventname[what]
85 if FrameWork.eventname[what] == 'mouseDown':
86 partcode, wid = Win.FindWindow(where)
87 if FrameWork.partname[partcode] <> 'inDesk':
88 return
89 else:
90 W.SetCursor('watch')
91 self.dispatch(event)
92
93 def refreshwindows(self, wait=1):
94 import W
95 while 1:
96 ok, event = Evt.WaitNextEvent(FrameWork.updateMask, wait)
97 if not ok:
98 break
99 self.dispatch(event)
100
101 def addidlefunc(self, func):
102 self._idlefuncs.append(func)
103
104 def removeidlefunc(self, func):
105 self._idlefuncs.remove(func)
106
107 def idle(self, event):
108 if not self._suspended:
109 if not self.do_frontWindowMethod("idle", event):
110 Qd.InitCursor()
111 if self._idlefuncs:
112 for func in self._idlefuncs:
113 try:
114 func()
115 except:
116 import sys
117 sys.stderr.write("exception in idle function %s; killed:\n" % `func`)
118 traceback.print_exc()
119 self._idlefuncs.remove(func)
120 break
121
122 def do_frontWindowMethod(self, attr, *args):
Just van Rossum40144012002-02-04 12:52:44 +0000123 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000124 if wid and self._windows.has_key(wid):
125 window = self._windows[wid]
126 if hasattr(window, attr):
127 handler = getattr(window, attr)
128 apply(handler, args)
129 return 1
130
131 def appendwindow(self, wid, window):
132 self._windows[wid] = window
133 self.makeopenwindowsmenu()
134
135 def removewindow(self, wid):
136 del self._windows[wid]
137 self.makeopenwindowsmenu()
138
Just van Rossumd4bdbf11999-02-26 21:30:19 +0000139 def makeopenwindowsmenu(self):
140 # dummy; could be the full version from PythonIDEMain.py
141 self._openwindows = {}
142 self._openwindowscheckmark = 0
143 if not hasattr(self, "_menustocheck"):
144 self._menustocheck = []
145
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000146 def do_key(self, event):
147 (what, message, when, where, modifiers) = event
148 ch = chr(message & FrameWork.charCodeMask)
149 rest = message & ~FrameWork.charCodeMask
150 keycode = (message & FrameWork.keyCodeMask) >> 8
151 if keycode in self.fkeymaps.keys(): # JJS
152 ch = self.fkeymaps[keycode]
153 modifiers = modifiers | FrameWork.cmdKey
Just van Rossum40144012002-02-04 12:52:44 +0000154 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000155 if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
156 if wid and self._windows.has_key(wid):
157 self.checkmenus(self._windows[wid])
158 else:
159 self.checkmenus(None)
160 event = (what, ord(ch) | rest, when, where, modifiers)
161 result = MenuToolbox.MenuKey(ord(ch))
162 id = (result>>16) & 0xffff # Hi word
163 item = result & 0xffff # Lo word
164 if id:
165 self.do_rawmenu(id, item, None, event)
166 return # here! we had a menukey!
167 #else:
168 # print "XXX Command-" +`ch`
169 # See whether the front window wants it
170 if wid and self._windows.has_key(wid):
171 window = self._windows[wid]
172 try:
173 do_char = window.do_char
174 except AttributeError:
175 do_char = self.do_char
176 do_char(ch, event)
177 # else it wasn't for us, sigh...
178
179 def do_inMenuBar(self, partcode, window, event):
180 Qd.InitCursor()
181 (what, message, when, where, modifiers) = event
182 self.checkopenwindowsmenu()
Just van Rossum40144012002-02-04 12:52:44 +0000183 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000184 if wid and self._windows.has_key(wid):
185 self.checkmenus(self._windows[wid])
186 else:
187 self.checkmenus(None)
188 result = MenuToolbox.MenuSelect(where)
189 id = (result>>16) & 0xffff # Hi word
190 item = result & 0xffff # Lo word
191 self.do_rawmenu(id, item, window, event)
192
193 def do_updateEvt(self, event):
194 (what, message, when, where, modifiers) = event
195 wid = Win.WhichWindow(message)
196 if wid and self._windows.has_key(wid):
197 window = self._windows[wid]
198 window.do_rawupdate(wid, event)
199 else:
Jack Jansendc4d9252001-08-27 10:55:41 +0000200 if KILLUNKNOWNWINDOWS and wid:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000201 wid.HideWindow()
202 import sys
203 sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
204 else:
Jack Jansenb9e66612002-03-21 22:36:57 +0000205 if hasattr(MacOS, 'HandleEvent'):
206 MacOS.HandleEvent(event)
207 else:
208 print 'Unexpected updateEvent:', event
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000209
210 def suspendresume(self, onoff):
211 pass
212
213 def do_suspendresume(self, event):
214 self._suspended = not event[1] & 1
215 FrameWork.Application.do_suspendresume(self, event)
216
217 def checkopenwindowsmenu(self):
218 if self._openwindowscheckmark:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000219 self.openwindowsmenu.menu.CheckMenuItem(self._openwindowscheckmark, 0)
Just van Rossum40144012002-02-04 12:52:44 +0000220 window = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000221 if window:
222 for item, wid in self._openwindows.items():
223 if wid == window:
224 #self.pythonwindowsmenuitem.check(1)
Jack Jansenafd0aa62001-01-29 13:29:47 +0000225 self.openwindowsmenu.menu.CheckMenuItem(item, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000226 self._openwindowscheckmark = item
227 break
228 else:
229 self._openwindowscheckmark = 0
230 #if self._openwindows:
231 # self.pythonwindowsmenuitem.enable(1)
232 #else:
233 # self.pythonwindowsmenuitem.enable(0)
234
235 def checkmenus(self, window):
236 for item in self._menustocheck:
237 callback = item.menu.items[item.item-1][2]
238 if type(callback) <> StringType:
239 item.enable(1)
240 elif hasattr(window, "domenu_" + callback):
241 if hasattr(window, "can_" + callback):
242 canhandler = getattr(window, "can_" + callback)
243 if canhandler(item):
244 item.enable(1)
245 else:
246 item.enable(0)
247 else:
248 item.enable(1)
249 else:
250 item.enable(0)
251
252 def enablemenubar(self, onoff):
253 for m in self.menubar.menus.values():
254 if onoff:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000255 m.menu.EnableMenuItem(0)
Just van Rossum4798c4e1999-02-27 17:15:32 +0000256 elif m.menu.GetMenuItemText(3) <> 'Cut': # ew...
Jack Jansenafd0aa62001-01-29 13:29:47 +0000257 m.menu.DisableMenuItem(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000258 MenuToolbox.DrawMenuBar()
259
260 def makemenubar(self):
261 self.menubar = MenuBar(self)
262 FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
263 self.makeusermenus()
Just van Rossum7171df31999-10-30 11:46:18 +0000264
265 def scriptswalk(self, top, menu, done=None):
266 if done is None:
267 done = {}
268 if done.has_key(top):
269 return
270 done[top] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000271 import os, macfs, string
272 try:
273 names = os.listdir(top)
274 except os.error:
275 FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
276 return
277 savedir = os.getcwd()
278 os.chdir(top)
279 for name in names:
Just van Rossum6dc2b571999-12-23 21:50:26 +0000280 if name == "CVS":
281 continue
282 try:
283 fss, isdir, isalias = macfs.ResolveAliasFile(name)
284 except:
285 # maybe a broken alias
286 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000287 path = fss.as_pathname()
Just van Rossum7171df31999-10-30 11:46:18 +0000288 if done.has_key(path):
289 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000290 name = string.strip(name)
291 if name[-3:] == '---':
292 menu.addseparator()
293 elif isdir:
294 submenu = FrameWork.SubMenu(menu, name)
Just van Rossum7171df31999-10-30 11:46:18 +0000295 self.scriptswalk(path, submenu, done)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000296 else:
297 creator, type = fss.GetCreatorType()
298 if type == 'TEXT':
299 if name[-3:] == '.py':
300 name = name[:-3]
301 item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
302 self._scripts[(menu.id, item.item)] = path
Just van Rossum7171df31999-10-30 11:46:18 +0000303 done[path] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000304 os.chdir(savedir)
305
306 def domenu_script(self, id, item, window, event):
307 (what, message, when, where, modifiers) = event
308 path = self._scripts[(id, item)]
309 import os
310 if not os.path.exists(path):
311 self.makescriptsmenu()
312 import W
313 raise W.AlertError, "File not found."
314 if ord(Evt.GetKeys()[7]) & 4:
315 self.openscript(path)
316 else:
317 import W, MacOS, sys
318 W.SetCursor("watch")
319 sys.argv = [path]
320 #cwd = os.getcwd()
321 #os.chdir(os.path.dirname(path) + ':')
322 try:
323 # xxx if there is a script window for this file,
324 # exec in that window's namespace.
325 # xxx what to do when it's not saved???
326 # promt to save?
Jack Jansen815d2bf2002-01-21 23:00:52 +0000327 if hasattr(MacOS, 'EnableAppswitch'):
328 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000329 execfile(path, {'__name__': '__main__', '__file__': path})
330 except W.AlertError, detail:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000331 if hasattr(MacOS, 'EnableAppswitch'):
332 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000333 raise W.AlertError, detail
334 except KeyboardInterrupt:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000335 if hasattr(MacOS, 'EnableAppswitch'):
336 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000337 except:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000338 if hasattr(MacOS, 'EnableAppswitch'):
339 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000340 import PyEdit
341 PyEdit.tracebackwindow.traceback(1)
342 else:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000343 if hasattr(MacOS, 'EnableAppswitch'):
344 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000345 #os.chdir(cwd)
346
347 def openscript(self, filename, lineno=None, charoffset=0, modname=""):
348 import os, PyEdit, W
349 editor = self.getscript(filename)
350 if editor:
351 editor.select()
352 elif os.path.exists(filename):
353 editor = PyEdit.Editor(filename)
354 elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
355 import imp
356 if not modname:
357 if filename[-1] == 'c':
358 modname = os.path.basename(filename)[:-4]
359 else:
360 modname = os.path.basename(filename)[:-3]
361 try:
362 # XXX This does not work correctly with packages!
363 # XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
364 # XXX It says we should use imp.load_module(), but that *reloads* a package,
365 # XXX and that's the last thing we want here.
366 f, filename, (suff, mode, dummy) = imp.find_module(modname)
367 except ImportError:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000368 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000369 else:
370 if not f:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000371 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000372 f.close()
373 if suff == '.py':
374 self.openscript(filename, lineno, charoffset)
375 return
376 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000377 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000378 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000379 raise W.AlertError, "Can't find file \"%s\"" % filename
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000380 if lineno is not None:
381 editor.selectline(lineno, charoffset)
382 return editor
383
384 def getscript(self, filename):
385 if filename[:1] == '<' and filename[-1:] == '>':
386 filename = filename[1:-1]
387 import string
388 lowpath = string.lower(filename)
389 for wid, window in self._windows.items():
Just van Rossum7171df31999-10-30 11:46:18 +0000390 if hasattr(window, "path") and type(window.path) == StringType and \
391 lowpath == string.lower(window.path):
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000392 return window
393 elif hasattr(window, "path") and filename == wid.GetWTitle():
394 return window
395
396 def getprefs(self):
397 import MacPrefs
398 return MacPrefs.GetPrefs(self.preffilepath)
Just van Rossum2a759091999-09-26 12:18:19 +0000399
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000400 def do_editorprefs(self, *args):
401 import PyEdit
402 PyEdit.EditorDefaultSettings()
403
Just van Rossum2a759091999-09-26 12:18:19 +0000404 def do_setwindowfont(self, *args):
405 import FontSettings, W
406 prefs = self.getprefs()
407 settings = FontSettings.FontDialog(prefs.defaultfont)
408 if settings:
409 prefs.defaultfont, tabsettings = settings
410 raise W.AlertError, "Note that changes will only affect new windows!"
411
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000412
413
414class MenuBar(FrameWork.MenuBar):
415
416 possibleIDs = range(10, 256)
417
418 def getnextid(self):
419 id = self.possibleIDs[0]
420 del self.possibleIDs[0]
421 return id
422
423 def __init__(self, parent = None):
424 self.bar = MenuToolbox.GetMenuBar()
425 MenuToolbox.ClearMenuBar()
426 self.menus = {}
427 self.parent = parent
428
429 def dispatch(self, id, item, window, event):
430 if self.menus.has_key(id):
431 self.menus[id].dispatch(id, item, window, event)
432
433 def delmenu(self, id):
434 MenuToolbox.DeleteMenu(id)
435 if id in self.possibleIDs:
436 print "XXX duplicate menu ID!", id
437 self.possibleIDs.append(id)
438
439
440class Menu(FrameWork.Menu):
441
442 def dispatch(self, id, item, window, event):
443 title, shortcut, callback, kind = self.items[item-1]
444 if type(callback) == StringType:
445 callback = self._getmenuhandler(callback)
446 if callback:
447 import W
448 W.CallbackCall(callback, 0, id, item, window, event)
449
450 def _getmenuhandler(self, callback):
451 menuhandler = None
Just van Rossum40144012002-02-04 12:52:44 +0000452 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000453 if wid and self.bar.parent._windows.has_key(wid):
454 window = self.bar.parent._windows[wid]
455 if hasattr(window, "domenu_" + callback):
456 menuhandler = getattr(window, "domenu_" + callback)
457 elif hasattr(self.bar.parent, "domenu_" + callback):
458 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
459 elif hasattr(self.bar.parent, "domenu_" + callback):
460 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
461 return menuhandler
462