blob: fdcd9fbcc8b5cc2fb56a54457d632803e087aa6b [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:
205 MacOS.HandleEvent(event)
206
207 def suspendresume(self, onoff):
208 pass
209
210 def do_suspendresume(self, event):
211 self._suspended = not event[1] & 1
212 FrameWork.Application.do_suspendresume(self, event)
213
214 def checkopenwindowsmenu(self):
215 if self._openwindowscheckmark:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000216 self.openwindowsmenu.menu.CheckMenuItem(self._openwindowscheckmark, 0)
Just van Rossum40144012002-02-04 12:52:44 +0000217 window = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000218 if window:
219 for item, wid in self._openwindows.items():
220 if wid == window:
221 #self.pythonwindowsmenuitem.check(1)
Jack Jansenafd0aa62001-01-29 13:29:47 +0000222 self.openwindowsmenu.menu.CheckMenuItem(item, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000223 self._openwindowscheckmark = item
224 break
225 else:
226 self._openwindowscheckmark = 0
227 #if self._openwindows:
228 # self.pythonwindowsmenuitem.enable(1)
229 #else:
230 # self.pythonwindowsmenuitem.enable(0)
231
232 def checkmenus(self, window):
233 for item in self._menustocheck:
234 callback = item.menu.items[item.item-1][2]
235 if type(callback) <> StringType:
236 item.enable(1)
237 elif hasattr(window, "domenu_" + callback):
238 if hasattr(window, "can_" + callback):
239 canhandler = getattr(window, "can_" + callback)
240 if canhandler(item):
241 item.enable(1)
242 else:
243 item.enable(0)
244 else:
245 item.enable(1)
246 else:
247 item.enable(0)
248
249 def enablemenubar(self, onoff):
250 for m in self.menubar.menus.values():
251 if onoff:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000252 m.menu.EnableMenuItem(0)
Just van Rossum4798c4e1999-02-27 17:15:32 +0000253 elif m.menu.GetMenuItemText(3) <> 'Cut': # ew...
Jack Jansenafd0aa62001-01-29 13:29:47 +0000254 m.menu.DisableMenuItem(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000255 MenuToolbox.DrawMenuBar()
256
257 def makemenubar(self):
258 self.menubar = MenuBar(self)
259 FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
260 self.makeusermenus()
Just van Rossum7171df31999-10-30 11:46:18 +0000261
262 def scriptswalk(self, top, menu, done=None):
263 if done is None:
264 done = {}
265 if done.has_key(top):
266 return
267 done[top] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000268 import os, macfs, string
269 try:
270 names = os.listdir(top)
271 except os.error:
272 FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
273 return
274 savedir = os.getcwd()
275 os.chdir(top)
276 for name in names:
Just van Rossum6dc2b571999-12-23 21:50:26 +0000277 if name == "CVS":
278 continue
279 try:
280 fss, isdir, isalias = macfs.ResolveAliasFile(name)
281 except:
282 # maybe a broken alias
283 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000284 path = fss.as_pathname()
Just van Rossum7171df31999-10-30 11:46:18 +0000285 if done.has_key(path):
286 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000287 name = string.strip(name)
288 if name[-3:] == '---':
289 menu.addseparator()
290 elif isdir:
291 submenu = FrameWork.SubMenu(menu, name)
Just van Rossum7171df31999-10-30 11:46:18 +0000292 self.scriptswalk(path, submenu, done)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000293 else:
294 creator, type = fss.GetCreatorType()
295 if type == 'TEXT':
296 if name[-3:] == '.py':
297 name = name[:-3]
298 item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
299 self._scripts[(menu.id, item.item)] = path
Just van Rossum7171df31999-10-30 11:46:18 +0000300 done[path] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000301 os.chdir(savedir)
302
303 def domenu_script(self, id, item, window, event):
304 (what, message, when, where, modifiers) = event
305 path = self._scripts[(id, item)]
306 import os
307 if not os.path.exists(path):
308 self.makescriptsmenu()
309 import W
310 raise W.AlertError, "File not found."
311 if ord(Evt.GetKeys()[7]) & 4:
312 self.openscript(path)
313 else:
314 import W, MacOS, sys
315 W.SetCursor("watch")
316 sys.argv = [path]
317 #cwd = os.getcwd()
318 #os.chdir(os.path.dirname(path) + ':')
319 try:
320 # xxx if there is a script window for this file,
321 # exec in that window's namespace.
322 # xxx what to do when it's not saved???
323 # promt to save?
Jack Jansen815d2bf2002-01-21 23:00:52 +0000324 if hasattr(MacOS, 'EnableAppswitch'):
325 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000326 execfile(path, {'__name__': '__main__', '__file__': path})
327 except W.AlertError, detail:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000328 if hasattr(MacOS, 'EnableAppswitch'):
329 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000330 raise W.AlertError, detail
331 except KeyboardInterrupt:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000332 if hasattr(MacOS, 'EnableAppswitch'):
333 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000334 except:
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 import PyEdit
338 PyEdit.tracebackwindow.traceback(1)
339 else:
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 #os.chdir(cwd)
343
344 def openscript(self, filename, lineno=None, charoffset=0, modname=""):
345 import os, PyEdit, W
346 editor = self.getscript(filename)
347 if editor:
348 editor.select()
349 elif os.path.exists(filename):
350 editor = PyEdit.Editor(filename)
351 elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
352 import imp
353 if not modname:
354 if filename[-1] == 'c':
355 modname = os.path.basename(filename)[:-4]
356 else:
357 modname = os.path.basename(filename)[:-3]
358 try:
359 # XXX This does not work correctly with packages!
360 # XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
361 # XXX It says we should use imp.load_module(), but that *reloads* a package,
362 # XXX and that's the last thing we want here.
363 f, filename, (suff, mode, dummy) = imp.find_module(modname)
364 except ImportError:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000365 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000366 else:
367 if not f:
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 f.close()
370 if suff == '.py':
371 self.openscript(filename, lineno, charoffset)
372 return
373 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000374 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000375 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000376 raise W.AlertError, "Can't find file \"%s\"" % filename
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000377 if lineno is not None:
378 editor.selectline(lineno, charoffset)
379 return editor
380
381 def getscript(self, filename):
382 if filename[:1] == '<' and filename[-1:] == '>':
383 filename = filename[1:-1]
384 import string
385 lowpath = string.lower(filename)
386 for wid, window in self._windows.items():
Just van Rossum7171df31999-10-30 11:46:18 +0000387 if hasattr(window, "path") and type(window.path) == StringType and \
388 lowpath == string.lower(window.path):
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000389 return window
390 elif hasattr(window, "path") and filename == wid.GetWTitle():
391 return window
392
393 def getprefs(self):
394 import MacPrefs
395 return MacPrefs.GetPrefs(self.preffilepath)
Just van Rossum2a759091999-09-26 12:18:19 +0000396
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000397 def do_editorprefs(self, *args):
398 import PyEdit
399 PyEdit.EditorDefaultSettings()
400
Just van Rossum2a759091999-09-26 12:18:19 +0000401 def do_setwindowfont(self, *args):
402 import FontSettings, W
403 prefs = self.getprefs()
404 settings = FontSettings.FontDialog(prefs.defaultfont)
405 if settings:
406 prefs.defaultfont, tabsettings = settings
407 raise W.AlertError, "Note that changes will only affect new windows!"
408
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000409
410
411class MenuBar(FrameWork.MenuBar):
412
413 possibleIDs = range(10, 256)
414
415 def getnextid(self):
416 id = self.possibleIDs[0]
417 del self.possibleIDs[0]
418 return id
419
420 def __init__(self, parent = None):
421 self.bar = MenuToolbox.GetMenuBar()
422 MenuToolbox.ClearMenuBar()
423 self.menus = {}
424 self.parent = parent
425
426 def dispatch(self, id, item, window, event):
427 if self.menus.has_key(id):
428 self.menus[id].dispatch(id, item, window, event)
429
430 def delmenu(self, id):
431 MenuToolbox.DeleteMenu(id)
432 if id in self.possibleIDs:
433 print "XXX duplicate menu ID!", id
434 self.possibleIDs.append(id)
435
436
437class Menu(FrameWork.Menu):
438
439 def dispatch(self, id, item, window, event):
440 title, shortcut, callback, kind = self.items[item-1]
441 if type(callback) == StringType:
442 callback = self._getmenuhandler(callback)
443 if callback:
444 import W
445 W.CallbackCall(callback, 0, id, item, window, event)
446
447 def _getmenuhandler(self, callback):
448 menuhandler = None
Just van Rossum40144012002-02-04 12:52:44 +0000449 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000450 if wid and self.bar.parent._windows.has_key(wid):
451 window = self.bar.parent._windows[wid]
452 if hasattr(window, "domenu_" + callback):
453 menuhandler = getattr(window, "domenu_" + callback)
454 elif hasattr(self.bar.parent, "domenu_" + callback):
455 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
456 elif hasattr(self.bar.parent, "domenu_" + callback):
457 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
458 return menuhandler
459