py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Mac / Tools / IDE / Wapplication.py
blob7a9b74a4c2c5b9bfc23caf28b7d8f4ccc7785210
1 import FrameWork
2 import Win
3 import Qd
4 import Evt
5 import MacOS
6 import Events
7 import traceback
8 from types import *
10 import Menu; MenuToolbox = Menu; del Menu
13 class Application(FrameWork.Application):
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"}
27 def mainloop(self, mask=FrameWork.everyEvent, wait=None):
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)
47 def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=None):
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)
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)
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)
88 def addidlefunc(self, func):
89 self._idlefuncs.append(func)
91 def removeidlefunc(self, func):
92 self._idlefuncs.remove(func)
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
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
118 def appendwindow(self, wid, window):
119 self._windows[wid] = window
120 self.makeopenwindowsmenu()
122 def removewindow(self, wid):
123 del self._windows[wid]
124 self.makeopenwindowsmenu()
126 def makeopenwindowsmenu(self):
127 # dummy; could be the full version from PythonIDEMain.py
128 self._openwindows = {}
129 self._openwindowscheckmark = 0
130 if not hasattr(self, "_menustocheck"):
131 self._menustocheck = []
133 def do_key(self, event):
134 (what, message, when, where, modifiers) = event
135 ch = chr(message & FrameWork.charCodeMask)
136 rest = message & ~FrameWork.charCodeMask
137 keycode = (message & FrameWork.keyCodeMask) >> 8
138 if keycode in self.fkeymaps.keys(): # JJS
139 ch = self.fkeymaps[keycode]
140 modifiers = modifiers | FrameWork.cmdKey
141 wid = Win.FrontWindow()
142 if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
143 if wid and self._windows.has_key(wid):
144 self.checkmenus(self._windows[wid])
145 else:
146 self.checkmenus(None)
147 event = (what, ord(ch) | rest, when, where, modifiers)
148 result = MenuToolbox.MenuKey(ord(ch))
149 id = (result>>16) & 0xffff # Hi word
150 item = result & 0xffff # Lo word
151 if id:
152 self.do_rawmenu(id, item, None, event)
153 return # here! we had a menukey!
154 #else:
155 # print "XXX Command-" +`ch`
156 # See whether the front window wants it
157 if wid and self._windows.has_key(wid):
158 window = self._windows[wid]
159 try:
160 do_char = window.do_char
161 except AttributeError:
162 do_char = self.do_char
163 do_char(ch, event)
164 # else it wasn't for us, sigh...
166 def do_inMenuBar(self, partcode, window, event):
167 Qd.InitCursor()
168 (what, message, when, where, modifiers) = event
169 self.checkopenwindowsmenu()
170 wid = Win.FrontWindow()
171 if wid and self._windows.has_key(wid):
172 self.checkmenus(self._windows[wid])
173 else:
174 self.checkmenus(None)
175 result = MenuToolbox.MenuSelect(where)
176 id = (result>>16) & 0xffff # Hi word
177 item = result & 0xffff # Lo word
178 self.do_rawmenu(id, item, window, event)
180 def do_updateEvt(self, event):
181 (what, message, when, where, modifiers) = event
182 wid = Win.WhichWindow(message)
183 if wid and self._windows.has_key(wid):
184 window = self._windows[wid]
185 window.do_rawupdate(wid, event)
186 else:
187 if wid:
188 wid.HideWindow()
189 import sys
190 sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
191 else:
192 MacOS.HandleEvent(event)
194 def suspendresume(self, onoff):
195 pass
197 def do_suspendresume(self, event):
198 self._suspended = not event[1] & 1
199 FrameWork.Application.do_suspendresume(self, event)
201 def checkopenwindowsmenu(self):
202 if self._openwindowscheckmark:
203 self.openwindowsmenu.menu.CheckMenuItem(self._openwindowscheckmark, 0)
204 window = Win.FrontWindow()
205 if window:
206 for item, wid in self._openwindows.items():
207 if wid == window:
208 #self.pythonwindowsmenuitem.check(1)
209 self.openwindowsmenu.menu.CheckMenuItem(item, 1)
210 self._openwindowscheckmark = item
211 break
212 else:
213 self._openwindowscheckmark = 0
214 #if self._openwindows:
215 # self.pythonwindowsmenuitem.enable(1)
216 #else:
217 # self.pythonwindowsmenuitem.enable(0)
219 def checkmenus(self, window):
220 for item in self._menustocheck:
221 callback = item.menu.items[item.item-1][2]
222 if type(callback) <> StringType:
223 item.enable(1)
224 elif hasattr(window, "domenu_" + callback):
225 if hasattr(window, "can_" + callback):
226 canhandler = getattr(window, "can_" + callback)
227 if canhandler(item):
228 item.enable(1)
229 else:
230 item.enable(0)
231 else:
232 item.enable(1)
233 else:
234 item.enable(0)
236 def enablemenubar(self, onoff):
237 for m in self.menubar.menus.values():
238 if onoff:
239 m.menu.EnableMenuItem(0)
240 elif m.menu.GetMenuItemText(3) <> 'Cut': # ew...
241 m.menu.DisableMenuItem(0)
242 MenuToolbox.DrawMenuBar()
244 def makemenubar(self):
245 self.menubar = MenuBar(self)
246 FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
247 self.makeusermenus()
249 def scriptswalk(self, top, menu, done=None):
250 if done is None:
251 done = {}
252 if done.has_key(top):
253 return
254 done[top] = 1
255 import os, macfs, string
256 try:
257 names = os.listdir(top)
258 except os.error:
259 FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
260 return
261 savedir = os.getcwd()
262 os.chdir(top)
263 for name in names:
264 if name == "CVS":
265 continue
266 try:
267 fss, isdir, isalias = macfs.ResolveAliasFile(name)
268 except:
269 # maybe a broken alias
270 continue
271 path = fss.as_pathname()
272 if done.has_key(path):
273 continue
274 name = string.strip(name)
275 if name[-3:] == '---':
276 menu.addseparator()
277 elif isdir:
278 submenu = FrameWork.SubMenu(menu, name)
279 self.scriptswalk(path, submenu, done)
280 else:
281 creator, type = fss.GetCreatorType()
282 if type == 'TEXT':
283 if name[-3:] == '.py':
284 name = name[:-3]
285 item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
286 self._scripts[(menu.id, item.item)] = path
287 done[path] = 1
288 os.chdir(savedir)
290 def domenu_script(self, id, item, window, event):
291 (what, message, when, where, modifiers) = event
292 path = self._scripts[(id, item)]
293 import os
294 if not os.path.exists(path):
295 self.makescriptsmenu()
296 import W
297 raise W.AlertError, "File not found."
298 if ord(Evt.GetKeys()[7]) & 4:
299 self.openscript(path)
300 else:
301 import W, MacOS, sys
302 W.SetCursor("watch")
303 sys.argv = [path]
304 #cwd = os.getcwd()
305 #os.chdir(os.path.dirname(path) + ':')
306 try:
307 # xxx if there is a script window for this file,
308 # exec in that window's namespace.
309 # xxx what to do when it's not saved???
310 # promt to save?
311 MacOS.EnableAppswitch(0)
312 execfile(path, {'__name__': '__main__', '__file__': path})
313 except W.AlertError, detail:
314 MacOS.EnableAppswitch(-1)
315 raise W.AlertError, detail
316 except KeyboardInterrupt:
317 MacOS.EnableAppswitch(-1)
318 except:
319 MacOS.EnableAppswitch(-1)
320 import PyEdit
321 PyEdit.tracebackwindow.traceback(1)
322 else:
323 MacOS.EnableAppswitch(-1)
324 #os.chdir(cwd)
326 def openscript(self, filename, lineno=None, charoffset=0, modname=""):
327 import os, PyEdit, W
328 editor = self.getscript(filename)
329 if editor:
330 editor.select()
331 elif os.path.exists(filename):
332 editor = PyEdit.Editor(filename)
333 elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
334 import imp
335 if not modname:
336 if filename[-1] == 'c':
337 modname = os.path.basename(filename)[:-4]
338 else:
339 modname = os.path.basename(filename)[:-3]
340 try:
341 # XXX This does not work correctly with packages!
342 # XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
343 # XXX It says we should use imp.load_module(), but that *reloads* a package,
344 # XXX and that's the last thing we want here.
345 f, filename, (suff, mode, dummy) = imp.find_module(modname)
346 except ImportError:
347 raise W.AlertError, "Can't find file for \"%s\"" % modname
348 else:
349 if not f:
350 raise W.AlertError, "Can't find file for \"%s\"" % modname
351 f.close()
352 if suff == '.py':
353 self.openscript(filename, lineno, charoffset)
354 return
355 else:
356 raise W.AlertError, "Can't find file for \"%s\"" % modname
357 else:
358 raise W.AlertError, "Can't find file \"%s\"" % filename
359 if lineno is not None:
360 editor.selectline(lineno, charoffset)
361 return editor
363 def getscript(self, filename):
364 if filename[:1] == '<' and filename[-1:] == '>':
365 filename = filename[1:-1]
366 import string
367 lowpath = string.lower(filename)
368 for wid, window in self._windows.items():
369 if hasattr(window, "path") and type(window.path) == StringType and \
370 lowpath == string.lower(window.path):
371 return window
372 elif hasattr(window, "path") and filename == wid.GetWTitle():
373 return window
375 def getprefs(self):
376 import MacPrefs
377 return MacPrefs.GetPrefs(self.preffilepath)
379 def do_editorprefs(self, *args):
380 import PyEdit
381 PyEdit.EditorDefaultSettings()
383 def do_setwindowfont(self, *args):
384 import FontSettings, W
385 prefs = self.getprefs()
386 settings = FontSettings.FontDialog(prefs.defaultfont)
387 if settings:
388 prefs.defaultfont, tabsettings = settings
389 raise W.AlertError, "Note that changes will only affect new windows!"
393 class MenuBar(FrameWork.MenuBar):
395 possibleIDs = range(10, 256)
397 def getnextid(self):
398 id = self.possibleIDs[0]
399 del self.possibleIDs[0]
400 return id
402 def __init__(self, parent = None):
403 self.bar = MenuToolbox.GetMenuBar()
404 MenuToolbox.ClearMenuBar()
405 self.menus = {}
406 self.parent = parent
408 def dispatch(self, id, item, window, event):
409 if self.menus.has_key(id):
410 self.menus[id].dispatch(id, item, window, event)
412 def delmenu(self, id):
413 MenuToolbox.DeleteMenu(id)
414 if id in self.possibleIDs:
415 print "XXX duplicate menu ID!", id
416 self.possibleIDs.append(id)
419 class Menu(FrameWork.Menu):
421 def dispatch(self, id, item, window, event):
422 title, shortcut, callback, kind = self.items[item-1]
423 if type(callback) == StringType:
424 callback = self._getmenuhandler(callback)
425 if callback:
426 import W
427 W.CallbackCall(callback, 0, id, item, window, event)
429 def _getmenuhandler(self, callback):
430 menuhandler = None
431 wid = Win.FrontWindow()
432 if wid and self.bar.parent._windows.has_key(wid):
433 window = self.bar.parent._windows[wid]
434 if hasattr(window, "domenu_" + callback):
435 menuhandler = getattr(window, "domenu_" + callback)
436 elif hasattr(self.bar.parent, "domenu_" + callback):
437 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
438 elif hasattr(self.bar.parent, "domenu_" + callback):
439 menuhandler = getattr(self.bar.parent, "domenu_" + callback)
440 return menuhandler