blob: 10ac3f102dead8f498b777385f9c19463ab3db83 [file] [log] [blame]
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001import FrameWork
2import Win
3import Qd
4import Evt
5import MacOS
6import Events
7import traceback
8from types import *
9
10import Menu; MenuToolbox = Menu; del Menu
11
12
13class Application(FrameWork.Application):
14
15 def __init__(self, signature='Pyth'):
16 import W
17 W.setapplication(self, signature)
18 FrameWork.Application.__init__(self)
19 self._suspended = 0
20 self.quitting = 0
21 self.debugger_quitting = 1
22 self.DebuggerQuit = 'DebuggerQuitDummyException'
23 self._idlefuncs = []
24 # map certain F key codes to equivalent command-letter combos (JJS)
25 self.fkeymaps = {122:"z", 120:"x", 99:"c", 118:"v"}
26
27 def mainloop(self, mask=FrameWork.everyEvent, wait=0):
28 import W
29 self.quitting = 0
30 saveyield = MacOS.EnableAppswitch(-1)
31 try:
32 while not self.quitting:
33 try:
34 self.do1event(mask, wait)
35 except W.AlertError, detail:
36 MacOS.EnableAppswitch(-1)
37 W.Message(detail)
38 except self.DebuggerQuit:
39 MacOS.EnableAppswitch(-1)
40 except:
41 MacOS.EnableAppswitch(-1)
42 import PyEdit
43 PyEdit.tracebackwindow.traceback()
44 finally:
45 MacOS.EnableAppswitch(1)
46
47 def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=0):
48 import W
49 self.debugger_quitting = 0
50 saveyield = MacOS.EnableAppswitch(-1)
51 try:
52 while not self.quitting and not self.debugger_quitting:
53 try:
54 self.do1event(mask, wait)
55 except W.AlertError, detail:
56 W.Message(detail)
57 except:
58 import PyEdit
59 PyEdit.tracebackwindow.traceback()
60 finally:
61 MacOS.EnableAppswitch(saveyield)
62
63 def breathe(self, wait=1):
64 import W
65 ok, event = Evt.WaitNextEvent(FrameWork.updateMask |
66 FrameWork.mDownMask | FrameWork.osMask |
67 FrameWork.activMask,
68 wait)
69 if ok:
70 (what, message, when, where, modifiers) = event
71 #print FrameWork.eventname[what]
72 if FrameWork.eventname[what] == 'mouseDown':
73 partcode, wid = Win.FindWindow(where)
74 if FrameWork.partname[partcode] <> 'inDesk':
75 return
76 else:
77 W.SetCursor('watch')
78 self.dispatch(event)
79
80 def refreshwindows(self, wait=1):
81 import W
82 while 1:
83 ok, event = Evt.WaitNextEvent(FrameWork.updateMask, wait)
84 if not ok:
85 break
86 self.dispatch(event)
87
88 def addidlefunc(self, func):
89 self._idlefuncs.append(func)
90
91 def removeidlefunc(self, func):
92 self._idlefuncs.remove(func)
93
94 def idle(self, event):
95 if not self._suspended:
96 if not self.do_frontWindowMethod("idle", event):
97 Qd.InitCursor()
98 if self._idlefuncs:
99 for func in self._idlefuncs:
100 try:
101 func()
102 except:
103 import sys
104 sys.stderr.write("exception in idle function %s; killed:\n" % `func`)
105 traceback.print_exc()
106 self._idlefuncs.remove(func)
107 break
108
109 def do_frontWindowMethod(self, attr, *args):
110 wid = Win.FrontWindow()
111 if wid and self._windows.has_key(wid):
112 window = self._windows[wid]
113 if hasattr(window, attr):
114 handler = getattr(window, attr)
115 apply(handler, args)
116 return 1
117
118 def appendwindow(self, wid, window):
119 self._windows[wid] = window
120 self.makeopenwindowsmenu()
121
122 def removewindow(self, wid):
123 del self._windows[wid]
124 self.makeopenwindowsmenu()
125
126 def do_key(self, event):
127 (what, message, when, where, modifiers) = event
128 ch = chr(message & FrameWork.charCodeMask)
129 rest = message & ~FrameWork.charCodeMask
130 keycode = (message & FrameWork.keyCodeMask) >> 8
131 if keycode in self.fkeymaps.keys(): # JJS
132 ch = self.fkeymaps[keycode]
133 modifiers = modifiers | FrameWork.cmdKey
134 wid = Win.FrontWindow()
135 if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
136 if wid and self._windows.has_key(wid):
137 self.checkmenus(self._windows[wid])
138 else:
139 self.checkmenus(None)
140 event = (what, ord(ch) | rest, when, where, modifiers)
141 result = MenuToolbox.MenuKey(ord(ch))
142 id = (result>>16) & 0xffff # Hi word
143 item = result & 0xffff # Lo word
144 if id:
145 self.do_rawmenu(id, item, None, event)
146 return # here! we had a menukey!
147 #else:
148 # print "XXX Command-" +`ch`
149 # See whether the front window wants it
150 if wid and self._windows.has_key(wid):
151 window = self._windows[wid]
152 try:
153 do_char = window.do_char
154 except AttributeError:
155 do_char = self.do_char
156 do_char(ch, event)
157 # else it wasn't for us, sigh...
158
159 def do_inMenuBar(self, partcode, window, event):
160 Qd.InitCursor()
161 (what, message, when, where, modifiers) = event
162 self.checkopenwindowsmenu()
163 wid = Win.FrontWindow()
164 if wid and self._windows.has_key(wid):
165 self.checkmenus(self._windows[wid])
166 else:
167 self.checkmenus(None)
168 result = MenuToolbox.MenuSelect(where)
169 id = (result>>16) & 0xffff # Hi word
170 item = result & 0xffff # Lo word
171 self.do_rawmenu(id, item, window, event)
172
173 def do_updateEvt(self, event):
174 (what, message, when, where, modifiers) = event
175 wid = Win.WhichWindow(message)
176 if wid and self._windows.has_key(wid):
177 window = self._windows[wid]
178 window.do_rawupdate(wid, event)
179 else:
180 if wid:
181 wid.HideWindow()
182 import sys
183 sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
184 else:
185 MacOS.HandleEvent(event)
186
187 def suspendresume(self, onoff):
188 pass
189
190 def do_suspendresume(self, event):
191 self._suspended = not event[1] & 1
192 FrameWork.Application.do_suspendresume(self, event)
193
194 def checkopenwindowsmenu(self):
195 if self._openwindowscheckmark:
196 self.openwindowsmenu.menu.CheckItem(self._openwindowscheckmark, 0)
197 window = Win.FrontWindow()
198 if window:
199 for item, wid in self._openwindows.items():
200 if wid == window:
201 #self.pythonwindowsmenuitem.check(1)
202 self.openwindowsmenu.menu.CheckItem(item, 1)
203 self._openwindowscheckmark = item
204 break
205 else:
206 self._openwindowscheckmark = 0
207 #if self._openwindows:
208 # self.pythonwindowsmenuitem.enable(1)
209 #else:
210 # self.pythonwindowsmenuitem.enable(0)
211
212 def checkmenus(self, window):
213 for item in self._menustocheck:
214 callback = item.menu.items[item.item-1][2]
215 if type(callback) <> StringType:
216 item.enable(1)
217 elif hasattr(window, "domenu_" + callback):
218 if hasattr(window, "can_" + callback):
219 canhandler = getattr(window, "can_" + callback)
220 if canhandler(item):
221 item.enable(1)
222 else:
223 item.enable(0)
224 else:
225 item.enable(1)
226 else:
227 item.enable(0)
228
229 def enablemenubar(self, onoff):
230 for m in self.menubar.menus.values():
231 if onoff:
232 m.menu.EnableItem(0)
233 else:
234 m.menu.DisableItem(0)
235 MenuToolbox.DrawMenuBar()
236
237 def makemenubar(self):
238 self.menubar = MenuBar(self)
239 FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
240 self.makeusermenus()
241
242 def scriptswalk(self, top, menu):
243 import os, macfs, string
244 try:
245 names = os.listdir(top)
246 except os.error:
247 FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
248 return
249 savedir = os.getcwd()
250 os.chdir(top)
251 for name in names:
252 fss, isdir, isalias = macfs.ResolveAliasFile(name)
253 path = fss.as_pathname()
254 name = string.strip(name)
255 if name[-3:] == '---':
256 menu.addseparator()
257 elif isdir:
258 submenu = FrameWork.SubMenu(menu, name)
259 self.scriptswalk(path, submenu)
260 else:
261 creator, type = fss.GetCreatorType()
262 if type == 'TEXT':
263 if name[-3:] == '.py':
264 name = name[:-3]
265 item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
266 self._scripts[(menu.id, item.item)] = path
267 os.chdir(savedir)
268
269 def domenu_script(self, id, item, window, event):
270 (what, message, when, where, modifiers) = event
271 path = self._scripts[(id, item)]
272 import os
273 if not os.path.exists(path):
274 self.makescriptsmenu()
275 import W
276 raise W.AlertError, "File not found."
277 if ord(Evt.GetKeys()[7]) & 4:
278 self.openscript(path)
279 else:
280 import W, MacOS, sys
281 W.SetCursor("watch")
282 sys.argv = [path]
283 #cwd = os.getcwd()
284 #os.chdir(os.path.dirname(path) + ':')
285 try:
286 # xxx if there is a script window for this file,
287 # exec in that window's namespace.
288 # xxx what to do when it's not saved???
289 # promt to save?
290 MacOS.EnableAppswitch(0)
291 execfile(path, {'__name__': '__main__', '__file__': path})
292 except W.AlertError, detail:
293 MacOS.EnableAppswitch(-1)
294 raise W.AlertError, detail
295 except KeyboardInterrupt:
296 MacOS.EnableAppswitch(-1)
297 except:
298 MacOS.EnableAppswitch(-1)
299 import PyEdit
300 PyEdit.tracebackwindow.traceback(1)
301 else:
302 MacOS.EnableAppswitch(-1)
303 #os.chdir(cwd)
304
305 def openscript(self, filename, lineno=None, charoffset=0, modname=""):
306 import os, PyEdit, W
307 editor = self.getscript(filename)
308 if editor:
309 editor.select()
310 elif os.path.exists(filename):
311 editor = PyEdit.Editor(filename)
312 elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
313 import imp
314 if not modname:
315 if filename[-1] == 'c':
316 modname = os.path.basename(filename)[:-4]
317 else:
318 modname = os.path.basename(filename)[:-3]
319 try:
320 # XXX This does not work correctly with packages!
321 # XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
322 # XXX It says we should use imp.load_module(), but that *reloads* a package,
323 # XXX and that's the last thing we want here.
324 f, filename, (suff, mode, dummy) = imp.find_module(modname)
325 except ImportError:
Just van Rossumedab9391999-02-02 22:31:05 +0000326 raise W.AlertError, "Can¹t find file for ³%s²" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000327 else:
328 if not f:
Just van Rossumedab9391999-02-02 22:31:05 +0000329 raise W.AlertError, "Can¹t find file for ³%s²" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000330 f.close()
331 if suff == '.py':
332 self.openscript(filename, lineno, charoffset)
333 return
334 else:
Just van Rossumedab9391999-02-02 22:31:05 +0000335 raise W.AlertError, "Can¹t find file for ³%s²" % modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000336 else:
Just van Rossumedab9391999-02-02 22:31:05 +0000337 raise W.AlertError, "Can¹t find file Œ%s¹" % filename
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000338 if lineno is not None:
339 editor.selectline(lineno, charoffset)
340 return editor
341
342 def getscript(self, filename):
343 if filename[:1] == '<' and filename[-1:] == '>':
344 filename = filename[1:-1]
345 import string
346 lowpath = string.lower(filename)
347 for wid, window in self._windows.items():
348 if hasattr(window, "path") and lowpath == string.lower(window.path):
349 return window
350 elif hasattr(window, "path") and filename == wid.GetWTitle():
351 return window
352
353 def getprefs(self):
354 import MacPrefs
355 return MacPrefs.GetPrefs(self.preffilepath)
356
357 def do_editorprefs(self, *args):
358 import PyEdit
359 PyEdit.EditorDefaultSettings()
360
361
362
363class MenuBar(FrameWork.MenuBar):
364
365 possibleIDs = range(10, 256)
366
367 def getnextid(self):
368 id = self.possibleIDs[0]
369 del self.possibleIDs[0]
370 return id
371
372 def __init__(self, parent = None):
373 self.bar = MenuToolbox.GetMenuBar()
374 MenuToolbox.ClearMenuBar()
375 self.menus = {}
376 self.parent = parent
377
378 def dispatch(self, id, item, window, event):
379 if self.menus.has_key(id):
380 self.menus[id].dispatch(id, item, window, event)
381
382 def delmenu(self, id):
383 MenuToolbox.DeleteMenu(id)
384 if id in self.possibleIDs:
385 print "XXX duplicate menu ID!", id
386 self.possibleIDs.append(id)
387
388
389class Menu(FrameWork.Menu):
390
391 def dispatch(self, id, item, window, event):
392 title, shortcut, callback, kind = self.items[item-1]
393 if type(callback) == StringType:
394 callback = self._getmenuhandler(callback)
395 if callback:
396 import W
397 W.CallbackCall(callback, 0, id, item, window, event)
398
399 def _getmenuhandler(self, callback):
400 menuhandler = None
401 wid = Win.FrontWindow()
402 if wid and self.bar.parent._windows.has_key(wid):
403 window = self.bar.parent._windows[wid]
404 if hasattr(window, "domenu_" + callback):
405 menuhandler = getattr(window, "domenu_" + callback)
406 elif hasattr(self.bar.parent, "domenu_" + callback):
407 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
408 elif hasattr(self.bar.parent, "domenu_" + callback):
409 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
410 return menuhandler
411