blob: 40eb0c67f3fd94f293187910e1483eeb3b35652f [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 *
9
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000010from Carbon import Menu; MenuToolbox = Menu; del Menu
Just van Rossum40f9b7b1999-01-30 22:39:17 +000011
Just van Rossumf376ef02001-11-18 14:12:43 +000012KILLUNKNOWNWINDOWS = 0 # Set to 0 for debugging.
Just van Rossum40f9b7b1999-01-30 22:39:17 +000013
14class Application(FrameWork.Application):
15
16 def __init__(self, signature='Pyth'):
17 import W
18 W.setapplication(self, signature)
19 FrameWork.Application.__init__(self)
20 self._suspended = 0
21 self.quitting = 0
22 self.debugger_quitting = 1
23 self.DebuggerQuit = 'DebuggerQuitDummyException'
24 self._idlefuncs = []
25 # map certain F key codes to equivalent command-letter combos (JJS)
26 self.fkeymaps = {122:"z", 120:"x", 99:"c", 118:"v"}
27
Jack Jansene5c94742001-03-08 23:10:37 +000028 def mainloop(self, mask=FrameWork.everyEvent, wait=None):
Just van Rossum40f9b7b1999-01-30 22:39:17 +000029 import W
30 self.quitting = 0
Jack Jansen815d2bf2002-01-21 23:00:52 +000031 if hasattr(MacOS, 'EnableAppswitch'):
32 saveyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000033 try:
34 while not self.quitting:
35 try:
36 self.do1event(mask, wait)
37 except W.AlertError, detail:
Jack Jansen815d2bf2002-01-21 23:00:52 +000038 if hasattr(MacOS, 'EnableAppswitch'):
39 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000040 W.Message(detail)
41 except self.DebuggerQuit:
Jack Jansen815d2bf2002-01-21 23:00:52 +000042 if hasattr(MacOS, 'EnableAppswitch'):
43 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000044 except:
Jack Jansen815d2bf2002-01-21 23:00:52 +000045 if hasattr(MacOS, 'EnableAppswitch'):
46 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000047 import PyEdit
48 PyEdit.tracebackwindow.traceback()
49 finally:
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
Jack Jansene5c94742001-03-08 23:10:37 +000053 def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=None):
Just van Rossum40f9b7b1999-01-30 22:39:17 +000054 import W
55 self.debugger_quitting = 0
Jack Jansen815d2bf2002-01-21 23:00:52 +000056 if hasattr(MacOS, 'EnableAppswitch'):
57 saveyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000058 try:
59 while not self.quitting and not self.debugger_quitting:
60 try:
61 self.do1event(mask, wait)
62 except W.AlertError, detail:
63 W.Message(detail)
64 except:
65 import PyEdit
66 PyEdit.tracebackwindow.traceback()
67 finally:
Jack Jansen815d2bf2002-01-21 23:00:52 +000068 if hasattr(MacOS, 'EnableAppswitch'):
69 MacOS.EnableAppswitch(saveyield)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000070
71 def breathe(self, wait=1):
72 import W
73 ok, event = Evt.WaitNextEvent(FrameWork.updateMask |
74 FrameWork.mDownMask | FrameWork.osMask |
75 FrameWork.activMask,
76 wait)
77 if ok:
78 (what, message, when, where, modifiers) = event
79 #print FrameWork.eventname[what]
80 if FrameWork.eventname[what] == 'mouseDown':
81 partcode, wid = Win.FindWindow(where)
82 if FrameWork.partname[partcode] <> 'inDesk':
83 return
84 else:
85 W.SetCursor('watch')
86 self.dispatch(event)
87
88 def refreshwindows(self, wait=1):
89 import W
90 while 1:
91 ok, event = Evt.WaitNextEvent(FrameWork.updateMask, wait)
92 if not ok:
93 break
94 self.dispatch(event)
95
96 def addidlefunc(self, func):
97 self._idlefuncs.append(func)
98
99 def removeidlefunc(self, func):
100 self._idlefuncs.remove(func)
101
102 def idle(self, event):
103 if not self._suspended:
104 if not self.do_frontWindowMethod("idle", event):
105 Qd.InitCursor()
106 if self._idlefuncs:
107 for func in self._idlefuncs:
108 try:
109 func()
110 except:
111 import sys
112 sys.stderr.write("exception in idle function %s; killed:\n" % `func`)
113 traceback.print_exc()
114 self._idlefuncs.remove(func)
115 break
116
117 def do_frontWindowMethod(self, attr, *args):
118 wid = Win.FrontWindow()
119 if wid and self._windows.has_key(wid):
120 window = self._windows[wid]
121 if hasattr(window, attr):
122 handler = getattr(window, attr)
123 apply(handler, args)
124 return 1
125
126 def appendwindow(self, wid, window):
127 self._windows[wid] = window
128 self.makeopenwindowsmenu()
129
130 def removewindow(self, wid):
131 del self._windows[wid]
132 self.makeopenwindowsmenu()
133
Just van Rossumd4bdbf11999-02-26 21:30:19 +0000134 def makeopenwindowsmenu(self):
135 # dummy; could be the full version from PythonIDEMain.py
136 self._openwindows = {}
137 self._openwindowscheckmark = 0
138 if not hasattr(self, "_menustocheck"):
139 self._menustocheck = []
140
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000141 def do_key(self, event):
142 (what, message, when, where, modifiers) = event
143 ch = chr(message & FrameWork.charCodeMask)
144 rest = message & ~FrameWork.charCodeMask
145 keycode = (message & FrameWork.keyCodeMask) >> 8
146 if keycode in self.fkeymaps.keys(): # JJS
147 ch = self.fkeymaps[keycode]
148 modifiers = modifiers | FrameWork.cmdKey
149 wid = Win.FrontWindow()
150 if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
151 if wid and self._windows.has_key(wid):
152 self.checkmenus(self._windows[wid])
153 else:
154 self.checkmenus(None)
155 event = (what, ord(ch) | rest, when, where, modifiers)
156 result = MenuToolbox.MenuKey(ord(ch))
157 id = (result>>16) & 0xffff # Hi word
158 item = result & 0xffff # Lo word
159 if id:
160 self.do_rawmenu(id, item, None, event)
161 return # here! we had a menukey!
162 #else:
163 # print "XXX Command-" +`ch`
164 # See whether the front window wants it
165 if wid and self._windows.has_key(wid):
166 window = self._windows[wid]
167 try:
168 do_char = window.do_char
169 except AttributeError:
170 do_char = self.do_char
171 do_char(ch, event)
172 # else it wasn't for us, sigh...
173
174 def do_inMenuBar(self, partcode, window, event):
175 Qd.InitCursor()
176 (what, message, when, where, modifiers) = event
177 self.checkopenwindowsmenu()
178 wid = Win.FrontWindow()
179 if wid and self._windows.has_key(wid):
180 self.checkmenus(self._windows[wid])
181 else:
182 self.checkmenus(None)
183 result = MenuToolbox.MenuSelect(where)
184 id = (result>>16) & 0xffff # Hi word
185 item = result & 0xffff # Lo word
186 self.do_rawmenu(id, item, window, event)
187
188 def do_updateEvt(self, event):
189 (what, message, when, where, modifiers) = event
190 wid = Win.WhichWindow(message)
191 if wid and self._windows.has_key(wid):
192 window = self._windows[wid]
193 window.do_rawupdate(wid, event)
194 else:
Jack Jansendc4d9252001-08-27 10:55:41 +0000195 if KILLUNKNOWNWINDOWS and wid:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000196 wid.HideWindow()
197 import sys
198 sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
199 else:
200 MacOS.HandleEvent(event)
201
202 def suspendresume(self, onoff):
203 pass
204
205 def do_suspendresume(self, event):
206 self._suspended = not event[1] & 1
207 FrameWork.Application.do_suspendresume(self, event)
208
209 def checkopenwindowsmenu(self):
210 if self._openwindowscheckmark:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000211 self.openwindowsmenu.menu.CheckMenuItem(self._openwindowscheckmark, 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000212 window = Win.FrontWindow()
213 if window:
214 for item, wid in self._openwindows.items():
215 if wid == window:
216 #self.pythonwindowsmenuitem.check(1)
Jack Jansenafd0aa62001-01-29 13:29:47 +0000217 self.openwindowsmenu.menu.CheckMenuItem(item, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000218 self._openwindowscheckmark = item
219 break
220 else:
221 self._openwindowscheckmark = 0
222 #if self._openwindows:
223 # self.pythonwindowsmenuitem.enable(1)
224 #else:
225 # self.pythonwindowsmenuitem.enable(0)
226
227 def checkmenus(self, window):
228 for item in self._menustocheck:
229 callback = item.menu.items[item.item-1][2]
230 if type(callback) <> StringType:
231 item.enable(1)
232 elif hasattr(window, "domenu_" + callback):
233 if hasattr(window, "can_" + callback):
234 canhandler = getattr(window, "can_" + callback)
235 if canhandler(item):
236 item.enable(1)
237 else:
238 item.enable(0)
239 else:
240 item.enable(1)
241 else:
242 item.enable(0)
243
244 def enablemenubar(self, onoff):
245 for m in self.menubar.menus.values():
246 if onoff:
Jack Jansenafd0aa62001-01-29 13:29:47 +0000247 m.menu.EnableMenuItem(0)
Just van Rossum4798c4e1999-02-27 17:15:32 +0000248 elif m.menu.GetMenuItemText(3) <> 'Cut': # ew...
Jack Jansenafd0aa62001-01-29 13:29:47 +0000249 m.menu.DisableMenuItem(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000250 MenuToolbox.DrawMenuBar()
251
252 def makemenubar(self):
253 self.menubar = MenuBar(self)
254 FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
255 self.makeusermenus()
Just van Rossum7171df31999-10-30 11:46:18 +0000256
257 def scriptswalk(self, top, menu, done=None):
258 if done is None:
259 done = {}
260 if done.has_key(top):
261 return
262 done[top] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000263 import os, macfs, string
264 try:
265 names = os.listdir(top)
266 except os.error:
267 FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
268 return
269 savedir = os.getcwd()
270 os.chdir(top)
271 for name in names:
Just van Rossum6dc2b571999-12-23 21:50:26 +0000272 if name == "CVS":
273 continue
274 try:
275 fss, isdir, isalias = macfs.ResolveAliasFile(name)
276 except:
277 # maybe a broken alias
278 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000279 path = fss.as_pathname()
Just van Rossum7171df31999-10-30 11:46:18 +0000280 if done.has_key(path):
281 continue
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000282 name = string.strip(name)
283 if name[-3:] == '---':
284 menu.addseparator()
285 elif isdir:
286 submenu = FrameWork.SubMenu(menu, name)
Just van Rossum7171df31999-10-30 11:46:18 +0000287 self.scriptswalk(path, submenu, done)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000288 else:
289 creator, type = fss.GetCreatorType()
290 if type == 'TEXT':
291 if name[-3:] == '.py':
292 name = name[:-3]
293 item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
294 self._scripts[(menu.id, item.item)] = path
Just van Rossum7171df31999-10-30 11:46:18 +0000295 done[path] = 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000296 os.chdir(savedir)
297
298 def domenu_script(self, id, item, window, event):
299 (what, message, when, where, modifiers) = event
300 path = self._scripts[(id, item)]
301 import os
302 if not os.path.exists(path):
303 self.makescriptsmenu()
304 import W
305 raise W.AlertError, "File not found."
306 if ord(Evt.GetKeys()[7]) & 4:
307 self.openscript(path)
308 else:
309 import W, MacOS, sys
310 W.SetCursor("watch")
311 sys.argv = [path]
312 #cwd = os.getcwd()
313 #os.chdir(os.path.dirname(path) + ':')
314 try:
315 # xxx if there is a script window for this file,
316 # exec in that window's namespace.
317 # xxx what to do when it's not saved???
318 # promt to save?
Jack Jansen815d2bf2002-01-21 23:00:52 +0000319 if hasattr(MacOS, 'EnableAppswitch'):
320 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000321 execfile(path, {'__name__': '__main__', '__file__': path})
322 except W.AlertError, detail:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000323 if hasattr(MacOS, 'EnableAppswitch'):
324 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000325 raise W.AlertError, detail
326 except KeyboardInterrupt:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000327 if hasattr(MacOS, 'EnableAppswitch'):
328 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000329 except:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000330 if hasattr(MacOS, 'EnableAppswitch'):
331 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000332 import PyEdit
333 PyEdit.tracebackwindow.traceback(1)
334 else:
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 #os.chdir(cwd)
338
339 def openscript(self, filename, lineno=None, charoffset=0, modname=""):
340 import os, PyEdit, W
341 editor = self.getscript(filename)
342 if editor:
343 editor.select()
344 elif os.path.exists(filename):
345 editor = PyEdit.Editor(filename)
346 elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
347 import imp
348 if not modname:
349 if filename[-1] == 'c':
350 modname = os.path.basename(filename)[:-4]
351 else:
352 modname = os.path.basename(filename)[:-3]
353 try:
354 # XXX This does not work correctly with packages!
355 # XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
356 # XXX It says we should use imp.load_module(), but that *reloads* a package,
357 # XXX and that's the last thing we want here.
358 f, filename, (suff, mode, dummy) = imp.find_module(modname)
359 except ImportError:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000360 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000361 else:
362 if not f:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000363 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000364 f.close()
365 if suff == '.py':
366 self.openscript(filename, lineno, charoffset)
367 return
368 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000369 raise W.AlertError, "Can't find file for \"%s\"" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000370 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000371 raise W.AlertError, "Can't find file \"%s\"" % filename
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000372 if lineno is not None:
373 editor.selectline(lineno, charoffset)
374 return editor
375
376 def getscript(self, filename):
377 if filename[:1] == '<' and filename[-1:] == '>':
378 filename = filename[1:-1]
379 import string
380 lowpath = string.lower(filename)
381 for wid, window in self._windows.items():
Just van Rossum7171df31999-10-30 11:46:18 +0000382 if hasattr(window, "path") and type(window.path) == StringType and \
383 lowpath == string.lower(window.path):
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000384 return window
385 elif hasattr(window, "path") and filename == wid.GetWTitle():
386 return window
387
388 def getprefs(self):
389 import MacPrefs
390 return MacPrefs.GetPrefs(self.preffilepath)
Just van Rossum2a759091999-09-26 12:18:19 +0000391
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000392 def do_editorprefs(self, *args):
393 import PyEdit
394 PyEdit.EditorDefaultSettings()
395
Just van Rossum2a759091999-09-26 12:18:19 +0000396 def do_setwindowfont(self, *args):
397 import FontSettings, W
398 prefs = self.getprefs()
399 settings = FontSettings.FontDialog(prefs.defaultfont)
400 if settings:
401 prefs.defaultfont, tabsettings = settings
402 raise W.AlertError, "Note that changes will only affect new windows!"
403
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000404
405
406class MenuBar(FrameWork.MenuBar):
407
408 possibleIDs = range(10, 256)
409
410 def getnextid(self):
411 id = self.possibleIDs[0]
412 del self.possibleIDs[0]
413 return id
414
415 def __init__(self, parent = None):
416 self.bar = MenuToolbox.GetMenuBar()
417 MenuToolbox.ClearMenuBar()
418 self.menus = {}
419 self.parent = parent
420
421 def dispatch(self, id, item, window, event):
422 if self.menus.has_key(id):
423 self.menus[id].dispatch(id, item, window, event)
424
425 def delmenu(self, id):
426 MenuToolbox.DeleteMenu(id)
427 if id in self.possibleIDs:
428 print "XXX duplicate menu ID!", id
429 self.possibleIDs.append(id)
430
431
432class Menu(FrameWork.Menu):
433
434 def dispatch(self, id, item, window, event):
435 title, shortcut, callback, kind = self.items[item-1]
436 if type(callback) == StringType:
437 callback = self._getmenuhandler(callback)
438 if callback:
439 import W
440 W.CallbackCall(callback, 0, id, item, window, event)
441
442 def _getmenuhandler(self, callback):
443 menuhandler = None
444 wid = Win.FrontWindow()
445 if wid and self.bar.parent._windows.has_key(wid):
446 window = self.bar.parent._windows[wid]
447 if hasattr(window, "domenu_" + callback):
448 menuhandler = getattr(window, "domenu_" + callback)
449 elif hasattr(self.bar.parent, "domenu_" + callback):
450 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
451 elif hasattr(self.bar.parent, "domenu_" + callback):
452 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
453 return menuhandler
454