blob: f78ef5e0a6cf5fb3369992435387f491cae9c19d [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
Jack Jansene9c03582002-04-03 21:52:10 +000010import macresource
Just van Rossum40f9b7b1999-01-30 22:39:17 +000011
Just van Rossum40144012002-02-04 12:52:44 +000012if hasattr(Win, "FrontNonFloatingWindow"):
13 MyFrontWindow = Win.FrontNonFloatingWindow
14else:
15 MyFrontWindow = Win.FrontWindow
16
17
Just van Rossumf376ef02001-11-18 14:12:43 +000018KILLUNKNOWNWINDOWS = 0 # Set to 0 for debugging.
Just van Rossum40f9b7b1999-01-30 22:39:17 +000019
20class Application(FrameWork.Application):
21
22 def __init__(self, signature='Pyth'):
Jack Jansene9c03582002-04-03 21:52:10 +000023 # Open our resource file, if it is not open yet
24 macresource.need('CURS', 468, "Widgets.rsrc")
Just van Rossum40f9b7b1999-01-30 22:39:17 +000025 import W
26 W.setapplication(self, signature)
27 FrameWork.Application.__init__(self)
28 self._suspended = 0
29 self.quitting = 0
30 self.debugger_quitting = 1
31 self.DebuggerQuit = 'DebuggerQuitDummyException'
32 self._idlefuncs = []
33 # map certain F key codes to equivalent command-letter combos (JJS)
34 self.fkeymaps = {122:"z", 120:"x", 99:"c", 118:"v"}
35
Jack Jansene5c94742001-03-08 23:10:37 +000036 def mainloop(self, mask=FrameWork.everyEvent, wait=None):
Just van Rossum40f9b7b1999-01-30 22:39:17 +000037 import W
38 self.quitting = 0
Jack Jansen815d2bf2002-01-21 23:00:52 +000039 if hasattr(MacOS, 'EnableAppswitch'):
40 saveyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000041 try:
42 while not self.quitting:
43 try:
44 self.do1event(mask, wait)
45 except W.AlertError, detail:
Jack Jansen815d2bf2002-01-21 23:00:52 +000046 if hasattr(MacOS, 'EnableAppswitch'):
47 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000048 W.Message(detail)
49 except self.DebuggerQuit:
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 except:
Jack Jansen815d2bf2002-01-21 23:00:52 +000053 if hasattr(MacOS, 'EnableAppswitch'):
54 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000055 import PyEdit
56 PyEdit.tracebackwindow.traceback()
57 finally:
Jack Jansen815d2bf2002-01-21 23:00:52 +000058 if hasattr(MacOS, 'EnableAppswitch'):
59 MacOS.EnableAppswitch(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000060
Jack Jansene5c94742001-03-08 23:10:37 +000061 def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=None):
Just van Rossum40f9b7b1999-01-30 22:39:17 +000062 import W
63 self.debugger_quitting = 0
Jack Jansen815d2bf2002-01-21 23:00:52 +000064 if hasattr(MacOS, 'EnableAppswitch'):
65 saveyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000066 try:
67 while not self.quitting and not self.debugger_quitting:
68 try:
69 self.do1event(mask, wait)
70 except W.AlertError, detail:
71 W.Message(detail)
72 except:
73 import PyEdit
74 PyEdit.tracebackwindow.traceback()
75 finally:
Jack Jansen815d2bf2002-01-21 23:00:52 +000076 if hasattr(MacOS, 'EnableAppswitch'):
77 MacOS.EnableAppswitch(saveyield)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000078
79 def breathe(self, wait=1):
80 import W
81 ok, event = Evt.WaitNextEvent(FrameWork.updateMask |
82 FrameWork.mDownMask | FrameWork.osMask |
83 FrameWork.activMask,
84 wait)
85 if ok:
86 (what, message, when, where, modifiers) = event
87 #print FrameWork.eventname[what]
88 if FrameWork.eventname[what] == 'mouseDown':
89 partcode, wid = Win.FindWindow(where)
90 if FrameWork.partname[partcode] <> 'inDesk':
91 return
92 else:
93 W.SetCursor('watch')
94 self.dispatch(event)
95
96 def refreshwindows(self, wait=1):
97 import W
98 while 1:
99 ok, event = Evt.WaitNextEvent(FrameWork.updateMask, wait)
100 if not ok:
101 break
102 self.dispatch(event)
103
104 def addidlefunc(self, func):
105 self._idlefuncs.append(func)
106
107 def removeidlefunc(self, func):
108 self._idlefuncs.remove(func)
109
110 def idle(self, event):
111 if not self._suspended:
112 if not self.do_frontWindowMethod("idle", event):
113 Qd.InitCursor()
114 if self._idlefuncs:
115 for func in self._idlefuncs:
116 try:
117 func()
118 except:
119 import sys
120 sys.stderr.write("exception in idle function %s; killed:\n" % `func`)
121 traceback.print_exc()
122 self._idlefuncs.remove(func)
123 break
124
125 def do_frontWindowMethod(self, attr, *args):
Just van Rossum40144012002-02-04 12:52:44 +0000126 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000127 if wid and self._windows.has_key(wid):
128 window = self._windows[wid]
129 if hasattr(window, attr):
130 handler = getattr(window, attr)
131 apply(handler, args)
132 return 1
133
134 def appendwindow(self, wid, window):
135 self._windows[wid] = window
136 self.makeopenwindowsmenu()
137
138 def removewindow(self, wid):
139 del self._windows[wid]
140 self.makeopenwindowsmenu()
141
Just van Rossumd4bdbf11999-02-26 21:30:19 +0000142 def makeopenwindowsmenu(self):
143 # dummy; could be the full version from PythonIDEMain.py
144 self._openwindows = {}
145 self._openwindowscheckmark = 0
146 if not hasattr(self, "_menustocheck"):
147 self._menustocheck = []
148
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000149 def do_key(self, event):
150 (what, message, when, where, modifiers) = event
151 ch = chr(message & FrameWork.charCodeMask)
152 rest = message & ~FrameWork.charCodeMask
153 keycode = (message & FrameWork.keyCodeMask) >> 8
154 if keycode in self.fkeymaps.keys(): # JJS
155 ch = self.fkeymaps[keycode]
156 modifiers = modifiers | FrameWork.cmdKey
Just van Rossum40144012002-02-04 12:52:44 +0000157 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000158 if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
159 if wid and self._windows.has_key(wid):
160 self.checkmenus(self._windows[wid])
161 else:
162 self.checkmenus(None)
163 event = (what, ord(ch) | rest, when, where, modifiers)
164 result = MenuToolbox.MenuKey(ord(ch))
165 id = (result>>16) & 0xffff # Hi word
166 item = result & 0xffff # Lo word
167 if id:
168 self.do_rawmenu(id, item, None, event)
169 return # here! we had a menukey!
170 #else:
171 # print "XXX Command-" +`ch`
172 # See whether the front window wants it
173 if wid and self._windows.has_key(wid):
174 window = self._windows[wid]
175 try:
176 do_char = window.do_char
177 except AttributeError:
178 do_char = self.do_char
179 do_char(ch, event)
180 # else it wasn't for us, sigh...
181
182 def do_inMenuBar(self, partcode, window, event):
183 Qd.InitCursor()
184 (what, message, when, where, modifiers) = event
185 self.checkopenwindowsmenu()
Just van Rossum40144012002-02-04 12:52:44 +0000186 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000187 if wid and self._windows.has_key(wid):
188 self.checkmenus(self._windows[wid])
189 else:
190 self.checkmenus(None)
191 result = MenuToolbox.MenuSelect(where)
192 id = (result>>16) & 0xffff # Hi word
Jack Jansenf94cadf2002-08-31 01:20:53 +0000193 if id >= 0x8000:
194 id = -0x10000 + id
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000195 item = result & 0xffff # Lo word
196 self.do_rawmenu(id, item, window, event)
197
198 def do_updateEvt(self, event):
199 (what, message, when, where, modifiers) = event
200 wid = Win.WhichWindow(message)
201 if wid and self._windows.has_key(wid):
202 window = self._windows[wid]
203 window.do_rawupdate(wid, event)
204 else:
Jack Jansendc4d9252001-08-27 10:55:41 +0000205 if KILLUNKNOWNWINDOWS and wid:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000206 wid.HideWindow()
207 import sys
208 sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
209 else:
Jack Jansenb9e66612002-03-21 22:36:57 +0000210 if hasattr(MacOS, 'HandleEvent'):
211 MacOS.HandleEvent(event)
212 else:
213 print 'Unexpected updateEvent:', event
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000214
215 def suspendresume(self, onoff):
216 pass
217
218 def do_suspendresume(self, event):
219 self._suspended = not event[1] & 1
220 FrameWork.Application.do_suspendresume(self, event)
221
222 def checkopenwindowsmenu(self):
223 if self._openwindowscheckmark:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000224 self.openwindowsmenu.menu.CheckMenuItem(self._openwindowscheckmark, 0)
Just van Rossum40144012002-02-04 12:52:44 +0000225 window = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000226 if window:
227 for item, wid in self._openwindows.items():
228 if wid == window:
229 #self.pythonwindowsmenuitem.check(1)
Jack Jansenafd0aa62001-01-29 13:29:47 +0000230 self.openwindowsmenu.menu.CheckMenuItem(item, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000231 self._openwindowscheckmark = item
232 break
233 else:
234 self._openwindowscheckmark = 0
235 #if self._openwindows:
236 # self.pythonwindowsmenuitem.enable(1)
237 #else:
238 # self.pythonwindowsmenuitem.enable(0)
239
240 def checkmenus(self, window):
241 for item in self._menustocheck:
242 callback = item.menu.items[item.item-1][2]
243 if type(callback) <> StringType:
244 item.enable(1)
245 elif hasattr(window, "domenu_" + callback):
246 if hasattr(window, "can_" + callback):
247 canhandler = getattr(window, "can_" + callback)
248 if canhandler(item):
249 item.enable(1)
250 else:
251 item.enable(0)
252 else:
253 item.enable(1)
254 else:
255 item.enable(0)
256
257 def enablemenubar(self, onoff):
258 for m in self.menubar.menus.values():
259 if onoff:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000260 m.menu.EnableMenuItem(0)
Just van Rossum4798c4e1999-02-27 17:15:32 +0000261 elif m.menu.GetMenuItemText(3) <> 'Cut': # ew...
Jack Jansenafd0aa62001-01-29 13:29:47 +0000262 m.menu.DisableMenuItem(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000263 MenuToolbox.DrawMenuBar()
264
265 def makemenubar(self):
266 self.menubar = MenuBar(self)
267 FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
268 self.makeusermenus()
Just van Rossum7171df31999-10-30 11:46:18 +0000269
270 def scriptswalk(self, top, menu, done=None):
271 if done is None:
272 done = {}
273 if done.has_key(top):
274 return
275 done[top] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000276 import os, macfs, string
277 try:
278 names = os.listdir(top)
279 except os.error:
280 FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
281 return
282 savedir = os.getcwd()
283 os.chdir(top)
284 for name in names:
Just van Rossum6dc2b571999-12-23 21:50:26 +0000285 if name == "CVS":
286 continue
287 try:
288 fss, isdir, isalias = macfs.ResolveAliasFile(name)
289 except:
290 # maybe a broken alias
291 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000292 path = fss.as_pathname()
Just van Rossum7171df31999-10-30 11:46:18 +0000293 if done.has_key(path):
294 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000295 name = string.strip(name)
296 if name[-3:] == '---':
297 menu.addseparator()
298 elif isdir:
299 submenu = FrameWork.SubMenu(menu, name)
Just van Rossum7171df31999-10-30 11:46:18 +0000300 self.scriptswalk(path, submenu, done)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000301 else:
302 creator, type = fss.GetCreatorType()
303 if type == 'TEXT':
304 if name[-3:] == '.py':
305 name = name[:-3]
306 item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
307 self._scripts[(menu.id, item.item)] = path
Just van Rossum7171df31999-10-30 11:46:18 +0000308 done[path] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000309 os.chdir(savedir)
310
311 def domenu_script(self, id, item, window, event):
312 (what, message, when, where, modifiers) = event
313 path = self._scripts[(id, item)]
314 import os
315 if not os.path.exists(path):
316 self.makescriptsmenu()
317 import W
318 raise W.AlertError, "File not found."
319 if ord(Evt.GetKeys()[7]) & 4:
320 self.openscript(path)
321 else:
322 import W, MacOS, sys
323 W.SetCursor("watch")
324 sys.argv = [path]
325 #cwd = os.getcwd()
326 #os.chdir(os.path.dirname(path) + ':')
327 try:
328 # xxx if there is a script window for this file,
329 # exec in that window's namespace.
330 # xxx what to do when it's not saved???
331 # promt to save?
Jack Jansen815d2bf2002-01-21 23:00:52 +0000332 if hasattr(MacOS, 'EnableAppswitch'):
333 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000334 execfile(path, {'__name__': '__main__', '__file__': path})
335 except W.AlertError, detail:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000336 if hasattr(MacOS, 'EnableAppswitch'):
337 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000338 raise W.AlertError, detail
339 except KeyboardInterrupt:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000340 if hasattr(MacOS, 'EnableAppswitch'):
341 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000342 except:
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 import PyEdit
346 PyEdit.tracebackwindow.traceback(1)
347 else:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000348 if hasattr(MacOS, 'EnableAppswitch'):
349 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000350 #os.chdir(cwd)
351
352 def openscript(self, filename, lineno=None, charoffset=0, modname=""):
353 import os, PyEdit, W
354 editor = self.getscript(filename)
355 if editor:
356 editor.select()
357 elif os.path.exists(filename):
358 editor = PyEdit.Editor(filename)
359 elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
360 import imp
361 if not modname:
362 if filename[-1] == 'c':
363 modname = os.path.basename(filename)[:-4]
364 else:
365 modname = os.path.basename(filename)[:-3]
366 try:
367 # XXX This does not work correctly with packages!
368 # XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
369 # XXX It says we should use imp.load_module(), but that *reloads* a package,
370 # XXX and that's the last thing we want here.
371 f, filename, (suff, mode, dummy) = imp.find_module(modname)
372 except ImportError:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000373 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000374 else:
375 if not f:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000376 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000377 f.close()
378 if suff == '.py':
379 self.openscript(filename, lineno, charoffset)
380 return
381 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000382 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000383 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000384 raise W.AlertError, "Can't find file \"%s\"" % filename
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000385 if lineno is not None:
386 editor.selectline(lineno, charoffset)
387 return editor
388
389 def getscript(self, filename):
390 if filename[:1] == '<' and filename[-1:] == '>':
391 filename = filename[1:-1]
392 import string
393 lowpath = string.lower(filename)
394 for wid, window in self._windows.items():
Just van Rossum7171df31999-10-30 11:46:18 +0000395 if hasattr(window, "path") and type(window.path) == StringType and \
396 lowpath == string.lower(window.path):
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000397 return window
398 elif hasattr(window, "path") and filename == wid.GetWTitle():
399 return window
400
401 def getprefs(self):
402 import MacPrefs
403 return MacPrefs.GetPrefs(self.preffilepath)
Just van Rossum2a759091999-09-26 12:18:19 +0000404
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000405 def do_editorprefs(self, *args):
406 import PyEdit
407 PyEdit.EditorDefaultSettings()
408
Just van Rossum2a759091999-09-26 12:18:19 +0000409 def do_setwindowfont(self, *args):
410 import FontSettings, W
411 prefs = self.getprefs()
412 settings = FontSettings.FontDialog(prefs.defaultfont)
413 if settings:
414 prefs.defaultfont, tabsettings = settings
415 raise W.AlertError, "Note that changes will only affect new windows!"
416
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000417
418
419class MenuBar(FrameWork.MenuBar):
420
421 possibleIDs = range(10, 256)
422
423 def getnextid(self):
424 id = self.possibleIDs[0]
425 del self.possibleIDs[0]
426 return id
427
428 def __init__(self, parent = None):
429 self.bar = MenuToolbox.GetMenuBar()
430 MenuToolbox.ClearMenuBar()
431 self.menus = {}
432 self.parent = parent
433
434 def dispatch(self, id, item, window, event):
435 if self.menus.has_key(id):
436 self.menus[id].dispatch(id, item, window, event)
437
438 def delmenu(self, id):
439 MenuToolbox.DeleteMenu(id)
440 if id in self.possibleIDs:
441 print "XXX duplicate menu ID!", id
442 self.possibleIDs.append(id)
443
444
445class Menu(FrameWork.Menu):
446
447 def dispatch(self, id, item, window, event):
448 title, shortcut, callback, kind = self.items[item-1]
449 if type(callback) == StringType:
450 callback = self._getmenuhandler(callback)
451 if callback:
452 import W
453 W.CallbackCall(callback, 0, id, item, window, event)
454
455 def _getmenuhandler(self, callback):
456 menuhandler = None
Just van Rossum40144012002-02-04 12:52:44 +0000457 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000458 if wid and self.bar.parent._windows.has_key(wid):
459 window = self.bar.parent._windows[wid]
460 if hasattr(window, "domenu_" + callback):
461 menuhandler = getattr(window, "domenu_" + callback)
462 elif hasattr(self.bar.parent, "domenu_" + callback):
463 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
464 elif hasattr(self.bar.parent, "domenu_" + callback):
465 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
466 return menuhandler
467