First Checked In.

This commit is contained in:
Just van Rossum 1999-01-30 22:39:17 +00:00
parent f59a89b5e3
commit 40f9b7bd7c
28 changed files with 8612 additions and 0 deletions

32
Mac/Tools/IDE/BuildIDE.py Normal file
View File

@ -0,0 +1,32 @@
import sys
import os
import buildtools
import Res
import py_resource
buildtools.DEBUG=1
template = buildtools.findtemplate()
ide_home = os.path.join(sys.exec_prefix, ":Mac:Tools:IDE")
mainfilename = os.path.join(ide_home, "PythonIDE.py")
dstfilename = os.path.join(sys.exec_prefix, "Python IDE")
buildtools.process(template, mainfilename, dstfilename, 1)
targetref = Res.OpenResFile(dstfilename)
Res.UseResFile(targetref)
files = os.listdir(ide_home)
files = filter(lambda x: x[-3:] == '.py' and x not in ("BuildIDE.py", "PythonIDE.py"), files)
for name in files:
print "adding", name
fullpath = os.path.join(ide_home, name)
id, name = py_resource.frompyfile(fullpath, name[:-3], preload=1,
ispackage=0)
wresref = Res.OpenResFile(os.path.join(ide_home, "Widgets.rsrc"))
buildtools.copyres(wresref, targetref, [], 0)

View File

@ -0,0 +1,223 @@
"""usage:
newsettings = FontDialog(('Chicago', 0, 12, (0, 0, 0))) # font name or id, style flags, size, color (color is ignored)
if newsettings:
fontsettings, tabsettings = newsettings
font, style, size, color = fontsettings # 'font' is always the font name, not the id number
# do something
"""
import W
import PyEdit
import TextEdit
import Qd
import string
import types
import sys
import MacOS
if hasattr(MacOS, "SysBeep"):
SysBeep = MacOS.SysBeep
else:
def SysBeep(*args):
pass
_stylenames = ["Plain", "Bold", "Italic", "Underline", "Outline", "Shadow", "Condensed", "Extended"]
class _FontDialog:
#def __del__(self):
# print "doei!"
def __init__(self, fontsettings, tabsettings):
leftmargin = 60
leftmargin2 = leftmargin - 16
self.w = W.ModalDialog((440, 180), 'Font settings')
self.w.fonttitle = W.TextBox((10, 12, leftmargin2, 14), "Font:", TextEdit.teJustRight)
self.w.pop = W.FontMenu((leftmargin, 10, 16, 16), self.setfont)
self.w.fontname = W.TextBox((leftmargin + 20, 12, 150, 14))
self.w.sizetitle = W.TextBox((10, 38, leftmargin2, 14), "Size:", TextEdit.teJustRight)
self.w.sizeedit = W.EditText((leftmargin, 35, 40, 20), "", self.checksize)
styletop = 64
self.w.styletitle = W.TextBox((10, styletop + 2, leftmargin2, 14), "Style:", TextEdit.teJustRight)
for i in range(len(_stylenames)):
top = styletop + (i % 4) * 20
left = leftmargin + 80 * (i > 3) - 2
if i:
self.w[i] = W.CheckBox((left, top, 76, 16), _stylenames[i], self.dostyle)
else:
self.w[i] = W.CheckBox((left, top, 70, 16), _stylenames[i], self.doplain)
if tabsettings:
self.lasttab, self.tabmode = tabsettings
self.w.tabsizetitle = W.TextBox((10, -26, leftmargin2, 14), "Tabsize:", TextEdit.teJustRight)
self.w.tabsizeedit = W.EditText((leftmargin, -29, 40, 20), "", self.checktab)
self.w.tabsizeedit.set(`self.lasttab`)
radiobuttons = []
self.w.tabsizechars = W.RadioButton((leftmargin + 48, -26, 55, 14), "Spaces",
radiobuttons, self.toggletabmode)
self.w.tabsizepixels = W.RadioButton((leftmargin + 110, -26, 55, 14), "Pixels",
radiobuttons, self.toggletabmode)
if self.tabmode:
self.w.tabsizechars.set(1)
else:
self.w.tabsizepixels.set(1)
else:
self.tabmode = None
self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
self.w.donebutton = W.Button((-90, -26, 80, 16), "Done", self.done)
sampletext = "Sample text."
self.w.sample = W.EditText((230, 10, -10, 130), sampletext,
fontsettings = fontsettings, tabsettings = tabsettings)
self.w.setdefaultbutton(self.w.donebutton)
self.w.bind('cmd.', self.w.cancelbutton.push)
self.w.bind('cmdw', self.w.donebutton.push)
self.lastsize = fontsettings[2]
self._rv = None
self.set(fontsettings)
self.w.open()
def toggletabmode(self, onoff):
if self.w.tabsizechars.get():
tabmode = 1
else:
tabmode = 0
if self.tabmode <> tabmode:
port = self.w.wid.GetWindowPort()
(font, style, size, color), (tabsize, dummy) = self.get()
savesettings = W.GetPortFontSettings(port)
W.SetPortFontSettings(port, (font, style, size))
spacewidth = Qd.StringWidth(' ')
W.SetPortFontSettings(port, savesettings)
if tabmode:
# convert pixels to spaces
self.lasttab = int(round(float(tabsize) / spacewidth))
else:
# convert spaces to pixels
self.lasttab = spacewidth * tabsize
self.w.tabsizeedit.set(`self.lasttab`)
self.tabmode = tabmode
self.doit()
def set(self, fontsettings):
font, style, size, color = fontsettings
if type(font) <> types.StringType:
import Res
res = Res.GetResource('FOND', font)
font = res.GetResInfo()[2]
self.w.fontname.set(font)
self.w.sizeedit.set(str(size))
if style:
for i in range(1, len(_stylenames)):
self.w[i].set(style & 0x01)
style = style >> 1
else:
self.w[0].set(1)
def get(self):
font = self.w.fontname.get()
style = 0
if not self.w[0].get():
flag = 0x01
for i in range(1, len(_stylenames)):
if self.w[i].get():
style = style | flag
flag = flag << 1
size = self.lastsize
if self.tabmode is None:
return (font, style, size, (0, 0, 0)), (32, 0)
else:
return (font, style, size, (0, 0, 0)), (self.lasttab, self.tabmode)
def doit(self):
if self.w[0].get():
style = 0
else:
style = 0
for i in range(1, len(_stylenames)):
if self.w[i].get():
style = style | 2 ** (i - 1)
#self.w.sample.set(`style`)
fontsettings, tabsettings = self.get()
self.w.sample.setfontsettings(fontsettings)
self.w.sample.settabsettings(tabsettings)
def checktab(self):
tabsize = self.w.tabsizeedit.get()
if not tabsize:
return
try:
tabsize = string.atoi(tabsize)
except (ValueError, OverflowError):
good = 0
sys.exc_traceback = None
else:
good = 1 <= tabsize <= 500
if good:
if self.lasttab <> tabsize:
self.lasttab = tabsize
self.doit()
else:
SysBeep(0)
self.w.tabsizeedit.set(`self.lasttab`)
self.w.tabsizeedit.selectall()
def checksize(self):
size = self.w.sizeedit.get()
if not size:
return
try:
size = string.atoi(size)
except (ValueError, OverflowError):
good = 0
sys.exc_traceback = None
else:
good = 1 <= size <= 500
if good:
if self.lastsize <> size:
self.lastsize = size
self.doit()
else:
SysBeep(0)
self.w.sizeedit.set(`self.lastsize`)
self.w.sizeedit.selectall()
def doplain(self):
for i in range(1, len(_stylenames)):
self.w[i].set(0)
self.w[0].set(1)
self.doit()
def dostyle(self):
for i in range(1, len(_stylenames)):
if self.w[i].get():
self.w[0].set(0)
break
else:
self.w[0].set(1)
self.doit()
def close(self):
self.w.close()
del self.w
def cancel(self):
self.close()
def done(self):
self._rv = self.get()
self.close()
def setfont(self, fontname):
self.w.fontname.set(fontname)
self.doit()
def FontDialog(fontsettings, tabsettings = (32, 0)):
fd = _FontDialog(fontsettings, tabsettings)
return fd._rv
def test():
print FontDialog(('Zapata-Light', 0, 25, (0, 0, 0)))

108
Mac/Tools/IDE/MacPrefs.py Normal file
View File

@ -0,0 +1,108 @@
import macfs
import marshal
import types
kOnSystemDisk = 0x8000
class PrefObject:
def __init__(self, dict = None):
if dict == None:
self._prefsdict = {}
else:
self._prefsdict = dict
def __len__(self):
return len(self._prefsdict)
def __delattr__(self, attr):
if self._prefsdict.has_key(attr):
del self._prefsdict[attr]
else:
raise AttributeError, 'delete non-existing instance attribute'
def __getattr__(self, attr):
if attr == '__members__':
keys = self._prefsdict.keys()
keys.sort()
return keys
try:
return self._prefsdict[attr]
except KeyError:
raise AttributeError, attr
def __setattr__(self, attr, value):
if attr[0] <> '_':
self._prefsdict[attr] = value
else:
self.__dict__[attr] = value
def getprefsdict(self):
return self._prefsdict
class PrefFile(PrefObject):
def __init__(self, path, creator = 'Pyth'):
# Find the preferences folder and our prefs file, create if needed.
self.__path = path
self.__creator = creator
self._prefsdict = {}
try:
prefdict = marshal.load(open(self.__path, 'rb'))
except IOError:
pass
else:
for key, value in prefdict.items():
if type(value) == types.DictType:
self._prefsdict[key] = PrefObject(value)
else:
self._prefsdict[key] = value
def save(self):
prefdict = {}
for key, value in self._prefsdict.items():
if type(value) == types.InstanceType:
prefdict[key] = value.getprefsdict()
if not prefdict[key]:
del prefdict[key]
else:
prefdict[key] = value
marshal.dump(prefdict, open(self.__path, 'wb'))
fss = macfs.FSSpec(self.__path)
fss.SetCreatorType(self.__creator, 'pref')
def __getattr__(self, attr):
if attr == '__members__':
keys = self._prefsdict.keys()
keys.sort()
return keys
try:
return self._prefsdict[attr]
except KeyError:
if attr[0] <> '_':
self._prefsdict[attr] = PrefObject()
return self._prefsdict[attr]
else:
raise AttributeError, attr
_prefscache = {}
def GetPrefs(prefname, creator = 'Pyth'):
import macostools, os
if _prefscache.has_key(prefname):
return _prefscache[prefname]
# Find the preferences folder and our prefs file, create if needed.
vrefnum, dirid = macfs.FindFolder(kOnSystemDisk, 'pref', 0)
prefsfolder_fss = macfs.FSSpec((vrefnum, dirid, ''))
prefsfolder = prefsfolder_fss.as_pathname()
path = os.path.join(prefsfolder, prefname)
head, tail = os.path.split(path)
# make sure the folder(s) exist
macostools.mkdirs(head)
preffile = PrefFile(path, creator)
_prefscache[prefname] = preffile
return preffile

View File

@ -0,0 +1,178 @@
import W
import sys
import Qd
__version__ = "0.2"
__author__ = "jvr"
class _modulebrowser:
def __init__(self):
self.editmodules = []
self.modules = []
self.window = W.Window((194, 1000), "Module Browser", minsize = (194, 160), maxsize = (340, 20000))
#self.window.bevelbox = W.BevelBox((0, 0, 0, 56))
self.window.openbutton = W.Button((10, 8, 80, 16), "Open", self.openbuttonhit)
self.window.browsebutton = W.Button((100, 8, 80, 16), "BrowseÉ", self.browsebuttonhit)
self.window.reloadbutton = W.Button((10, 32, 80, 16), "Reload", self.reloadbuttonhit)
self.window.openotherbutton = W.Button((100, 32, 80, 16), "Open otherÉ", self.openother)
self.window.openbutton.enable(0)
self.window.reloadbutton.enable(0)
self.window.browsebutton.enable(0)
self.window.setdefaultbutton(self.window.browsebutton)
self.window.bind("cmdr", self.window.reloadbutton.push)
self.window.bind("cmdb", self.window.browsebutton.push)
self.window.bind("<activate>", self.activate)
self.window.bind("<close>", self.close)
self.window.list = W.List((-1, 56, 1, -14), [], self.listhit)
self.window.open()
self.checkbuttons()
def close(self):
global _browser
_browser = None
def activate(self, onoff):
if onoff:
self.makelist()
def listhit(self, isdbl):
self.checkbuttons()
if isdbl:
if self.window._defaultbutton:
self.window._defaultbutton.push()
def checkbuttons(self):
sel = self.window.list.getselection()
if sel:
for i in sel:
if self.editmodules[i]:
self.window.openbutton.enable(1)
self.window.reloadbutton.enable(1)
self.window.setdefaultbutton(self.window.openbutton)
break
else:
self.window.openbutton.enable(0)
self.window.reloadbutton.enable(0)
self.window.setdefaultbutton(self.window.browsebutton)
self.window.browsebutton.enable(1)
else:
#self.window.setdefaultbutton(self.window.browsebutton)
self.window.openbutton.enable(0)
self.window.reloadbutton.enable(0)
self.window.browsebutton.enable(0)
def openbuttonhit(self):
import imp
sel = self.window.list.getselection()
W.SetCursor("watch")
for i in sel:
modname = self.window.list[i]
try:
self.openscript(sys.modules[modname].__file__, modname)
except IOError:
try:
file, path, description = imp.find_module(modname)
except ImportError:
W.SetCursor("arrow")
W.Message("CanÕt find file for module Ò%sÓ."
% modname)
else:
self.openscript(path, modname)
def openscript(self, path, modname):
import os
if path[-3:] == '.py':
W.getapplication().openscript(path, modname=modname)
elif path[-4:] in ['.pyc', '.pyo']:
W.getapplication().openscript(path[:-1], modname=modname)
else:
W.Message("CanÕt edit Ò%sÓ; it might be a shared library or a .pyc file."
% modname)
def openother(self):
import imp
import EasyDialogs
modname = EasyDialogs.AskString("Open module:")
if modname:
try:
file, path, description = imp.find_module(modname)
except ImportError:
if modname in sys.builtin_module_names:
alerttext = "Ò%sÓ is a builtin module, which you canÕt edit." % modname
else:
alerttext = "No module named Ò%sÓ." % modname
raise W.AlertError, alerttext
self.openscript(path, modname)
def reloadbuttonhit(self):
sel = self.window.list.getselection()
W.SetCursor("watch")
for i in sel:
mname = self.window.list[i]
m = sys.modules[mname]
# Set the __name__ attribute of the module to its real name.
# reload() complains if it's __main__, which is true
# when it recently has been run as a script with "Run as __main__"
# enabled.
m.__name__ = mname
reload(m)
def browsebuttonhit(self):
sel = self.window.list.getselection()
if not sel:
return
import PyBrowser
for i in sel:
PyBrowser.Browser(sys.modules[self.window.list[i]])
def makelist(self):
editmodules, modules = getmoduleslist()
if modules == self.modules:
return
self.editmodules, self.modules = editmodules, modules
self.window.list.setdrawingmode(0)
sel = self.window.list.getselectedobjects()
self.window.list.set(self.modules)
self.window.list.setselectedobjects(sel)
self.window.list.setdrawingmode(1)
def getmoduleslist():
import PyBrowser # for caselesssort function
moduleitems = sys.modules.items()
moduleitems = filter(lambda (name, module): module is not None, moduleitems)
modules = map(lambda (name, module): name, moduleitems)
modules = PyBrowser.caselesssort(modules)
editmodules = []
sysmodules = sys.modules
modulesappend = editmodules.append
for m in modules:
module = sysmodules[m]
try:
if sysmodules[m].__file__[-3:] == '.py' or \
sysmodules[m].__file__[-4:] in ['.pyc', '.pyo']:
modulesappend(1)
else:
modulesappend(0)
except AttributeError:
modulesappend(0)
return editmodules, modules
_browser = None
def ModuleBrowser():
global _browser
if _browser is not None:
_browser.window.select()
else:
_browser = _modulebrowser()

View File

@ -0,0 +1,91 @@
import W
import Evt
import sys
import StringIO
import string
import pstats, fpformat
# increase precision
def f8(x):
return string.rjust(fpformat.fix(x, 4), 8)
pstats.f8 = f8
# hacking around a hack
if sys.version[:3] > '1.4':
timer = Evt.TickCount
else:
def timer(TickCount = Evt.TickCount):
return TickCount() / 60.0
class ProfileBrowser:
def __init__(self, stats = None):
self.sortkeys = ('calls',)
self.setupwidgets()
self.setstats(stats)
def setupwidgets(self):
self.w = W.Window((580, 400), "Profile Statistics", minsize = (200, 100), tabbable = 0)
self.w.divline = W.HorizontalLine((0, 20, 0, 0))
self.w.titlebar = W.TextBox((4, 4, 40, 12), 'Sort by:')
self.buttons = []
self.w.button_calls = W.RadioButton((54, 4, 45, 12), 'calls', self.buttons, self.setsort)
self.w.button_time = W.RadioButton((104, 4, 40, 12), 'time', self.buttons, self.setsort)
self.w.button_cumulative = W.RadioButton((154, 4, 75, 12), 'cumulative', self.buttons, self.setsort)
self.w.button_stdname = W.RadioButton((234, 4, 60, 12), 'stdname', self.buttons, self.setsort)
self.w.button_calls.set(1)
self.w.button_file = W.RadioButton((304, 4, 40, 12), 'file', self.buttons, self.setsort)
self.w.button_line = W.RadioButton((354, 4, 50, 12), 'line', self.buttons, self.setsort)
self.w.button_name = W.RadioButton((404, 4, 50, 12), 'name', self.buttons, self.setsort)
## self.w.button_nfl = W.RadioButton((4, 4, 12, 12), 'nfl', self.buttons, self.setsort)
## self.w.button_pcalls = W.RadioButton((4, 4, 12, 12), 'pcalls', self.buttons, self.setsort)
self.w.text = W.TextEditor((0, 21, -15, -15), inset = (6, 5),
readonly = 1, wrap = 0, fontsettings = ('Monaco', 0, 9, (0, 0, 0)))
self.w._bary = W.Scrollbar((-15, 20, 16, -14), self.w.text.vscroll, max = 32767)
self.w._barx = W.Scrollbar((-1, -15, -14, 16), self.w.text.hscroll, max = 32767)
self.w.open()
def setstats(self, stats):
self.stats = stats
self.stats.strip_dirs()
self.displaystats()
def setsort(self):
# Grmpf. The callback doesn't give us the button:-(
for b in self.buttons:
if b.get():
if b._title == self.sortkeys[0]:
return
self.sortkeys = (b._title,) + self.sortkeys[:3]
break
self.displaystats()
def displaystats(self):
W.SetCursor('watch')
apply(self.stats.sort_stats, self.sortkeys)
saveout = sys.stdout
try:
s = sys.stdout = StringIO.StringIO()
self.stats.print_stats()
finally:
sys.stdout = saveout
text = string.join(string.split(s.getvalue(), '\n'), '\r')
self.w.text.set(text)
def main():
import pstats
args = sys.argv[1:]
for i in args:
stats = pstats.Stats(i)
browser = ProfileBrowser(stats)
else:
import macfs
fss, ok = macfs.PromptGetFile('Profiler data')
if not ok: sys.exit(0)
stats = pstats.Stats(fss.as_pathname())
browser = ProfileBrowser(stats)
if __name__ == '__main__':
main()

440
Mac/Tools/IDE/PyBrowser.py Normal file
View File

@ -0,0 +1,440 @@
import W
import Wkeys
import struct
import string
import types
import regex
nullid = '\0\0'
closedid = struct.pack('h', 468)
openid = struct.pack('h', 469)
closedsolidid = struct.pack('h', 470)
opensolidid = struct.pack('h', 471)
arrows = (nullid, closedid, openid, closedsolidid, opensolidid)
has_ctlcharsRE = regex.compile('[\000-\037\177-\377]')
def double_repr(key, value, truncvalue = 0,
type = type, StringType = types.StringType,
has_ctlchars = has_ctlcharsRE.search, _repr = repr, str = str):
if type(key) == StringType and has_ctlchars(key) < 0:
key = str(key)
else:
key = _repr(key)
if type(value) == StringType and has_ctlchars(value) < 0:
value = str(value)
elif key == '__builtins__':
value = "<" + type(value).__name__ + " '__builtin__'>"
elif key == '__return__':
# bleh, when returning from a class codeblock we get infinite recursion in repr.
# Use safe repr instead.
import repr
value = repr.repr(value)
else:
try:
value = _repr(value)
'' + value # test to see if it is a string, in case a __repr__ method is buggy
except:
value = '¥¥¥ exception in repr()'
if truncvalue:
return key + '\t' + value[:255]
return key + '\t' + value
class BrowserWidget(W.List):
LDEF_ID = 471
def __init__(self, possize, object = None, col = 100, closechildren = 0):
W.List.__init__(self, possize, callback = self.listhit)
self.object = (None,)
self.indent = 16
self.lastmaxindent = 0
self.closechildren = closechildren
self.children = []
self.mincol = 64
self.setcolumn(col)
self.bind('return', self.openselection)
self.bind('enter', self.openselection)
if object is not None:
self.set(object)
def set(self, object):
if self.object[0] is not object:
self.object = object,
self[:] = self.unpack(object, 0)
elif self._parentwindow is not None and self._parentwindow.wid:
self.update()
def unpack(self, object, indent):
return unpack_object(object, indent)
def update(self):
# for now...
W.SetCursor('watch')
self.setdrawingmode(0)
sel = self.getselectedobjects()
fold = self.getunfoldedobjects()
topcell = self.gettopcell()
self[:] = self.unpack(self.object[0], 0)
self.unfoldobjects(fold)
self.setselectedobjects(sel)
self.settopcell(topcell)
self.setdrawingmode(1)
def setcolumn(self, col):
self.col = col
self.colstr = struct.pack('h', col)
if self._list:
sel = self.getselection()
self.setitems(self.items)
self.setselection(sel)
def key(self, char, event):
if char in (Wkeys.leftarrowkey, Wkeys.rightarrowkey):
sel = self.getselection()
sel.reverse()
self.setdrawingmode(0)
for index in sel:
self.fold(index, char == Wkeys.rightarrowkey)
self.setdrawingmode(1)
else:
W.List.key(self, char, event)
def rollover(self, (x, y), onoff):
if onoff:
if self.incolumn((x, y)):
W.SetCursor('hmover')
else:
W.SetCursor('arrow')
def inarrow(self, (x, y)):
cl, ct, cr, cb = self._list.LRect((0, 0))
l, t, r, b = self._bounds
if (x - cl) < 16:
cellheight = cb - ct
index = (y - ct) / cellheight
if index < len(self.items):
return 1, index
return None, None
def incolumn(self, (x, y)):
l, t, r, b = self._list.LRect((0, 0))
abscol = l + self.col
return abs(abscol - x) < 3
def trackcolumn(self, (x, y)):
import Qd, QuickDraw, Evt
self.SetPort()
l, t, r, b = self._bounds
bounds = l, t, r, b = l + 1, t + 1, r - 16, b - 1
abscol = l + self.col
mincol = l + self.mincol
maxcol = r - 10
diff = abscol - x
Qd.PenPat('\000\377\000\377\000\377\000\377')
Qd.PenMode(QuickDraw.srcXor)
rect = abscol - 1, t, abscol, b
Qd.PaintRect(rect)
lastpoint = (x, y)
newcol = -1
#W.SetCursor('fist')
while Evt.Button():
(x, y) = Evt.GetMouse()
if (x, y) <> lastpoint:
newcol = x + diff
newcol = max(newcol, mincol)
newcol = min(newcol, maxcol)
Qd.PaintRect(rect)
rect = newcol - 1, t, newcol, b
Qd.PaintRect(rect)
lastpoint = (x, y)
Qd.PaintRect(rect)
Qd.PenPat(Qd.qd.black)
Qd.PenNormal()
if newcol > 0 and newcol <> abscol:
self.setcolumn(newcol - l)
def click(self, point, modifiers):
if point == (-1, -1): # gross.
W.List.click(self, point ,modifiers)
return
hit, index = self.inarrow(point)
if hit:
(key, value, arrow, indent) = self.items[index]
self.fold(index, arrow == 1)
elif self.incolumn(point):
self.trackcolumn(point)
else:
W.List.click(self, point, modifiers)
# for W.List.key
def findmatch(self, tag):
lower = string.lower
items = self.items
taglen = len(tag)
match = '\377' * 100
match_i = -1
for i in range(len(items)):
item = lower(str(items[i][0]))
if tag <= item < match:
match = item
match_i = i
if match_i >= 0:
return match_i
else:
return len(items) - 1
def close(self):
if self.closechildren:
for window in self.children:
window.close()
self.children = []
W.List.close(self)
def fold(self, index, onoff):
(key, value, arrow, indent) = self.items[index]
if arrow == 0 or (onoff and arrow == 2) or (not onoff and arrow == 1):
return
W.SetCursor('watch')
topcell = self.gettopcell()
if onoff:
self[index] = (key, value, 4, indent)
self.setdrawingmode(0)
self[index+1:index+1] = self.unpack(value, indent + 1)
self[index] = (key, value, 2, indent)
else:
self[index] = (key, value, 3, indent)
self.setdrawingmode(0)
count = 0
for i in range(index + 1, len(self.items)):
(dummy, dummy, dummy, subindent) = self.items[i]
if subindent <= indent:
break
count = count + 1
self[index+1:index+1+count] = []
self[index] = (key, value, 1, indent)
maxindent = self.getmaxindent()
if maxindent <> self.lastmaxindent:
newabsindent = self.col + (maxindent - self.lastmaxindent) * self.indent
if newabsindent >= self.mincol:
self.setcolumn(newabsindent)
self.lastmaxindent = maxindent
self.settopcell(topcell)
self.setdrawingmode(1)
def unfoldobjects(self, objects):
for obj in objects:
try:
index = self.items.index(obj)
except ValueError:
pass
else:
self.fold(index, 1)
def getunfoldedobjects(self):
curindent = 0
objects = []
for index in range(len(self.items)):
(key, value, arrow, indent) = self.items[index]
if indent > curindent:
(k, v, a, i) = self.items[index - 1]
objects.append((k, v, 1, i))
curindent = indent
elif indent < curindent:
curindent = indent
return objects
def listhit(self, isdbl):
if isdbl:
self.openselection()
def openselection(self):
import os
sel = self.getselection()
for index in sel:
(key, value, arrow, indent) = self[index]
if arrow:
self.children.append(Browser(value))
elif type(value) == types.StringType and '\0' not in value:
editor = self._parentwindow.parent.getscript(value)
if editor:
editor.select()
return
elif os.path.exists(value) and os.path.isfile(value):
import macfs
fss = macfs.FSSpec(value)
if fss.GetCreatorType()[1] == 'TEXT':
W.getapplication().openscript(value)
def itemrepr(self, (key, value, arrow, indent), str = str, double_repr = double_repr,
arrows = arrows, pack = struct.pack):
arrow = arrows[arrow]
return arrow + pack('h', self.indent * indent) + self.colstr + \
double_repr(key, value, 1)
def getmaxindent(self, max = max):
maxindent = 0
for item in self.items:
maxindent = max(maxindent, item[3])
return maxindent
def domenu_copy(self, *args):
sel = self.getselectedobjects()
selitems = []
for key, value, dummy, dummy in sel:
selitems.append(double_repr(key, value))
text = string.join(selitems, '\r')
if text:
import Scrap
Scrap.ZeroScrap()
Scrap.PutScrap('TEXT', text)
class Browser:
def __init__(self, object = None, title = None, closechildren = 0):
if hasattr(object, '__name__'):
name = object.__name__
else:
name = ''
if title is None:
title = 'Object browser'
if name:
title = title + ': ' + name
self.w = w = W.Window((300, 400), title, minsize = (100, 100))
w.info = W.TextBox((18, 8, -70, 15))
w.updatebutton = W.Button((-64, 4, 50, 16), 'Update', self.update)
w.browser = BrowserWidget((-1, 24, 1, -14), None)
w.bind('cmdu', w.updatebutton.push)
w.open()
self.set(object, name)
def close(self):
if self.w.wid:
self.w.close()
def set(self, object, name = ''):
W.SetCursor('watch')
tp = type(object).__name__
try:
length = len(object)
except:
length = -1
if not name and hasattr(object, '__name__'):
name = object.__name__
if name:
info = name + ': ' + tp
else:
info = tp
if length >= 0:
if length == 1:
info = info + ' (%d element)' % length
else:
info = info + ' (%d elements)' % length
self.w.info.set(info)
self.w.browser.set(object)
def update(self):
self.w.browser.update()
SIMPLE_TYPES = (
types.NoneType,
types.IntType,
types.LongType,
types.FloatType,
types.ComplexType,
types.StringType
)
INDEXING_TYPES = (
types.TupleType,
types.ListType,
types.DictionaryType
)
def unpack_object(object, indent = 0):
tp = type(object)
if tp in SIMPLE_TYPES and tp is not types.NoneType:
raise TypeError, 'canÕt browse simple type: %s' % tp.__name__
elif tp == types.DictionaryType:
return unpack_dict(object, indent)
elif tp in (types.TupleType, types.ListType):
return unpack_sequence(object, indent)
elif tp == types.InstanceType:
return unpack_instance(object, indent)
elif tp == types.ClassType:
return unpack_class(object, indent)
elif tp == types.ModuleType:
return unpack_dict(object.__dict__, indent)
else:
return unpack_other(object, indent)
def unpack_sequence(seq, indent = 0):
items = map(None, range(len(seq)), seq)
items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent:
(k, v, not type(v) in simp, indent), items)
return items
def unpack_dict(dict, indent = 0):
items = dict.items()
return pack_items(items, indent)
def unpack_instance(inst, indent = 0):
if hasattr(inst, '__pybrowse_unpack__'):
return unpack_object(inst.__pybrowse_unpack__(), indent)
else:
items = [('__class__', inst.__class__)] + inst.__dict__.items()
return pack_items(items, indent)
def unpack_class(clss, indent = 0):
items = [('__bases__', clss.__bases__), ('__name__', clss.__name__)] + clss.__dict__.items()
return pack_items(items, indent)
def unpack_other(object, indent = 0):
attrs = []
if hasattr(object, '__members__'):
attrs = attrs + object.__members__
if hasattr(object, '__methods__'):
attrs = attrs + object.__methods__
items = []
for attr in attrs:
items.append((attr, getattr(object, attr)))
return pack_items(items, indent)
def pack_items(items, indent = 0):
items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent:
(k, v, not type(v) in simp, indent),
items)
return tuple_caselesssort(items)
def caselesssort(alist):
"""Return a sorted copy of a list. If there are only strings in the list,
it will not consider case"""
try:
# turn ['FOO', 'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible
tupledlist = map(lambda item, lower = string.lower: (lower(item), item), alist)
except TypeError:
# at least one element in alist is not a string, proceed the normal way...
alist = alist[:]
alist.sort()
return alist
else:
tupledlist.sort()
# turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO']
return map(lambda x: x[1], tupledlist)
def tuple_caselesssort(items):
try:
tupledlist = map(lambda tuple, lower = string.lower: (lower(tuple[0]), tuple), items)
except TypeError:
items = items[:]
items.sort()
return items
else:
tupledlist.sort()
return map(lambda (low, tuple): tuple, tupledlist)

380
Mac/Tools/IDE/PyConsole.py Normal file
View File

@ -0,0 +1,380 @@
import W
import Wkeys
import Fm
import WASTEconst
from types import *
import Events
import string
import sys
import traceback
import MacOS
import MacPrefs
import Qd
import PyInteractive
if not hasattr(sys, 'ps1'):
sys.ps1 = '>>> '
if not hasattr(sys, 'ps2'):
sys.ps2 = '... '
def inspect(foo): # JJS 1/25/99
"Launch the browser on the given object. This is a general built-in function."
import PyBrowser
PyBrowser.Browser(foo)
class ConsoleTextWidget(W.EditText):
def __init__(self, *args, **kwargs):
apply(W.EditText.__init__, (self,) + args, kwargs)
self._inputstart = 0
self._buf = ''
self.pyinteractive = PyInteractive.PyInteractive()
import __main__
self._namespace = __main__.__dict__
self._namespace['inspect'] = inspect # JJS 1/25/99
def insert(self, text):
self.checkselection()
self.ted.WEInsert(text, None, None)
self.changed = 1
self.selchanged = 1
def set_namespace(self, dict):
if type(dict) <> DictionaryType:
raise TypeError, "The namespace needs to be a dictionary"
if 'inspect' not in dict.keys(): dict['inspect'] = inspect # JJS 1/25/99
self._namespace = dict
def open(self):
W.EditText.open(self)
self.write('Python ' + sys.version + '\n' + sys.copyright + '\n')
self.write(sys.ps1)
self.flush()
def key(self, char, event):
(what, message, when, where, modifiers) = event
if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
if char not in Wkeys.navigationkeys:
self.checkselection()
if char == Wkeys.enterkey:
char = Wkeys.returnkey
selstart, selend = self.getselection()
if char == Wkeys.backspacekey:
if selstart <= (self._inputstart - (selstart <> selend)):
return
self.ted.WEKey(ord(char), modifiers)
if char not in Wkeys.navigationkeys:
self.changed = 1
if char not in Wkeys.scrollkeys:
self.selchanged = 1
self.updatescrollbars()
if char == Wkeys.returnkey:
text = self.get()[self._inputstart:selstart]
text = string.join(string.split(text, "\r"), "\n")
saveyield = MacOS.EnableAppswitch(0)
self.pyinteractive.executeline(text, self, self._namespace)
MacOS.EnableAppswitch(saveyield)
selstart, selend = self.getselection()
self._inputstart = selstart
def domenu_save_as(self, *args):
import macfs
fss, ok = macfs.StandardPutFile('Save console text as:', 'console.txt')
if not ok:
return
f = open(fss.as_pathname(), 'wb')
f.write(self.get())
f.close()
fss.SetCreatorType(W._signature, 'TEXT')
def write(self, text):
self._buf = self._buf + text
if '\n' in self._buf:
self.flush()
def flush(self):
stuff = string.split(self._buf, '\n')
stuff = string.join(stuff, '\r')
self.setselection_at_end()
self.ted.WEInsert(stuff, None, None)
selstart, selend = self.getselection()
self._inputstart = selstart
self._buf = ""
self.ted.WEClearUndo()
self.updatescrollbars()
def selection_ok(self):
selstart, selend = self.getselection()
return not (selstart < self._inputstart or selend < self._inputstart)
def checkselection(self):
if not self.selection_ok():
self.setselection_at_end()
def setselection_at_end(self):
end = self.ted.WEGetTextLength()
self.setselection(end, end)
self.updatescrollbars()
def domenu_cut(self, *args):
if not self.selection_ok():
return
W.EditText.domenu_cut(self)
def domenu_paste(self, *args):
if not self.selection_ok():
self.setselection_at_end()
W.EditText.domenu_paste(self)
def domenu_clear(self, *args):
if not self.selection_ok():
return
W.EditText.domenu_clear(self)
class PyConsole(W.Window):
def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)),
tabsettings = (32, 0), unclosable = 0):
W.Window.__init__(self,
bounds,
"Python Interactive",
minsize = (200, 100),
tabbable = 0,
show = show)
self._unclosable = unclosable
consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5),
fontsettings = fontsettings, tabsettings = tabsettings)
self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767)
self.consoletext = consoletext
self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace)
self.namespacemenu.bind('<click>', self.makenamespacemenu)
self.open()
def makenamespacemenu(self, *args):
W.SetCursor('watch')
namespacelist = self.getnamespacelist()
self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settingsÉ", self.dofontsettings),
["Namespace"] + namespacelist, ("Browse namespaceÉ", self.browsenamespace)])
currentname = self.consoletext._namespace["__name__"]
for i in range(len(namespacelist)):
if namespacelist[i][0] == currentname:
break
else:
return
# XXX this functionality should be generally available in Wmenus
submenuid = self.namespacemenu.menu.menu.GetItemMark(3)
menu = self.namespacemenu.menu.bar.menus[submenuid]
menu.menu.CheckItem(i + 1, 1)
def browsenamespace(self):
import PyBrowser, W
W.SetCursor('watch')
PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"])
def clearbuffer(self):
import Res
self.consoletext.ted.WEUseText(Res.Resource(''))
self.consoletext.write(sys.ps1)
self.consoletext.flush()
def getnamespacelist(self):
import os
import __main__
editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values())
namespaces = [ ("__main__",__main__.__dict__) ]
for ed in editors:
modname = os.path.splitext(ed.title)[0]
if sys.modules.has_key(modname):
module = sys.modules[modname]
namespaces.append((modname, module.__dict__))
else:
if ed.title[-3:] == '.py':
modname = ed.title[:-3]
else:
modname = ed.title
ed.globals["__name__"] = modname
namespaces.append((modname, ed.globals))
return namespaces
def dofontsettings(self):
import FontSettings
settings = FontSettings.FontDialog(self.consoletext.getfontsettings(),
self.consoletext.gettabsettings())
if settings:
fontsettings, tabsettings = settings
self.consoletext.setfontsettings(fontsettings)
self.consoletext.settabsettings(tabsettings)
def show(self, onoff = 1):
W.Window.show(self, onoff)
if onoff:
self.select()
def close(self):
if self._unclosable:
self.show(0)
return -1
W.Window.close(self)
def writeprefs(self):
prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
prefs.console.show = self.isvisible()
prefs.console.windowbounds = self.getbounds()
prefs.console.fontsettings = self.consoletext.getfontsettings()
prefs.console.tabsettings = self.consoletext.gettabsettings()
prefs.save()
class OutputTextWidget(W.EditText):
def domenu_save_as(self, *args):
title = self._parentwindow.gettitle()
import macfs
fss, ok = macfs.StandardPutFile('Save %s text as:' % title, title + '.txt')
if not ok:
return
f = open(fss.as_pathname(), 'wb')
f.write(self.get())
f.close()
fss.SetCreatorType(W._signature, 'TEXT')
class PyOutput:
def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)):
self.bounds = bounds
self.fontsettings = fontsettings
self.tabsettings = tabsettings
self.w = None
self.closed = 1
self._buf = ''
# should be able to set this
self.savestdout, self.savestderr = sys.stdout, sys.stderr
sys.stderr = sys.stdout = self
if show:
self.show()
def setupwidgets(self):
self.w = W.Window(self.bounds, "Output",
minsize = (200, 100),
tabbable = 0)
self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5),
fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1)
menuitems = [("Clear window", self.clearbuffer), ("Font settingsÉ", self.dofontsettings)]
self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems)
self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767)
self.w.bind("<close>", self.close)
self.w.bind("<activate>", self.activate)
def write(self, text):
oldyield = MacOS.EnableAppswitch(-1)
try:
self._buf = self._buf + text
if '\n' in self._buf:
self.flush()
finally:
MacOS.EnableAppswitch(oldyield)
def flush(self):
self.show()
stuff = string.split(self._buf, '\n')
stuff = string.join(stuff, '\r')
end = self.w.outputtext.ted.WEGetTextLength()
self.w.outputtext.setselection(end, end)
self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
self.w.outputtext.ted.WEInsert(stuff, None, None)
self._buf = ""
self.w.outputtext.updatescrollbars()
self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
def show(self):
if self.closed:
if not self.w:
self.setupwidgets()
self.w.open()
self.w.outputtext.updatescrollbars()
self.closed = 0
else:
self.w.show(1)
self.closed = 0
self.w.select()
def writeprefs(self):
if self.w is not None:
prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
prefs.output.show = self.w.isvisible()
prefs.output.windowbounds = self.w.getbounds()
prefs.output.fontsettings = self.w.outputtext.getfontsettings()
prefs.output.tabsettings = self.w.outputtext.gettabsettings()
prefs.save()
def dofontsettings(self):
import FontSettings
settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(),
self.w.outputtext.gettabsettings())
if settings:
fontsettings, tabsettings = settings
self.w.outputtext.setfontsettings(fontsettings)
self.w.outputtext.settabsettings(tabsettings)
def clearbuffer(self):
import Res
self.w.outputtext.set('')
def activate(self, onoff):
if onoff:
self.closed = 0
def close(self):
self.w.show(0)
self.closed = 1
return -1
class SimpleStdin:
def readline(self):
import EasyDialogs
sys.stdout.flush()
rv = EasyDialogs.AskString("")
if rv is None:
return ""
return rv + '\n'
def installconsole(defaultshow = 1):
global console
prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
if not prefs.console or not hasattr(prefs.console, 'show'):
prefs.console.show = defaultshow
if not hasattr(prefs.console, "windowbounds"):
prefs.console.windowbounds = (450, 250)
if not hasattr(prefs.console, "fontsettings"):
prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
if not hasattr(prefs.console, "tabsettings"):
prefs.console.tabsettings = (32, 0)
console = PyConsole(prefs.console.windowbounds, prefs.console.show,
prefs.console.fontsettings, prefs.console.tabsettings, 1)
def installoutput(defaultshow = 0, OutPutWindow = PyOutput):
global output
# quick 'n' dirty std in emulation
sys.stdin = SimpleStdin()
prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
if not prefs.output or not hasattr(prefs.output, 'show'):
prefs.output.show = defaultshow
if not hasattr(prefs.output, "windowbounds"):
prefs.output.windowbounds = (450, 250)
if not hasattr(prefs.output, "fontsettings"):
prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
if not hasattr(prefs.output, "tabsettings"):
prefs.output.tabsettings = (32, 0)
output = OutPutWindow(prefs.output.windowbounds, prefs.output.show,
prefs.output.fontsettings, prefs.output.tabsettings)

887
Mac/Tools/IDE/PyDebugger.py Normal file
View File

@ -0,0 +1,887 @@
import sys
import bdb
import types
import os
import W
import WASTEconst
import PyBrowser
import Qd
import Evt
import Lists
import MacOS
_filenames = {}
SIMPLE_TYPES = (
types.NoneType,
types.IntType,
types.LongType,
types.FloatType,
types.ComplexType,
types.StringType
)
class Debugger(bdb.Bdb):
def __init__(self, title = 'Debugger'):
bdb.Bdb.__init__(self)
self.closed = 1
self.title = title
self.breaksviewer = None
self.reset()
self.tracing = 0
self.tracingmonitortime = Evt.TickCount()
self.editors = {}
prefs = W.getapplication().getprefs()
if prefs.debugger:
for file, breaks in prefs.debugger.breaks.items():
for b in breaks:
self.set_break(file, b)
self.bounds, self.horpanes, self.verpanes = prefs.debugger.windowsettings
self.tracemagic = prefs.debugger.tracemagic
else:
self.breaks = {}
self.horpanes = (0.4, 0.6)
self.verpanes = (0.3, 0.35, 0.35)
self.bounds = (600, 400)
self.tracemagic = 0
self.laststacksel = None
def reset(self):
self.currentframe = None
self.file = None
self.laststack = None
self.reason = 'Not running'
self.continuewithoutdebugger = 0
bdb.Bdb.reset(self)
self.forget()
def start(self, bottomframe = None, running = 0):
W.getapplication().DebuggerQuit = bdb.BdbQuit
import Menu
Menu.HiliteMenu(0)
if self.closed:
self.setupwidgets(self.title)
self.closed = 0
if not self.w.parent.debugger_quitting:
self.w.select()
raise W.AlertError, 'There is another debugger session busy.'
self.reset()
self.botframe = bottomframe
if running:
self.set_continue()
self.reason = 'RunningÉ'
self.setstate('running')
else:
self.set_step()
self.reason = 'stopped'
self.setstate('stopped')
sys.settrace(self.trace_dispatch)
def stop(self):
self.set_quit()
if self.w.parent:
self.exit_mainloop()
self.resetwidgets()
def set_continue_without_debugger(self):
sys.settrace(None)
self.set_quit()
self.clear_tracefuncs()
self.continuewithoutdebugger = 1
if self.w.parent:
self.exit_mainloop()
self.resetwidgets()
def clear_tracefuncs(self):
try:
raise 'spam'
except:
pass
frame = sys.exc_traceback.tb_frame
while frame is not None:
del frame.f_trace
frame = frame.f_back
def postmortem(self, exc_type, exc_value, traceback):
if self.closed:
self.setupwidgets(self.title)
self.closed = 0
if not self.w.parent.debugger_quitting:
raise W.AlertError, 'There is another debugger session busy.'
self.reset()
if traceback:
self.botframe = traceback.tb_frame
while traceback.tb_next <> None:
traceback = traceback.tb_next
frame = traceback.tb_frame
else:
self.botframe = None
frame = None
self.w.panes.bottom.buttons.killbutton.enable(1)
self.reason = '(dead) ' + self.formatexception(exc_type, exc_value)
self.w.select()
self.setup(frame, traceback)
self.setstate('dead')
self.showstack(self.curindex)
self.showframe(self.curindex)
def setupwidgets(self, title):
self.w = w = W.Window(self.bounds, title, minsize = (500, 300))
w.panes = W.HorizontalPanes((8, 4, -8, -8), self.horpanes)
w.panes.browserpanes = browserpanes = W.VerticalPanes(None, self.verpanes)
browserpanes.stacklist = W.Group(None)
browserpanes.stacklist.title = W.TextBox((4, 0, 0, 12), 'Stack')
browserpanes.stacklist.stack = W.List((0, 16, 0, 0), callback = self.do_stack, flags = Lists.lOnlyOne)
browserpanes.locals = W.Group(None)
browserpanes.locals.title = W.TextBox((4, 0, 0, 12), 'Local variables')
browserpanes.locals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0))
browserpanes.globals = W.Group(None)
browserpanes.globals.title = W.TextBox((4, 0, 0, 12), 'Global variables')
browserpanes.globals.browser = PyBrowser.BrowserWidget((0, 16, 0, 0))
w.panes.bottom = bottom = W.Group(None)
bottom.src = src = W.Group((0, 52, 0, 0))
source = SourceViewer((1, 1, -15, -15), readonly = 1, debugger = self)
src.optionsmenu = W.PopupMenu((-16, 0, 16, 16), [])
src.optionsmenu.bind('<click>', self.makeoptionsmenu)
src._barx = W.Scrollbar((0, -16, -15, 16), source.hscroll, max = 32767)
src._bary = W.Scrollbar((-16, 15, 16, -15), source.vscroll, max = 32767)
src.source = source
src.frame = W.Frame((0, 0, -15, -15))
bottom.tracingmonitor = TracingMonitor((0, 23, 6, 6))
bottom.state = W.TextBox((12, 20, 0, 16), self.reason)
bottom.srctitle = W.TextBox((12, 36, 0, 14))
bottom.buttons = buttons = W.Group((12, 0, 0, 16))
buttons.runbutton = W.Button((0, 0, 50, 16), "Run", self.do_run)
buttons.stopbutton = W.Button((58, 0, 50, 16), "Stop", self.do_stop)
buttons.killbutton = W.Button((116, 0, 50, 16), "Kill", self.do_kill)
buttons.line = W.VerticalLine((173, 0, 0, 0))
buttons.stepbutton = W.Button((181, 0, 50, 16), "Step", self.do_step)
buttons.stepinbutton = W.Button((239, 0, 50, 16), "Step in", self.do_stepin)
buttons.stepoutbutton = W.Button((297, 0, 50, 16), "Step out", self.do_stepout)
w.bind('cmdr', buttons.runbutton.push)
w.bind('cmd.', buttons.stopbutton.push)
w.bind('cmdk', buttons.killbutton.push)
w.bind('cmds', buttons.stepbutton.push)
w.bind('cmdt', buttons.stepinbutton.push)
w.bind('cmdu', buttons.stepoutbutton.push)
w.bind('<close>', self.close)
w.open()
w.xxx___select(w.panes.bottom.src.source)
def makeoptionsmenu(self):
options = [('Clear breakpoints', self.w.panes.bottom.src.source.clearbreakpoints),
('Clear all breakpoints', self.clear_all_breaks),
('Edit breakpointsÉ', self.edit_breaks), '-',
(self.tracemagic and
'Disable __magic__ tracing' or 'Enable __magic__ tracing', self.togglemagic)]
self.w.panes.bottom.src.optionsmenu.set(options)
def edit_breaks(self):
if self.breaksviewer:
self.breaksviewer.select()
else:
self.breaksviewer = BreakpointsViewer(self)
def togglemagic(self):
self.tracemagic = not self.tracemagic
def setstate(self, state):
self.w.panes.bottom.tracingmonitor.reset()
self.w.panes.bottom.state.set(self.reason)
buttons = self.w.panes.bottom.buttons
if state == 'stopped':
buttons.runbutton.enable(1)
buttons.stopbutton.enable(0)
buttons.killbutton.enable(1)
buttons.stepbutton.enable(1)
buttons.stepinbutton.enable(1)
buttons.stepoutbutton.enable(1)
elif state == 'running':
buttons.runbutton.enable(0)
buttons.stopbutton.enable(1)
buttons.killbutton.enable(1)
buttons.stepbutton.enable(0)
buttons.stepinbutton.enable(0)
buttons.stepoutbutton.enable(0)
elif state == 'idle':
buttons.runbutton.enable(0)
buttons.stopbutton.enable(0)
buttons.killbutton.enable(0)
buttons.stepbutton.enable(0)
buttons.stepinbutton.enable(0)
buttons.stepoutbutton.enable(0)
elif state == 'dead':
buttons.runbutton.enable(0)
buttons.stopbutton.enable(0)
buttons.killbutton.enable(1)
buttons.stepbutton.enable(0)
buttons.stepinbutton.enable(0)
buttons.stepoutbutton.enable(0)
else:
print 'unknown state:', state
def resetwidgets(self):
self.reason = ''
self.w.panes.bottom.srctitle.set('')
self.w.panes.bottom.src.source.set('')
self.w.panes.browserpanes.stacklist.stack.set([])
self.w.panes.browserpanes.locals.browser.set({})
self.w.panes.browserpanes.globals.browser.set({})
self.setstate('idle')
# W callbacks
def close(self):
self.set_quit()
self.exit_mainloop()
self.closed = 1
self.unregister_editor(self.w.panes.bottom.src.source,
self.w.panes.bottom.src.source.file)
self.horpanes = self.w.panes.getpanesizes()
self.verpanes = self.w.panes.browserpanes.getpanesizes()
self.bounds = self.w.getbounds()
prefs = W.getapplication().getprefs()
prefs.debugger.breaks = self.breaks
prefs.debugger.windowsettings = self.bounds, self.horpanes, self.verpanes
prefs.debugger.tracemagic = self.tracemagic
prefs.save()
# stack list callback
def do_stack(self, isdbl):
sel = self.w.panes.browserpanes.stacklist.stack.getselection()
if isdbl:
if sel:
frame, lineno = self.stack[sel[0] + 1]
filename = frame.f_code.co_filename
editor = self.w._parentwindow.parent.openscript(filename, lineno)
if self.breaks.has_key(filename):
editor.showbreakpoints(1)
else:
if sel and sel <> self.laststacksel:
self.showframe(sel[0] + 1)
self.laststacksel = sel
def geteditor(self, filename):
if filename[:1] == '<' and filename[-1:] == '>':
editor = W.getapplication().getscript(filename[1:-1])
else:
editor = W.getapplication().getscript(filename)
return editor
# button callbacks
def do_run(self):
self.running()
self.set_continue()
self.exit_mainloop()
def do_stop(self):
self.set_step()
def do_kill(self):
self.set_quit()
self.exit_mainloop()
self.resetwidgets()
def do_step(self):
self.running()
self.set_next(self.curframe)
self.exit_mainloop()
def do_stepin(self):
self.running()
self.set_step()
self.exit_mainloop()
def do_stepout(self):
self.running()
self.set_return(self.curframe)
self.exit_mainloop()
def running(self):
W.SetCursor('watch')
self.reason = 'RunningÉ'
self.setstate('running')
#self.w.panes.bottom.src.source.set('')
#self.w.panes.browserpanes.stacklist.stack.set([])
#self.w.panes.browserpanes.locals.browser.set({})
#self.w.panes.browserpanes.globals.browser.set({})
def exit_mainloop(self):
self.w.parent.debugger_quitting = 1
#
def showframe(self, stackindex):
(frame, lineno) = self.stack[stackindex]
W.SetCursor('watch')
filename = frame.f_code.co_filename
if filename <> self.file:
editor = self.geteditor(filename)
if editor:
self.w.panes.bottom.src.source.set(editor.get(), filename)
else:
try:
f = open(filename, 'rb')
data = f.read()
f.close()
except IOError:
if filename[-3:] == '.py':
import imp
modname = os.path.basename(filename)[:-3]
try:
f, filename, (suff, mode, dummy) = imp.find_module(modname)
except ImportError:
self.w.panes.bottom.src.source.set('canÕt find file')
else:
if f:
f.close()
if f and suff == '.py':
f = open(filename, 'rb')
data = f.read()
f.close()
self.w.panes.bottom.src.source.set(data, filename)
else:
self.w.panes.bottom.src.source.set('canÕt find file')
else:
self.w.panes.bottom.src.source.set('canÕt find file')
else:
self.w.panes.bottom.src.source.set(data, filename)
self.file = filename
self.w.panes.bottom.srctitle.set('Source: ' + filename + ((lineno > 0) and (' (line %d)' % lineno) or ' '))
self.goto_line(lineno)
self.lineno = lineno
self.showvars((frame, lineno))
def showvars(self, (frame, lineno)):
if frame.f_locals is not frame.f_globals:
locals = frame.f_locals
else:
locals = {'Same as Globals':''}
filteredlocals = {}
for key, value in locals.items():
# empty key is magic for Python 1.4; '.' is magic for 1.5...
if not key or key[0] <> '.':
filteredlocals[key] = value
self.w.panes.browserpanes.locals.browser.set(filteredlocals)
self.w.panes.browserpanes.globals.browser.set(frame.f_globals)
def showstack(self, stackindex):
stack = []
for frame, lineno in self.stack[1:]:
filename = frame.f_code.co_filename
try:
filename = _filenames[filename]
except KeyError:
if filename[:1] + filename[-1:] <> '<>':
filename = os.path.basename(filename)
_filenames[frame.f_code.co_filename] = filename
funcname = frame.f_code.co_name
if funcname == '?':
funcname = '<toplevel>'
stack.append(filename + ': ' + funcname)
if stack <> self.laststack:
self.w.panes.browserpanes.stacklist.stack.set(stack)
self.laststack = stack
sel = [stackindex - 1]
self.w.panes.browserpanes.stacklist.stack.setselection(sel)
self.laststacksel = sel
def goto_line(self, lineno):
if lineno > 0:
self.w.panes.bottom.src.source.selectline(lineno - 1)
else:
self.w.panes.bottom.src.source.setselection(0, 0)
# bdb entry points
# def user_call(self, frame, argument_list):
# self.reason = 'Calling'
# self.interaction(frame, None)
def user_line(self, frame):
# This function is called when we stop or break at this line
self.reason = 'Stopped'
self.interaction(frame, None)
def user_return(self, frame, return_value):
# This function is called when a return trap is set here
fname = frame.f_code.co_name
if fname <> '?':
self.reason = 'Returning from %s()' % frame.f_code.co_name
frame.f_locals['__return__'] = return_value
elif frame.f_back is self.botframe:
self.reason = 'Done'
else:
self.reason = 'Returning'
self.interaction(frame, None, 1)
def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
# This function is called when we stop or break at this line
self.reason = self.formatexception(exc_type, exc_value)
self.interaction(frame, exc_traceback)
def formatexception(self, exc_type, exc_value):
if exc_type == SyntaxError:
try:
value, (filename, lineno, charno, line) = exc_value
except:
pass
else:
return str(exc_type) + ': ' + str(value)
if type(exc_type) == types.ClassType:
nice = exc_type.__name__
else:
nice = str(exc_type)
value = str(exc_value)
if exc_value and value:
nice = nice + ": " + value
return nice
def forget(self):
self.stack = []
self.curindex = 0
self.curframe = None
def setup(self, f, t, isreturning = 0):
self.forget()
self.stack, self.curindex = self.get_stack(f, t)
self.curframe = self.stack[self.curindex - isreturning][0]
def interaction(self, frame, traceback, isreturning = 0):
saveport = Qd.GetPort()
self.w.select()
try:
self.setup(frame, traceback, isreturning)
self.setstate('stopped')
stackindex = self.curindex
if isreturning:
if frame.f_back is not self.botframe:
stackindex = stackindex - 1
self.showstack(stackindex)
self.showframe(stackindex)
self.w.parent.debugger_mainloop()
self.forget()
finally:
Qd.SetPort(saveport)
# bdb customization
def trace_dispatch(self, frame, event, arg, TickCount = Evt.TickCount):
if TickCount() - self.tracingmonitortime > 15:
self.tracingmonitortime = TickCount()
self.w.panes.bottom.tracingmonitor.toggle()
try:
try:
MacOS.EnableAppswitch(0)
if self.quitting:
# returning None is not enough, a former BdbQuit exception
# might have been eaten by the print statement
raise bdb.BdbQuit
if event == 'line':
return self.dispatch_line(frame)
if event == 'call':
return self.dispatch_call(frame, arg)
if event == 'return':
return self.dispatch_return(frame, arg)
if event == 'exception':
return self.dispatch_exception(frame, arg)
print 'bdb.Bdb.dispatch: unknown debugging event:', `event`
return self.trace_dispatch
finally:
MacOS.EnableAppswitch(-1)
except KeyboardInterrupt:
self.set_step()
return self.trace_dispatch
except bdb.BdbQuit:
if self.continuewithoutdebugger:
self.clear_tracefuncs()
return
else:
raise bdb.BdbQuit
except:
print 'XXX Exception during debugger interaction.', \
self.formatexception(sys.exc_type, sys.exc_value)
import traceback
traceback.print_exc()
return self.trace_dispatch
def dispatch_call(self, frame, arg):
if not self.tracemagic and \
frame.f_code.co_name[:2] == '__' == frame.f_code.co_name[-2:] and \
frame.f_code.co_name <> '__init__':
return
if self.botframe is None:
# First call of dispatch since reset()
self.botframe = frame.f_back # xxx !!! added f_back
return self.trace_dispatch
if not (self.stop_here(frame) or self.break_anywhere(frame)):
# No need to trace this function
return # None
self.user_call(frame, arg)
if self.quitting:
raise bdb.BdbQuit
return self.trace_dispatch
def set_continue(self):
# Don't stop except at breakpoints or when finished
self.stopframe = self.botframe
self.returnframe = None
self.quitting = 0
# unlike in bdb/pdb, there's a chance that breakpoints change
# *while* a program (this program ;-) is running. It's actually quite likely.
# So we don't delete frame.f_trace until the bottom frame if there are no breakpoints.
def set_break(self, filename, lineno):
if not self.breaks.has_key(filename):
self.breaks[filename] = []
list = self.breaks[filename]
if lineno in list:
return 'There is already a breakpoint there!'
list.append(lineno)
list.sort() # I want to keep them neatly sorted; easier for drawing
if hasattr(bdb, "Breakpoint"):
# 1.5.2b1 specific
bp = bdb.Breakpoint(filename, lineno, 0, None)
self.update_breaks(filename)
def clear_break(self, filename, lineno):
bdb.Bdb.clear_break(self, filename, lineno)
self.update_breaks(filename)
def clear_all_file_breaks(self, filename):
bdb.Bdb.clear_all_file_breaks(self, filename)
self.update_breaks(filename)
def clear_all_breaks(self):
bdb.Bdb.clear_all_breaks(self)
for editors in self.editors.values():
for editor in editors:
editor.drawbreakpoints()
# special
def toggle_break(self, filename, lineno):
if self.get_break(filename, lineno):
self.clear_break(filename, lineno)
else:
self.set_break(filename, lineno)
def clear_breaks_above(self, filename, above):
if not self.breaks.has_key(filename):
return 'There are no breakpoints in that file!'
for lineno in self.breaks[filename][:]:
if lineno > above:
self.breaks[filename].remove(lineno)
if not self.breaks[filename]:
del self.breaks[filename]
# editor stuff
def update_breaks(self, filename):
if self.breaksviewer:
self.breaksviewer.update()
if self.editors.has_key(filename):
for editor in self.editors[filename]:
if editor._debugger: # XXX
editor.drawbreakpoints()
else:
print 'xxx dead editor!'
def update_allbreaks(self):
if self.breaksviewer:
self.breaksviewer.update()
for filename in self.breaks.keys():
if self.editors.has_key(filename):
for editor in self.editors[filename]:
if editor._debugger: # XXX
editor.drawbreakpoints()
else:
print 'xxx dead editor!'
def register_editor(self, editor, filename):
if not filename:
return
if not self.editors.has_key(filename):
self.editors[filename] = [editor]
elif editor not in self.editors[filename]:
self.editors[filename].append(editor)
def unregister_editor(self, editor, filename):
if not filename:
return
try:
self.editors[filename].remove(editor)
if not self.editors[filename]:
del self.editors[filename]
# if this was an untitled window, clear the breaks.
if filename[:1] == '<' and filename[-1:] == '>' and \
self.breaks.has_key(filename):
self.clear_all_file_breaks(filename)
except (KeyError, ValueError):
pass
class SourceViewer(W.PyEditor):
def __init__(self, *args, **kwargs):
apply(W.PyEditor.__init__, (self,) + args, kwargs)
self.bind('<click>', self.clickintercept)
def clickintercept(self, point, modifiers):
if self._parentwindow._currentwidget <> self and not self.pt_in_breaks(point):
self._parentwindow.xxx___select(self)
return 1
def _getviewrect(self):
l, t, r, b = self._bounds
if self._debugger:
return (l + 12, t + 2, r - 1, b - 2)
else:
return (l + 5, t + 2, r - 1, b - 2)
def select(self, onoff, isclick = 0):
if W.SelectableWidget.select(self, onoff):
return
self.SetPort()
#if onoff:
# self.ted.WEActivate()
#else:
# self.ted.WEDeactivate()
self.drawselframe(onoff)
def drawselframe(self, onoff):
pass
class BreakpointsViewer:
def __init__(self, debugger):
self.debugger = debugger
import Lists
self.w = W.Window((300, 250), 'Breakpoints', minsize = (200, 200))
self.w.panes = W.HorizontalPanes((8, 8, -8, -32), (0.3, 0.7))
self.w.panes.files = W.List(None, callback = self.filehit) #, flags = Lists.lOnlyOne)
self.w.panes.gr = W.Group(None)
self.w.panes.gr.breaks = W.List((0, 0, -130, 0), callback = self.linehit) #, flags = Lists.lOnlyOne)
self.w.panes.gr.openbutton = W.Button((-80, 4, 0, 16), 'ViewÉ', self.openbuttonhit)
self.w.panes.gr.deletebutton = W.Button((-80, 28, 0, 16), 'Delete', self.deletebuttonhit)
self.w.bind('<close>', self.close)
self.w.bind('backspace', self.w.panes.gr.deletebutton.push)
self.setup()
self.w.open()
self.w.panes.gr.openbutton.enable(0)
self.w.panes.gr.deletebutton.enable(0)
self.curfile = None
def deletebuttonhit(self):
if self.w._currentwidget == self.w.panes.files:
self.del_filename()
else:
self.del_number()
self.checkbuttons()
def del_number(self):
if self.curfile is None:
return
sel = self.w.panes.gr.breaks.getselectedobjects()
for lineno in sel:
self.debugger.clear_break(self.curfile, lineno)
def del_filename(self):
sel = self.w.panes.files.getselectedobjects()
for filename in sel:
self.debugger.clear_all_file_breaks(filename)
self.debugger.update_allbreaks()
def setup(self):
files = self.debugger.breaks.keys()
files.sort()
self.w.panes.files.set(files)
def close(self):
self.debugger.breaksviewer = None
self.debugger = None
def update(self):
sel = self.w.panes.files.getselectedobjects()
self.setup()
self.w.panes.files.setselectedobjects(sel)
sel = self.w.panes.files.getselection()
if len(sel) == 0 and self.curfile:
self.w.panes.files.setselectedobjects([self.curfile])
self.filehit(0)
def select(self):
self.w.select()
def selectfile(self, file):
self.w.panes.files.setselectedobjects([file])
self.filehit(0)
def openbuttonhit(self):
self.filehit(1)
def filehit(self, isdbl):
sel = self.w.panes.files.getselectedobjects()
if isdbl:
for filename in sel:
lineno = None
if filename == self.curfile:
linesel = self.w.panes.gr.breaks.getselectedobjects()
if linesel:
lineno = linesel[-1]
elif self.w.panes.gr.breaks:
lineno = self.w.panes.gr.breaks[0]
editor = self.w._parentwindow.parent.openscript(filename, lineno)
editor.showbreakpoints(1)
return
if len(sel) == 1:
file = sel[0]
filebreaks = self.debugger.breaks[file][:]
if self.curfile == file:
linesel = self.w.panes.gr.breaks.getselectedobjects()
self.w.panes.gr.breaks.set(filebreaks)
if self.curfile == file:
self.w.panes.gr.breaks.setselectedobjects(linesel)
self.curfile = file
else:
if len(sel) <> 0:
self.curfile = None
self.w.panes.gr.breaks.set([])
self.checkbuttons()
def linehit(self, isdbl):
if isdbl:
files = self.w.panes.files.getselectedobjects()
if len(files) <> 1:
return
filename = files[0]
linenos = self.w.panes.gr.breaks.getselectedobjects()
if not linenos:
return
lineno = linenos[-1]
editor = self.w._parentwindow.parent.openscript(filename, lineno)
editor.showbreakpoints(1)
self.checkbuttons()
def checkbuttons(self):
if self.w.panes.files.getselection():
self.w.panes.gr.openbutton.enable(1)
self.w._parentwindow.setdefaultbutton(self.w.panes.gr.openbutton)
if self.w._currentwidget == self.w.panes.files:
if self.w.panes.files.getselection():
self.w.panes.gr.deletebutton.enable(1)
else:
self.w.panes.gr.deletebutton.enable(0)
else:
if self.w.panes.gr.breaks.getselection():
self.w.panes.gr.deletebutton.enable(1)
else:
self.w.panes.gr.deletebutton.enable(0)
else:
self.w.panes.gr.openbutton.enable(0)
self.w.panes.gr.deletebutton.enable(0)
class TracingMonitor(W.Widget):
def __init__(self, *args, **kwargs):
apply(W.Widget.__init__, (self,) + args, kwargs)
self.state = 0
def toggle(self):
if hasattr(self, "_parentwindow") and self._parentwindow is not None:
self.state = self.state % 2 + 1
port = Qd.GetPort()
self.SetPort()
self.draw()
Qd.SetPort(port)
def reset(self):
if self._parentwindow:
self.state = 0
port = Qd.GetPort()
self.SetPort()
self.draw()
Qd.SetPort(port)
def draw(self, visRgn = None):
if self.state == 2:
Qd.PaintOval(self._bounds)
else:
Qd.EraseOval(self._bounds)
# convenience funcs
def postmortem(exc_type, exc_value, tb):
d = getdebugger()
d.postmortem(exc_type, exc_value, tb)
def start(bottomframe = None):
d = getdebugger()
d.start(bottomframe)
def startfromhere():
d = getdebugger()
try:
raise 'spam'
except:
frame = sys.exc_traceback.tb_frame.f_back
d.start(frame)
def startfrombottom():
d = getdebugger()
d.start(_getbottomframe(), 1)
def stop():
d = getdebugger()
d.stop()
def cont():
sys.settrace(None)
d = getdebugger()
d.set_continue_without_debugger()
def _getbottomframe():
try:
raise 'spam'
except:
pass
frame = sys.exc_traceback.tb_frame
while 1:
if frame.f_code.co_name == 'mainloop' or frame.f_back is None:
break
frame = frame.f_back
return frame
_debugger = None
def getdebugger():
if not __debug__:
raise W.AlertError, "CanÕt debug in ÒOptimize bytecodeÓ mode.\r(see ÒDefault startup optionsÓ in EditPythonPreferences)"
global _debugger
if _debugger is None:
_debugger = Debugger()
return _debugger

View File

@ -0,0 +1,290 @@
import aetools
import Standard_Suite
import Required_Suite
import WWW_Suite
import regex
import W
import macfs
import os
import MacPrefs
import MacOS
import string
if hasattr(WWW_Suite, "WWW_Suite"):
WWW = WWW_Suite.WWW_Suite
else:
WWW = WWW_Suite.WorldWideWeb_suite_2c__as_defined_in_Spyglass_spec_2e_
class WebBrowser(aetools.TalkTo,
Standard_Suite.Standard_Suite,
WWW):
def openfile(self, path, activate = 1):
if activate:
self.activate()
self.OpenURL("file:///" + string.join(string.split(path,':'), '/'))
app = W.getapplication()
#SIGNATURE='MSIE' # MS Explorer
SIGNATURE='MOSS' # Netscape
_titlepat = regex.compile('<title>\([^<]*\)</title>')
def sucktitle(path):
f = open(path)
text = f.read(1024) # assume the title is in the first 1024 bytes
f.close()
lowertext = string.lower(text)
if _titlepat.search(lowertext) > 0:
a, b = _titlepat.regs[1]
return text[a:b]
return path
def verifydocpath(docpath):
try:
tut = os.path.join(docpath, "tut")
lib = os.path.join(docpath, "lib")
ref = os.path.join(docpath, "ref")
for path in [tut, lib, ref]:
if not os.path.exists(path):
return 0
except:
return 0
return 1
class TwoLineList(W.List):
LDEF_ID = 468
def createlist(self):
import List
self._calcbounds()
self.SetPort()
rect = self._bounds
rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1
self._list = List.LNew(rect, (0, 0, 1, 0), (0, 28), self.LDEF_ID, self._parentwindow.wid,
0, 1, 0, 1)
self.set(self.items)
_resultscounter = 1
class Results:
def __init__(self, hits):
global _resultscounter
hits = map(lambda (path, hits): (sucktitle(path), path, hits), hits)
hits.sort()
self.hits = hits
nicehits = map(
lambda (title, path, hits):
title + '\r' + string.join(
map(lambda (c, p): "%s (%d)" % (p, c), hits), ', '), hits)
nicehits.sort()
self.w = W.Window((440, 300), "Search results %d" % _resultscounter, minsize = (200, 100))
self.w.results = TwoLineList((-1, -1, 1, -14), nicehits, self.listhit)
self.w.open()
self.w.bind('return', self.listhit)
self.w.bind('enter', self.listhit)
_resultscounter = _resultscounter + 1
self.browser = None
def listhit(self, isdbl = 1):
if isdbl:
for i in self.w.results.getselection():
if self.browser is None:
self.browser = WebBrowser(SIGNATURE, start = 1)
self.browser.openfile(self.hits[i][1])
class Status:
def __init__(self):
self.w = W.Dialog((440, 64), "SearchingÉ")
self.w.searching = W.TextBox((4, 4, -4, 16), "DevDev:PyPyDoc 1.5.1:ext:parseTupleAndKeywords.html")
self.w.hits = W.TextBox((4, 24, -4, 16), "Hits: 0")
self.w.canceltip = W.TextBox((4, 44, -4, 16), "Type cmd-period (.) to cancel.")
self.w.open()
def set(self, path, hits):
self.w.searching.set(path)
self.w.hits.set('Hits: ' + `hits`)
app.breathe()
def close(self):
self.w.close()
def match(text, patterns, all):
hits = []
hitsappend = hits.append
stringcount = string.count
for pat in patterns:
c = stringcount(text, pat)
if c > 0:
hitsappend((c, pat))
elif all:
hits[:] = []
break
hits.sort()
hits.reverse()
return hits
def dosearch(docpath, searchstring, settings):
(docpath, kind, case, word, tut, lib, ref, ext, api) = settings
books = [(tut, 'tut'), (lib, 'lib'), (ref, 'ref'), (ext, 'ext'), (api, 'api')]
if not case:
searchstring = string.lower(searchstring)
if kind == 1:
patterns = string.split(searchstring)
all = 1
elif kind == 2:
patterns = string.split(searchstring)
all = 0
else:
patterns = [searchstring]
all = 0 # not relevant
ospathjoin = os.path.join
stringlower = string.lower
status = Status()
statusset = status.set
_match = match
_open = open
hits = {}
try:
MacOS.EnableAppswitch(0)
try:
for do, name in books:
if not do:
continue
bookpath = ospathjoin(docpath, name)
if not os.path.exists(bookpath):
continue
files = os.listdir(bookpath)
for file in files:
fullpath = ospathjoin(bookpath, file)
if fullpath[-5:] <> '.html':
continue
statusset(fullpath, len(hits))
f = _open(fullpath)
text = f.read()
if not case:
text = stringlower(text)
f.close()
filehits = _match(text, patterns, all)
if filehits:
hits[fullpath] = filehits
finally:
MacOS.EnableAppswitch(-1)
status.close()
except KeyboardInterrupt:
pass
hits = hits.items()
hits.sort()
return hits
class PyDocSearch:
def __init__(self):
prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
try:
(docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine
except:
(docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine = \
("", 0, 0, 0, 1, 1, 0, 0, 0)
if docpath and not verifydocpath(docpath):
docpath = ""
self.w = W.Window((400, 200), "Search the Python Documentation")
self.w.searchtext = W.EditText((10, 10, -100, 20), callback = self.checkbuttons)
self.w.searchbutton = W.Button((-90, 12, 80, 16), "Search", self.search)
buttons = []
gutter = 10
width = 130
bookstart = width + 2 * gutter
self.w.phraseradio = W.RadioButton((10, 38, width, 16), "As a phrase", buttons)
self.w.allwordsradio = W.RadioButton((10, 58, width, 16), "All words", buttons)
self.w.anywordsradio = W.RadioButton((10, 78, width, 16), "Any word", buttons)
self.w.casesens = W.CheckBox((10, 98, width, 16), "Case sensitive")
self.w.wholewords = W.CheckBox((10, 118, width, 16), "Whole words")
self.w.tutorial = W.CheckBox((bookstart, 38, -10, 16), "Tutorial")
self.w.library = W.CheckBox((bookstart, 58, -10, 16), "Library reference")
self.w.langueref = W.CheckBox((bookstart, 78, -10, 16), "Lanuage reference manual")
self.w.extending = W.CheckBox((bookstart, 98, -10, 16), "Extending & embedding")
self.w.api = W.CheckBox((bookstart, 118, -10, 16), "C/C++ API")
self.w.setdocfolderbutton = W.Button((10, -30, 80, 16), "Set doc folder", self.setdocpath)
if docpath:
self.w.setdefaultbutton(self.w.searchbutton)
else:
self.w.setdefaultbutton(self.w.setdocfolderbutton)
self.docpath = docpath
if not docpath:
docpath = "(please select the Python html documentation folder)"
self.w.docfolder = W.TextBox((100, -28, -10, 16), docpath)
[self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio][kind].set(1)
self.w.casesens.set(case)
self.w.wholewords.set(word)
self.w.tutorial.set(tut)
self.w.library.set(lib)
self.w.langueref.set(ref)
self.w.extending.set(ext)
self.w.api.set(api)
self.w.open()
self.w.wholewords.enable(0)
self.w.bind('<close>', self.close)
self.w.searchbutton.enable(0)
def search(self):
hits = dosearch(self.docpath, self.w.searchtext.get(), self.getsettings())
if hits:
Results(hits)
elif hasattr(MacOS, 'SysBeep'):
MacOS.SysBeep(0)
#import PyBrowser
#PyBrowser.Browser(hits)
def setdocpath(self):
fss, ok = macfs.GetDirectory()
if ok:
docpath = fss.as_pathname()
if not verifydocpath(docpath):
W.Message("This does not seem to be a Python documentation folder...")
else:
self.docpath = docpath
self.w.docfolder.set(docpath)
self.w.setdefaultbutton(self.w.searchbutton)
def close(self):
prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
prefs.docsearchengine = self.getsettings()
def getsettings(self):
radiobuttons = [self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio]
for i in range(3):
if radiobuttons[i].get():
kind = i
break
docpath = self.docpath
case = self.w.casesens.get()
word = self.w.wholewords.get()
tut = self.w.tutorial.get()
lib = self.w.library.get()
ref = self.w.langueref.get()
ext = self.w.extending.get()
api = self.w.api.get()
return (docpath, kind, case, word, tut, lib, ref, ext, api)
def checkbuttons(self):
self.w.searchbutton.enable(not not self.w.searchtext.get())

1126
Mac/Tools/IDE/PyEdit.py Normal file

File diff suppressed because it is too large Load Diff

154
Mac/Tools/IDE/PyFontify.py Normal file
View File

@ -0,0 +1,154 @@
"""Module to analyze Python source code; for syntax coloring tools.
Interface:
tags = fontify(pytext, searchfrom, searchto)
The 'pytext' argument is a string containing Python source code.
The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext.
The returned value is a list of tuples, formatted like this:
[('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ]
The tuple contents are always like this:
(tag, startindex, endindex, sublist)
tag is one of 'keyword', 'string', 'comment' or 'identifier'
sublist is not used, hence always None.
"""
# Based on FontText.py by Mitchell S. Chapman,
# which was modified by Zachary Roadhouse,
# then un-Tk'd by Just van Rossum.
# Many thanks for regular expression debugging & authoring are due to:
# Tim (the-incredib-ly y'rs) Peters and Cristian Tismer
# So, who owns the copyright? ;-) How about this:
# Copyright 1996-1997:
# Mitchell S. Chapman,
# Zachary Roadhouse,
# Tim Peters,
# Just van Rossum
__version__ = "0.3.1"
import string, regex
# First a little helper, since I don't like to repeat things. (Tismer speaking)
import string
def replace(where, what, with):
return string.join(string.split(where, what), with)
# This list of keywords is taken from ref/node13.html of the
# Python 1.3 HTML documentation. ("access" is intentionally omitted.)
keywordsList = [
"assert",
"del", "from", "lambda", "return",
"and", "elif", "global", "not", "try",
"break", "else", "if", "or", "while",
"class", "except", "import", "pass",
"continue", "finally", "in", "print",
"def", "for", "is", "raise"]
# Build up a regular expression which will match anything
# interesting, including multi-line triple-quoted strings.
commentPat = "#.*"
pat = "q[^\q\n]*\(\\\\[\000-\377][^\q\n]*\)*q"
quotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"')
# Way to go, Tim!
pat = """
qqq
[^\\q]*
\(
\( \\\\[\000-\377]
\| q
\( \\\\[\000-\377]
\| [^\\q]
\| q
\( \\\\[\000-\377]
\| [^\\q]
\)
\)
\)
[^\\q]*
\)*
qqq
"""
pat = string.join(string.split(pat), '') # get rid of whitespace
tripleQuotePat = replace(pat, "q", "'") + "\|" + replace(pat, 'q', '"')
# Build up a regular expression which matches all and only
# Python keywords. This will let us skip the uninteresting
# identifier references.
# nonKeyPat identifies characters which may legally precede
# a keyword pattern.
nonKeyPat = "\(^\|[^a-zA-Z0-9_.\"']\)"
keyPat = nonKeyPat + "\("
for keyword in keywordsList:
keyPat = keyPat + keyword + "\|"
keyPat = keyPat[:-2] + "\)" + nonKeyPat
matchPat = keyPat + "\|" + commentPat + "\|" + tripleQuotePat + "\|" + quotePat
matchRE = regex.compile(matchPat)
idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*" # Ident w. leading whitespace.
idRE = regex.compile(idKeyPat)
def fontify(pytext, searchfrom = 0, searchto = None):
if searchto is None:
searchto = len(pytext)
# Cache a few attributes for quicker reference.
search = matchRE.search
group = matchRE.group
idSearch = idRE.search
idGroup = idRE.group
tags = []
tags_append = tags.append
commentTag = 'comment'
stringTag = 'string'
keywordTag = 'keyword'
identifierTag = 'identifier'
start = 0
end = searchfrom
while 1:
start = search(pytext, end)
if start < 0 or start >= searchto:
break # EXIT LOOP
match = group(0)
end = start + len(match)
c = match[0]
if c not in "#'\"":
# Must have matched a keyword.
if start <> searchfrom:
# there's still a redundant char before and after it, strip!
match = match[1:-1]
start = start + 1
else:
# this is the first keyword in the text.
# Only a space at the end.
match = match[:-1]
end = end - 1
tags_append((keywordTag, start, end, None))
# If this was a defining keyword, look ahead to the
# following identifier.
if match in ["def", "class"]:
start = idSearch(pytext, end)
if start == end:
match = idGroup(0)
end = start + len(match)
tags_append((identifierTag, start, end, None))
elif c == "#":
tags_append((commentTag, start, end, None))
else:
tags_append((stringTag, start, end, None))
return tags
def test(path):
f = open(path)
text = f.read()
f.close()
tags = fontify(text)
for tag, start, end, sublist in tags:
print tag, `text[start:end]`

View File

@ -0,0 +1,115 @@
import string
import sys
import traceback
try:
sys.ps1
except AttributeError:
sys.ps1 = ">>> "
try:
sys.ps2
except AttributeError:
sys.ps2 = "... "
def print_exc(limit=None, file=None):
if not file:
file = sys.stderr
# we're going to skip the outermost traceback object, we don't
# want people to see the line which excecuted their code.
tb = sys.exc_traceback
if tb:
tb = tb.tb_next
try:
sys.last_type = sys.exc_type
sys.last_value = sys.exc_value
sys.last_traceback = tb
traceback.print_exception(sys.last_type, sys.last_value,
sys.last_traceback, limit, file)
except:
print '--- hola! ---'
traceback.print_exception(sys.exc_type, sys.exc_value,
sys.exc_traceback, limit, file)
class PyInteractive:
def __init__(self):
self._pybuf = ""
def executeline(self, stuff, out = None, env = None):
if env is None:
import __main__
env = __main__.__dict__
if out:
saveerr, saveout = sys.stderr, sys.stdout
sys.stderr = sys.stdout = out
try:
if self._pybuf:
self._pybuf = self._pybuf + '\n' + stuff
else:
self._pybuf = stuff
# Compile three times: as is, with \n, and with \n\n appended.
# If it compiles as is, it's complete. If it compiles with
# one \n appended, we expect more. If it doesn't compile
# either way, we compare the error we get when compiling with
# \n or \n\n appended. If the errors are the same, the code
# is broken. But if the errors are different, we expect more.
# Not intuitive; not even guaranteed to hold in future
# releases; but this matches the compiler's behavior in Python
# 1.4 and 1.5.
err = err1 = err2 = None
code = code1 = code2 = None
# quickly get out of here when the line is 'empty' or is a comment
stripped = string.strip(self._pybuf)
if not stripped or stripped[0] == '#':
self._pybuf = ''
sys.stdout.write(sys.ps1)
sys.stdout.flush()
return
try:
code = compile(self._pybuf, "<input>", "single")
except SyntaxError, err:
pass
except:
# OverflowError. More?
print_exc()
self._pybuf = ""
sys.stdout.write(sys.ps1)
sys.stdout.flush()
return
try:
code1 = compile(self._pybuf + "\n", "<input>", "single")
except SyntaxError, err1:
pass
try:
code2 = compile(self._pybuf + "\n\n", "<input>", "single")
except SyntaxError, err2:
pass
if code:
try:
exec code in env
except:
print_exc()
self._pybuf = ""
elif code1:
pass
elif err1 == err2 or (not stuff and self._pybuf):
print_exc()
self._pybuf = ""
if self._pybuf:
sys.stdout.write(sys.ps2)
sys.stdout.flush()
else:
sys.stdout.write(sys.ps1)
sys.stdout.flush()
finally:
if out:
sys.stderr, sys.stdout = saveerr, saveout

View File

@ -0,0 +1,33 @@
# copyright 1996-1999 Just van Rossum, Letterror. just@letterror.com
# keep this (__main__) as clean as possible, since we are using
# it like the "normal" interpreter.
__version__ = '1.0b2'
def init():
import MacOS
MacOS.EnableAppswitch(-1)
import Qd, QuickDraw
Qd.SetCursor(Qd.GetCursor(QuickDraw.watchCursor).data)
import Res
try:
Res.GetResource('DITL', 468)
except Res.Error:
# we're not an applet
Res.OpenResFile('Widgets.rsrc')
Res.OpenResFile('PythonIDE.rsrc')
else:
# we're an applet
import sys
if sys.argv[0] not in sys.path:
sys.path[2:2] = [sys.argv[0]]
init()
del init
import PythonIDEMain

Binary file not shown.

View File

@ -0,0 +1,237 @@
# copyright 1997-1998 Just van Rossum, Letterror. just@letterror.com
import Splash
import FrameWork
import Win
import Wapplication
import W
import os
import macfs
class PythonIDE(Wapplication.Application):
def __init__(self):
self.preffilepath = ":Python:PythonIDE preferences"
Wapplication.Application.__init__(self, 'Pyth')
import AE, AppleEvents
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication,
self.ignoreevent)
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments,
self.ignoreevent)
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments,
self.opendocsevent)
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication,
self.quitevent)
import PyConsole, PyEdit
Splash.wait()
Splash.uninstall_importhook()
PyConsole.installoutput()
PyConsole.installconsole()
import sys
for path in sys.argv[1:]:
self.opendoc(path)
self.mainloop()
def makeusermenus(self):
m = Wapplication.Menu(self.menubar, "File")
newitem = FrameWork.MenuItem(m, "New", "N", 'new')
openitem = FrameWork.MenuItem(m, "OpenÉ", "O", 'open')
FrameWork.Separator(m)
closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
saveasitem = FrameWork.MenuItem(m, "Save asÉ", None, 'save_as')
FrameWork.Separator(m)
saveasappletitem = FrameWork.MenuItem(m, "Save as AppletÉ", None, 'save_as_applet')
FrameWork.Separator(m)
quititem = FrameWork.MenuItem(m, "Quit", "Q", 'quit')
m = Wapplication.Menu(self.menubar, "Edit")
undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
FrameWork.Separator(m)
cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
FrameWork.MenuItem(m, "Clear", None, "clear")
FrameWork.Separator(m)
selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
sellineitem = FrameWork.MenuItem(m, "Select line", "L", "selectline")
FrameWork.Separator(m)
finditem = FrameWork.MenuItem(m, "FindÉ", "F", "find")
findagainitem = FrameWork.MenuItem(m, "Find again", 'G', "findnext")
enterselitem = FrameWork.MenuItem(m, "Enter search string", "E", "entersearchstring")
replaceitem = FrameWork.MenuItem(m, "Replace", None, "replace")
replacefinditem = FrameWork.MenuItem(m, "Replace & find again", 'T', "replacefind")
FrameWork.Separator(m)
shiftleftitem = FrameWork.MenuItem(m, "Shift left", "[", "shiftleft")
shiftrightitem = FrameWork.MenuItem(m, "Shift right", "]", "shiftright")
m = Wapplication.Menu(self.menubar, "Python")
runitem = FrameWork.MenuItem(m, "Run window", "R", 'run')
runselitem = FrameWork.MenuItem(m, "Run selection", None, 'runselection')
FrameWork.Separator(m)
moditem = FrameWork.MenuItem(m, "Module browserÉ", "M", self.domenu_modulebrowser)
FrameWork.Separator(m)
mm = FrameWork.SubMenu(m, "Preferences")
FrameWork.MenuItem(mm, "Set Scripts folderÉ", None, self.do_setscriptsfolder)
FrameWork.MenuItem(mm, "Editor default settingsÉ", None, self.do_editorprefs)
self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
self.makeopenwindowsmenu()
self._menustocheck = [closeitem, saveitem, saveasitem, saveasappletitem,
undoitem, cutitem, copyitem, pasteitem,
selallitem, sellineitem,
finditem, findagainitem, enterselitem, replaceitem, replacefinditem,
shiftleftitem, shiftrightitem,
runitem, runselitem]
prefs = self.getprefs()
try:
fss, fss_changed = macfs.RawAlias(prefs.scriptsfolder).Resolve()
except:
path = os.path.join(os.getcwd(), 'Scripts')
if not os.path.exists(path):
os.mkdir(path)
fss = macfs.FSSpec(path)
self.scriptsfolder = fss.NewAlias()
self.scriptsfoldermodtime = fss.GetDates()[1]
else:
self.scriptsfolder = fss.NewAlias()
self.scriptsfoldermodtime = fss.GetDates()[1]
prefs.scriptsfolder = self.scriptsfolder.data
self._scripts = {}
self.scriptsmenu = None
self.makescriptsmenu()
def quitevent(self, theAppleEvent, theReply):
import AE
AE.AEInteractWithUser(50000000)
self._quit()
def suspendresume(self, onoff):
if onoff:
fss, fss_changed = self.scriptsfolder.Resolve()
modtime = fss.GetDates()[1]
if self.scriptsfoldermodtime <> modtime or fss_changed:
self.scriptsfoldermodtime = modtime
W.SetCursor('watch')
self.makescriptsmenu()
def ignoreevent(self, theAppleEvent, theReply):
pass
def opendocsevent(self, theAppleEvent, theReply):
W.SetCursor('watch')
import aetools
parameters, args = aetools.unpackevent(theAppleEvent)
docs = parameters['----']
if type(docs) <> type([]):
docs = [docs]
for doc in docs:
fss, a = doc.Resolve()
path = fss.as_pathname()
self.opendoc(path)
def opendoc(self, path):
fcreator, ftype = macfs.FSSpec(path).GetCreatorType()
if ftype == 'TEXT':
self.openscript(path)
else:
W.Message("CanÕt open file of type '%s'." % ftype)
def getabouttext(self):
return "About Python IDEÉ"
def do_about(self, id, item, window, event):
Splash.about()
def do_setscriptsfolder(self, *args):
fss, ok = macfs.GetDirectory("Select Scripts Folder")
if ok:
prefs = self.getprefs()
alis = fss.NewAlias()
prefs.scriptsfolder = alis.data
self.scriptsfolder = alis
self.makescriptsmenu()
prefs.save()
def domenu_modulebrowser(self, *args):
W.SetCursor('watch')
import ModuleBrowser
ModuleBrowser.ModuleBrowser()
def domenu_open(self, *args):
fss, ok = macfs.StandardGetFile("TEXT")
if ok:
self.openscript(fss.as_pathname())
def domenu_new(self, *args):
W.SetCursor('watch')
import PyEdit
return PyEdit.Editor()
def makescriptsmenu(self):
W.SetCursor('watch')
if self._scripts:
for id, item in self._scripts.keys():
if self.menubar.menus.has_key(id):
m = self.menubar.menus[id]
m.delete()
self._scripts = {}
if self.scriptsmenu:
if hasattr(self.scriptsmenu, 'id') and self.menubar.menus.has_key(self.scriptsmenu.id):
self.scriptsmenu.delete()
self.scriptsmenu = FrameWork.Menu(self.menubar, "Scripts")
#FrameWork.MenuItem(self.scriptsmenu, "New script", None, self.domenu_new)
#self.scriptsmenu.addseparator()
fss, fss_changed = self.scriptsfolder.Resolve()
self.scriptswalk(fss.as_pathname(), self.scriptsmenu)
def makeopenwindowsmenu(self):
for i in range(len(self.openwindowsmenu.items)):
self.openwindowsmenu.menu.DeleteMenuItem(1)
self.openwindowsmenu.items = []
windows = []
self._openwindows = {}
for window in self._windows.keys():
title = window.GetWTitle()
if not title:
title = "<no title>"
windows.append(title, window)
windows.sort()
for title, window in windows:
if title == "Python Interactive": # ugly but useful hack by Joe Strout
shortcut = '0'
else:
shortcut = None
item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
self._openwindows[item.item] = window
self._openwindowscheckmark = 0
self.checkopenwindowsmenu()
def domenu_openwindows(self, id, item, window, event):
w = self._openwindows[item]
w.ShowWindow()
w.SelectWindow()
def domenu_quit(self):
self._quit()
def domenu_save(self, *args):
print "Save"
def _quit(self):
import PyConsole, PyEdit
PyConsole.console.writeprefs()
PyConsole.output.writeprefs()
PyEdit.searchengine.writeprefs()
for window in self._windows.values():
rv = window.close()
if rv and rv > 0:
return
self.quitting = 1
PythonIDE()

162
Mac/Tools/IDE/Splash.py Normal file
View File

@ -0,0 +1,162 @@
import Dlg
import Res
splash = Dlg.GetNewDialog(468, -1)
splash.DrawDialog()
import Qd, TE, Fm, sys
_real__import__ = None
def install_importhook():
global _real__import__
import __builtin__
if _real__import__ is None:
_real__import__ = __builtin__.__import__
__builtin__.__import__ = my__import__
def uninstall_importhook():
global _real__import__
if _real__import__ is not None:
import __builtin__
__builtin__.__import__ = _real__import__
_real__import__ = None
_progress = 0
def importing(module):
global _progress
Qd.SetPort(splash)
fontID = Fm.GetFNum("Python-Sans")
if not fontID:
fontID = geneva
Qd.TextFont(fontID)
Qd.TextSize(9)
rect = (35, 260, 365, 276)
if module:
TE.TETextBox('Importing: ' + module, rect, 0)
if not _progress:
Qd.FrameRect((35, 276, 365, 284))
pos = min(36 + 330 * _progress / 44, 364)
Qd.PaintRect((36, 277, pos, 283))
_progress = _progress + 1
else:
Qd.EraseRect(rect)
Qd.PaintRect((36, 277, pos, 283))
def my__import__(name, globals=None, locals=None, fromlist=None):
try:
return sys.modules[name]
except KeyError:
try:
importing(name)
except:
try:
rv = _real__import__(name)
finally:
uninstall_importhook()
return rv
return _real__import__(name)
install_importhook()
kHighLevelEvent = 23
import Win
from Fonts import *
from QuickDraw import *
from TextEdit import *
import string
import sys
_keepsplashscreenopen = 0
abouttext1 = """The Python Integrated Developement Environment for the Macintoshª
Version: %s
Copyright 1997-98 Just van Rossum, Letterror. <just@letterror.com>
Python %s
%s
Written by Guido van Rossum with Jack Jansen (and others)
See: <http://www.python.org/> for information and documentation."""
flauwekul = [ 'Goodday, Bruce.',
'WhatÕs new?',
'Nudge, nudge, say no more!',
'No, no sir, itÕs not dead. ItÕs resting.',
'Albatros!',
'ItÕs . . .',
'Is your name not Bruce, then?',
"""But Mr F.G. Superman has a secret identity . . .
when trouble strikes at any time . . .
at any place . . . he is ready to become . . .
Bicycle Repair Man!"""
]
def nl2return(text):
return string.join(string.split(text, '\n'), '\r')
def UpdateSplash(drawdialog = 0, what = 0):
if drawdialog:
splash.DrawDialog()
drawtext(what)
Win.ValidRect(splash.GetWindowPort().portRect)
def drawtext(what = 0):
Qd.SetPort(splash)
fontID = Fm.GetFNum("Python-Sans")
if not fontID:
fontID = geneva
Qd.TextFont(fontID)
Qd.TextSize(9)
rect = (10, 125, 390, 260)
if not what:
import __main__
abouttxt = nl2return(abouttext1 \
% (__main__.__version__, sys.version, sys.copyright))
else:
import random
abouttxt = nl2return(random.choice(flauwekul))
TE.TETextBox(abouttxt, rect, teJustCenter)
UpdateSplash(1)
def wait():
import Evt
from Events import *
global splash
try:
splash
except NameError:
return
Qd.InitCursor()
time = Evt.TickCount()
whattext = 0
while _keepsplashscreenopen:
ok, event = Evt.EventAvail(highLevelEventMask)
if ok:
# got apple event, back to mainloop
break
ok, event = Evt.EventAvail(mDownMask | keyDownMask | updateMask)
if ok:
ok, event = Evt.WaitNextEvent(mDownMask | keyDownMask | updateMask, 30)
if ok:
(what, message, when, where, modifiers) = event
if what == updateEvt:
if Win.WhichWindow(message) == splash:
UpdateSplash(1, whattext)
else:
break
if Evt.TickCount() - time > 360:
whattext = not whattext
drawtext(whattext)
time = Evt.TickCount()
del splash
#Res.CloseResFile(splashresfile)
def about():
global splash, splashresfile, _keepsplashscreenopen
_keepsplashscreenopen = 1
splash = Dlg.GetNewDialog(468, -1)
splash.DrawDialog()
wait()

34
Mac/Tools/IDE/W.py Normal file
View File

@ -0,0 +1,34 @@
"""Widgets for the Macintosh. Built on top of FrameWork"""
__version__ = "0.3"
from Wbase import *
from Wcontrols import *
from Wtext import *
from Wlists import *
from Wwindows import *
from Wmenus import *
_application = None
_signature = None
AlertError = 'AlertError'
def setapplication(app, sig):
global _application, _signature
_application = app
_signature = sig
def getapplication():
if _application is None:
raise WidgetsError, 'W not properly initialized: unknown Application'
return _application
def Message(text):
import EasyDialogs, Qd, string
Qd.InitCursor()
text = string.replace(text, "\n", "\r")
if not text:
text = '<Alert text not specified>'
EasyDialogs.Message(text)

View File

@ -0,0 +1,411 @@
import FrameWork
import Win
import Qd
import Evt
import MacOS
import Events
import traceback
from types import *
import Menu; MenuToolbox = Menu; del Menu
class Application(FrameWork.Application):
def __init__(self, signature='Pyth'):
import W
W.setapplication(self, signature)
FrameWork.Application.__init__(self)
self._suspended = 0
self.quitting = 0
self.debugger_quitting = 1
self.DebuggerQuit = 'DebuggerQuitDummyException'
self._idlefuncs = []
# map certain F key codes to equivalent command-letter combos (JJS)
self.fkeymaps = {122:"z", 120:"x", 99:"c", 118:"v"}
def mainloop(self, mask=FrameWork.everyEvent, wait=0):
import W
self.quitting = 0
saveyield = MacOS.EnableAppswitch(-1)
try:
while not self.quitting:
try:
self.do1event(mask, wait)
except W.AlertError, detail:
MacOS.EnableAppswitch(-1)
W.Message(detail)
except self.DebuggerQuit:
MacOS.EnableAppswitch(-1)
except:
MacOS.EnableAppswitch(-1)
import PyEdit
PyEdit.tracebackwindow.traceback()
finally:
MacOS.EnableAppswitch(1)
def debugger_mainloop(self, mask=FrameWork.everyEvent, wait=0):
import W
self.debugger_quitting = 0
saveyield = MacOS.EnableAppswitch(-1)
try:
while not self.quitting and not self.debugger_quitting:
try:
self.do1event(mask, wait)
except W.AlertError, detail:
W.Message(detail)
except:
import PyEdit
PyEdit.tracebackwindow.traceback()
finally:
MacOS.EnableAppswitch(saveyield)
def breathe(self, wait=1):
import W
ok, event = Evt.WaitNextEvent(FrameWork.updateMask |
FrameWork.mDownMask | FrameWork.osMask |
FrameWork.activMask,
wait)
if ok:
(what, message, when, where, modifiers) = event
#print FrameWork.eventname[what]
if FrameWork.eventname[what] == 'mouseDown':
partcode, wid = Win.FindWindow(where)
if FrameWork.partname[partcode] <> 'inDesk':
return
else:
W.SetCursor('watch')
self.dispatch(event)
def refreshwindows(self, wait=1):
import W
while 1:
ok, event = Evt.WaitNextEvent(FrameWork.updateMask, wait)
if not ok:
break
self.dispatch(event)
def addidlefunc(self, func):
self._idlefuncs.append(func)
def removeidlefunc(self, func):
self._idlefuncs.remove(func)
def idle(self, event):
if not self._suspended:
if not self.do_frontWindowMethod("idle", event):
Qd.InitCursor()
if self._idlefuncs:
for func in self._idlefuncs:
try:
func()
except:
import sys
sys.stderr.write("exception in idle function %s; killed:\n" % `func`)
traceback.print_exc()
self._idlefuncs.remove(func)
break
def do_frontWindowMethod(self, attr, *args):
wid = Win.FrontWindow()
if wid and self._windows.has_key(wid):
window = self._windows[wid]
if hasattr(window, attr):
handler = getattr(window, attr)
apply(handler, args)
return 1
def appendwindow(self, wid, window):
self._windows[wid] = window
self.makeopenwindowsmenu()
def removewindow(self, wid):
del self._windows[wid]
self.makeopenwindowsmenu()
def do_key(self, event):
(what, message, when, where, modifiers) = event
ch = chr(message & FrameWork.charCodeMask)
rest = message & ~FrameWork.charCodeMask
keycode = (message & FrameWork.keyCodeMask) >> 8
if keycode in self.fkeymaps.keys(): # JJS
ch = self.fkeymaps[keycode]
modifiers = modifiers | FrameWork.cmdKey
wid = Win.FrontWindow()
if modifiers & FrameWork.cmdKey and not modifiers & FrameWork.shiftKey:
if wid and self._windows.has_key(wid):
self.checkmenus(self._windows[wid])
else:
self.checkmenus(None)
event = (what, ord(ch) | rest, when, where, modifiers)
result = MenuToolbox.MenuKey(ord(ch))
id = (result>>16) & 0xffff # Hi word
item = result & 0xffff # Lo word
if id:
self.do_rawmenu(id, item, None, event)
return # here! we had a menukey!
#else:
# print "XXX Command-" +`ch`
# See whether the front window wants it
if wid and self._windows.has_key(wid):
window = self._windows[wid]
try:
do_char = window.do_char
except AttributeError:
do_char = self.do_char
do_char(ch, event)
# else it wasn't for us, sigh...
def do_inMenuBar(self, partcode, window, event):
Qd.InitCursor()
(what, message, when, where, modifiers) = event
self.checkopenwindowsmenu()
wid = Win.FrontWindow()
if wid and self._windows.has_key(wid):
self.checkmenus(self._windows[wid])
else:
self.checkmenus(None)
result = MenuToolbox.MenuSelect(where)
id = (result>>16) & 0xffff # Hi word
item = result & 0xffff # Lo word
self.do_rawmenu(id, item, window, event)
def do_updateEvt(self, event):
(what, message, when, where, modifiers) = event
wid = Win.WhichWindow(message)
if wid and self._windows.has_key(wid):
window = self._windows[wid]
window.do_rawupdate(wid, event)
else:
if wid:
wid.HideWindow()
import sys
sys.stderr.write("XXX killed unknown (crashed?) Python window.\n")
else:
MacOS.HandleEvent(event)
def suspendresume(self, onoff):
pass
def do_suspendresume(self, event):
self._suspended = not event[1] & 1
FrameWork.Application.do_suspendresume(self, event)
def checkopenwindowsmenu(self):
if self._openwindowscheckmark:
self.openwindowsmenu.menu.CheckItem(self._openwindowscheckmark, 0)
window = Win.FrontWindow()
if window:
for item, wid in self._openwindows.items():
if wid == window:
#self.pythonwindowsmenuitem.check(1)
self.openwindowsmenu.menu.CheckItem(item, 1)
self._openwindowscheckmark = item
break
else:
self._openwindowscheckmark = 0
#if self._openwindows:
# self.pythonwindowsmenuitem.enable(1)
#else:
# self.pythonwindowsmenuitem.enable(0)
def checkmenus(self, window):
for item in self._menustocheck:
callback = item.menu.items[item.item-1][2]
if type(callback) <> StringType:
item.enable(1)
elif hasattr(window, "domenu_" + callback):
if hasattr(window, "can_" + callback):
canhandler = getattr(window, "can_" + callback)
if canhandler(item):
item.enable(1)
else:
item.enable(0)
else:
item.enable(1)
else:
item.enable(0)
def enablemenubar(self, onoff):
for m in self.menubar.menus.values():
if onoff:
m.menu.EnableItem(0)
else:
m.menu.DisableItem(0)
MenuToolbox.DrawMenuBar()
def makemenubar(self):
self.menubar = MenuBar(self)
FrameWork.AppleMenu(self.menubar, self.getabouttext(), self.do_about)
self.makeusermenus()
def scriptswalk(self, top, menu):
import os, macfs, string
try:
names = os.listdir(top)
except os.error:
FrameWork.MenuItem(menu, '(Scripts Folder not found)', None, None)
return
savedir = os.getcwd()
os.chdir(top)
for name in names:
fss, isdir, isalias = macfs.ResolveAliasFile(name)
path = fss.as_pathname()
name = string.strip(name)
if name[-3:] == '---':
menu.addseparator()
elif isdir:
submenu = FrameWork.SubMenu(menu, name)
self.scriptswalk(path, submenu)
else:
creator, type = fss.GetCreatorType()
if type == 'TEXT':
if name[-3:] == '.py':
name = name[:-3]
item = FrameWork.MenuItem(menu, name, None, self.domenu_script)
self._scripts[(menu.id, item.item)] = path
os.chdir(savedir)
def domenu_script(self, id, item, window, event):
(what, message, when, where, modifiers) = event
path = self._scripts[(id, item)]
import os
if not os.path.exists(path):
self.makescriptsmenu()
import W
raise W.AlertError, "File not found."
if ord(Evt.GetKeys()[7]) & 4:
self.openscript(path)
else:
import W, MacOS, sys
W.SetCursor("watch")
sys.argv = [path]
#cwd = os.getcwd()
#os.chdir(os.path.dirname(path) + ':')
try:
# xxx if there is a script window for this file,
# exec in that window's namespace.
# xxx what to do when it's not saved???
# promt to save?
MacOS.EnableAppswitch(0)
execfile(path, {'__name__': '__main__', '__file__': path})
except W.AlertError, detail:
MacOS.EnableAppswitch(-1)
raise W.AlertError, detail
except KeyboardInterrupt:
MacOS.EnableAppswitch(-1)
except:
MacOS.EnableAppswitch(-1)
import PyEdit
PyEdit.tracebackwindow.traceback(1)
else:
MacOS.EnableAppswitch(-1)
#os.chdir(cwd)
def openscript(self, filename, lineno=None, charoffset=0, modname=""):
import os, PyEdit, W
editor = self.getscript(filename)
if editor:
editor.select()
elif os.path.exists(filename):
editor = PyEdit.Editor(filename)
elif filename[-3:] == '.py' or filename[-4:] == '.pyc':
import imp
if not modname:
if filename[-1] == 'c':
modname = os.path.basename(filename)[:-4]
else:
modname = os.path.basename(filename)[:-3]
try:
# XXX This does not work correctly with packages!
# XXX The docs say we should do it manually, pack, then sub, then sub2 etc.
# XXX It says we should use imp.load_module(), but that *reloads* a package,
# XXX and that's the last thing we want here.
f, filename, (suff, mode, dummy) = imp.find_module(modname)
except ImportError:
raise W.AlertError, "CanÕt find file for Ò%sÓ" % modname
else:
if not f:
raise W.AlertError, "CanÕt find file for Ò%sÓ" % modname
f.close()
if suff == '.py':
self.openscript(filename, lineno, charoffset)
return
else:
raise W.AlertError, "CanÕt find file for Ò%sÓ" % modname
else:
raise W.AlertError, "CanÕt find file Ô%sÕ" % filename
if lineno is not None:
editor.selectline(lineno, charoffset)
return editor
def getscript(self, filename):
if filename[:1] == '<' and filename[-1:] == '>':
filename = filename[1:-1]
import string
lowpath = string.lower(filename)
for wid, window in self._windows.items():
if hasattr(window, "path") and lowpath == string.lower(window.path):
return window
elif hasattr(window, "path") and filename == wid.GetWTitle():
return window
def getprefs(self):
import MacPrefs
return MacPrefs.GetPrefs(self.preffilepath)
def do_editorprefs(self, *args):
import PyEdit
PyEdit.EditorDefaultSettings()
class MenuBar(FrameWork.MenuBar):
possibleIDs = range(10, 256)
def getnextid(self):
id = self.possibleIDs[0]
del self.possibleIDs[0]
return id
def __init__(self, parent = None):
self.bar = MenuToolbox.GetMenuBar()
MenuToolbox.ClearMenuBar()
self.menus = {}
self.parent = parent
def dispatch(self, id, item, window, event):
if self.menus.has_key(id):
self.menus[id].dispatch(id, item, window, event)
def delmenu(self, id):
MenuToolbox.DeleteMenu(id)
if id in self.possibleIDs:
print "XXX duplicate menu ID!", id
self.possibleIDs.append(id)
class Menu(FrameWork.Menu):
def dispatch(self, id, item, window, event):
title, shortcut, callback, kind = self.items[item-1]
if type(callback) == StringType:
callback = self._getmenuhandler(callback)
if callback:
import W
W.CallbackCall(callback, 0, id, item, window, event)
def _getmenuhandler(self, callback):
menuhandler = None
wid = Win.FrontWindow()
if wid and self.bar.parent._windows.has_key(wid):
window = self.bar.parent._windows[wid]
if hasattr(window, "domenu_" + callback):
menuhandler = getattr(window, "domenu_" + callback)
elif hasattr(self.bar.parent, "domenu_" + callback):
menuhandler = getattr(self.bar.parent, "domenu_" + callback)
elif hasattr(self.bar.parent, "domenu_" + callback):
menuhandler = getattr(self.bar.parent, "domenu_" + callback)
return menuhandler

720
Mac/Tools/IDE/Wbase.py Normal file
View File

@ -0,0 +1,720 @@
import Qd
import Win
import QuickDraw
import Evt
import string
from types import *
import sys
WidgetsError = "WidgetsError"
DEBUG = 0
class Widget:
"""Base class for all widgets."""
_selectable = 0
def __init__(self, possize):
self._widgets = []
self._widgetsdict = {}
self._possize = possize
self._bounds = None
self._visible = 1
self._enabled = 0
self._selected = 0
self._activated = 0
self._callback = None
self._parent = None
self._parentwindow = None
self._bindings = {}
self._backcolor = None
def show(self, onoff):
self._visible = onoff
for w in self._widgets:
w.show(onoff)
if self._parentwindow is not None and self._parentwindow.wid is not None:
self.SetPort()
if onoff:
self.draw()
else:
Qd.EraseRect(self._bounds)
def draw(self, visRgn = None):
if self._visible:
# draw your stuff here
pass
def getpossize(self):
return self._possize
def getbounds(self):
return self._bounds
def move(self, x, y = None):
"""absolute move"""
if y == None:
x, y = x
if type(self._possize) <> TupleType:
raise WidgetsError, "can't move widget with bounds function"
l, t, r, b = self._possize
self.resize(x, y, r, b)
def rmove(self, x, y = None):
"""relative move"""
if y == None:
x, y = x
if type(self._possize) <> TupleType:
raise WidgetsError, "can't move widget with bounds function"
l, t, r, b = self._possize
self.resize(l + x, t + y, r, b)
def resize(self, *args):
if len(args) == 1:
if type(args[0]) == FunctionType or type(args[0]) == MethodType:
self._possize = args[0]
else:
apply(self.resize, args[0])
elif len(args) == 2:
self._possize = (0, 0) + args
elif len(args) == 4:
self._possize = args
else:
raise TypeError, "wrong number of arguments"
self._calcbounds()
def open(self):
self._calcbounds()
def close(self):
del self._callback
del self._possize
del self._bindings
del self._parent
del self._parentwindow
def bind(self, key, callback):
"""bind a key or an 'event' to a callback"""
if callback:
self._bindings[key] = callback
elif self._bindings.has_key(key):
del self._bindings[key]
def adjust(self, oldbounds):
self.SetPort()
Win.InvalRect(oldbounds)
Win.InvalRect(self._bounds)
def _calcbounds(self):
# calculate absolute bounds relative to the window origin from our
# abstract _possize attribute, which is either a 4-tuple or a callable object
oldbounds = self._bounds
pl, pt, pr, pb = self._parent._bounds
if callable(self._possize):
# _possize is callable, let it figure it out by itself: it should return
# the bounds relative to our parent widget.
width = pr - pl
height = pb - pt
self._bounds = Qd.OffsetRect(self._possize(width, height), pl, pt)
else:
# _possize must be a 4-tuple. This is where the algorithm by Peter Kriens and
# Petr van Blokland kicks in. (*** Parts of this algorithm are applied for
# patents by Ericsson, Sweden ***)
l, t, r, b = self._possize
# depending on the values of l(eft), t(op), r(right) and b(ottom),
# they mean different things:
if l < -1:
# l is less than -1, this mean it measures from the *right* of it's parent
l = pr + l
else:
# l is -1 or greater, this mean it measures from the *left* of it's parent
l = pl + l
if t < -1:
# t is less than -1, this mean it measures from the *bottom* of it's parent
t = pb + t
else:
# t is -1 or greater, this mean it measures from the *top* of it's parent
t = pt + t
if r > 1:
# r is greater than 1, this means r is the *width* of the widget
r = l + r
else:
# r is less than 1, this means it measures from the *right* of it's parent
r = pr + r
if b > 1:
# b is greater than 1, this means b is the *height* of the widget
b = t + b
else:
# b is less than 1, this means it measures from the *bottom* of it's parent
b = pb + b
self._bounds = (l, t, r, b)
if oldbounds and oldbounds <> self._bounds:
self.adjust(oldbounds)
for w in self._widgets:
w._calcbounds()
def test(self, point):
if Qd.PtInRect(point, self._bounds):
return 1
def click(self, point, modifiers):
pass
def findwidget(self, point, onlyenabled = 1):
if self.test(point):
for w in self._widgets:
widget = w.findwidget(point)
if widget is not None:
return widget
if self._enabled or not onlyenabled:
return self
def forall(self, methodname, *args):
for w in self._widgets:
rv = apply(w.forall, (methodname,) + args)
if rv:
return rv
if self._bindings.has_key("<" + methodname + ">"):
callback = self._bindings["<" + methodname + ">"]
rv = apply(callback, args)
if rv:
return rv
if hasattr(self, methodname):
method = getattr(self, methodname)
return apply(method, args)
def forall_butself(self, methodname, *args):
for w in self._widgets:
rv = apply(w.forall, (methodname,) + args)
if rv:
return rv
def forall_frombottom(self, methodname, *args):
if self._bindings.has_key("<" + methodname + ">"):
callback = self._bindings["<" + methodname + ">"]
rv = apply(callback, args)
if rv:
return rv
if hasattr(self, methodname):
method = getattr(self, methodname)
rv = apply(method, args)
if rv:
return rv
for w in self._widgets:
rv = apply(w.forall_frombottom, (methodname,) + args)
if rv:
return rv
def _addwidget(self, key, widget):
if widget in self._widgets:
raise ValueError, "duplicate widget"
if self._widgetsdict.has_key(key):
self._removewidget(key)
self._widgets.append(widget)
self._widgetsdict[key] = widget
widget._parent = self
self._setparentwindow(widget)
if self._parentwindow and self._parentwindow.wid:
widget.forall_frombottom("open")
Win.InvalRect(widget._bounds)
def _setparentwindow(self, widget):
widget._parentwindow = self._parentwindow
for w in widget._widgets:
self._setparentwindow(w)
def _removewidget(self, key):
if not self._widgetsdict.has_key(key):
raise KeyError, "no widget with key " + `key`
widget = self._widgetsdict[key]
for k in widget._widgetsdict.keys():
widget._removewidget(k)
if self._parentwindow._currentwidget == widget:
widget.select(0)
self._parentwindow._currentwidget = None
self.SetPort()
Win.InvalRect(widget._bounds)
widget.close()
del self._widgetsdict[key]
self._widgets.remove(widget)
def __setattr__(self, attr, value):
if type(value) == InstanceType and isinstance(value, Widget) and \
attr not in ("_currentwidget", "_lastrollover",
"_parent", "_parentwindow", "_defaultbutton"):
if hasattr(self, attr):
raise ValueError, "Can't replace existing attribute: " + attr
self._addwidget(attr, value)
self.__dict__[attr] = value
def __delattr__(self, attr):
if attr == "_widgetsdict":
raise AttributeError, "cannot delete attribute _widgetsdict"
if self._widgetsdict.has_key(attr):
self._removewidget(attr)
if self.__dict__.has_key(attr):
del self.__dict__[attr]
elif self.__dict__.has_key(attr):
del self.__dict__[attr]
else:
raise AttributeError, attr
def __setitem__(self, key, value):
self._addwidget(key, value)
def __getitem__(self, key):
if not self._widgetsdict.has_key(key):
raise KeyError, key
return self._widgetsdict[key]
def __delitem__(self, key):
self._removewidget(key)
def SetPort(self):
self._parentwindow.SetPort()
def __del__(self):
if DEBUG:
print "%s instance deleted" % self.__class__.__name__
def _drawbounds(self):
Qd.FrameRect(self._bounds)
class ClickableWidget(Widget):
"""Base class for clickable widgets. (note: self._enabled must be true to receive click events.)"""
def click(self, point, modifiers):
pass
def enable(self, onoff):
self._enabled = onoff
self.SetPort()
self.draw()
def callback(self):
if self._callback:
return CallbackCall(self._callback, 1)
class SelectableWidget(ClickableWidget):
"""Base class for selectable widgets."""
_selectable = 1
def select(self, onoff, isclick = 0):
if onoff == self._selected:
return 1
if self._bindings.has_key("<select>"):
callback = self._bindings["<select>"]
if callback(onoff):
return 1
self._selected = onoff
if onoff:
if self._parentwindow._currentwidget is not None:
self._parentwindow._currentwidget.select(0)
self._parentwindow._currentwidget = self
else:
self._parentwindow._currentwidget = None
def key(self, char, event):
pass
def drawselframe(self, onoff):
if not self._parentwindow._hasselframes:
return
thickrect = Qd.InsetRect(self._bounds, -3, -3)
state = Qd.GetPenState()
Qd.PenSize(2, 2)
if onoff:
Qd.PenPat(Qd.qd.black)
else:
Qd.PenPat(Qd.qd.white)
Qd.FrameRect(thickrect)
Qd.SetPenState(state)
def adjust(self, oldbounds):
self.SetPort()
if self._selected:
Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3))
Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3))
else:
Win.InvalRect(oldbounds)
Win.InvalRect(self._bounds)
class _Line(Widget):
def __init__(self, possize, thickness = 1):
Widget.__init__(self, possize)
self._thickness = thickness
def open(self):
self._calcbounds()
self.SetPort()
self.draw()
def draw(self, visRgn = None):
if self._visible:
Qd.PaintRect(self._bounds)
def _drawbounds(self):
pass
class HorizontalLine(_Line):
def _calcbounds(self):
Widget._calcbounds(self)
l, t, r, b = self._bounds
self._bounds = l, t, r, t + self._thickness
class VerticalLine(_Line):
def _calcbounds(self):
Widget._calcbounds(self)
l, t, r, b = self._bounds
self._bounds = l, t, l + self._thickness, b
class Frame(Widget):
def __init__(self, possize, pattern = Qd.qd.black, color = (0, 0, 0)):
Widget.__init__(self, possize)
self._framepattern = pattern
self._framecolor = color
def setcolor(self, color):
self._framecolor = color
self.SetPort()
self.draw()
def setpattern(self, pattern):
self._framepattern = pattern
self.SetPort()
self.draw()
def draw(self, visRgn = None):
if self._visible:
penstate = Qd.GetPenState()
Qd.PenPat(self._framepattern)
Qd.RGBForeColor(self._framecolor)
Qd.FrameRect(self._bounds)
Qd.RGBForeColor((0, 0, 0))
Qd.SetPenState(penstate)
def _darkencolor((r, g, b)):
return 0.75 * r, 0.75 * g, 0.75 * b
class BevelBox(Widget):
"""'Platinum' beveled rectangle."""
def __init__(self, possize, color = (0xe000, 0xe000, 0xe000)):
Widget.__init__(self, possize)
self._color = color
self._darkercolor = _darkencolor(color)
def setcolor(self, color):
self._color = color
self.SetPort()
self.draw()
def draw(self, visRgn = None):
if self._visible:
l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
Qd.RGBForeColor(self._color)
Qd.PaintRect((l, t, r, b))
Qd.RGBForeColor(self._darkercolor)
Qd.MoveTo(l, b)
Qd.LineTo(r, b)
Qd.LineTo(r, t)
Qd.RGBForeColor((0, 0, 0))
class Group(Widget):
"""A container for subwidgets"""
class HorizontalPanes(Widget):
"""Panes, a.k.a. frames. Works a bit like a group. Devides the widget area into "panes",
which can be resized by the user by clicking and dragging between the subwidgets."""
_direction = 1
def __init__(self, possize, panesizes = None, gutter = 8):
"""panesizes should be a tuple of numbers. The length of the tuple is the number of panes,
the items in the tuple are the relative sizes of these panes; these numbers should add up
to 1 (the total size of all panes)."""
ClickableWidget.__init__(self, possize)
self._panesizes = panesizes
self._gutter = gutter
self._enabled = 1
self.setuppanes()
#def open(self):
# self.installbounds()
# ClickableWidget.open(self)
def _calcbounds(self):
# hmmm. It should not neccesary be override _calcbounds :-(
self.installbounds()
Widget._calcbounds(self)
def setuppanes(self):
panesizes = self._panesizes
total = 0
if panesizes is not None:
#if len(self._widgets) <> len(panesizes):
# raise TypeError, 'number of widgets does not match number of panes'
for panesize in panesizes:
if not 0 < panesize < 1:
raise TypeError, 'pane sizes must be between 0 and 1, not including.'
total = total + panesize
if round(total, 4) <> 1.0:
raise TypeError, 'pane sizes must add up to 1'
else:
# XXX does not work!
step = 1.0 / len(self._widgets)
panesizes = []
for i in range(len(self._widgets)):
panesizes.append(step)
current = 0
self._panesizes = []
self._gutters = []
for panesize in panesizes:
if current:
self._gutters.append(current)
self._panesizes.append(current, current + panesize)
current = current + panesize
self.makepanebounds()
def getpanesizes(self):
return map(lambda (fr, to): to-fr, self._panesizes)
boundstemplate = "lambda width, height: (0, height * %s + %d, width, height * %s + %d)"
def makepanebounds(self):
halfgutter = self._gutter / 2
self._panebounds = []
for i in range(len(self._panesizes)):
panestart, paneend = self._panesizes[i]
boundsstring = self.boundstemplate % (`panestart`, panestart and halfgutter,
`paneend`, (paneend <> 1.0) and -halfgutter)
self._panebounds.append(eval(boundsstring))
def installbounds(self):
#self.setuppanes()
for i in range(len(self._widgets)):
w = self._widgets[i]
w._possize = self._panebounds[i]
#if hasattr(w, "setuppanes"):
# w.setuppanes()
if hasattr(w, "installbounds"):
w.installbounds()
def rollover(self, point, onoff):
if onoff:
orgmouse = point[self._direction]
halfgutter = self._gutter / 2
l, t, r, b = self._bounds
if self._direction:
begin, end = t, b
else:
begin, end = l, r
i = self.findgutter(orgmouse, begin, end)
if i is None:
SetCursor("arrow")
else:
SetCursor(self._direction and 'vmover' or 'hmover')
def findgutter(self, orgmouse, begin, end):
tolerance = max(4, self._gutter) / 2
for i in range(len(self._gutters)):
pos = begin + (end - begin) * self._gutters[i]
if abs(orgmouse - pos) <= tolerance:
break
else:
return
return i
def click(self, point, modifiers):
# what a mess...
orgmouse = point[self._direction]
halfgutter = self._gutter / 2
l, t, r, b = self._bounds
if self._direction:
begin, end = t, b
else:
begin, end = l, r
i = self.findgutter(orgmouse, begin, end)
if i is None:
return
pos = orgpos = begin + (end - begin) * self._gutters[i] # init pos too, for fast click on border, bug done by Petr
minpos = self._panesizes[i][0]
maxpos = self._panesizes[i+1][1]
minpos = begin + (end - begin) * minpos + 64
maxpos = begin + (end - begin) * maxpos - 64
if minpos > orgpos and maxpos < orgpos:
return
#SetCursor("fist")
self.SetPort()
if self._direction:
rect = l, orgpos - 1, r, orgpos
else:
rect = orgpos - 1, t, orgpos, b
# track mouse --- XXX move to separate method?
Qd.PenMode(QuickDraw.srcXor)
Qd.PenPat(Qd.qd.gray)
Qd.PaintRect(rect)
lastpos = None
while Evt.Button():
pos = orgpos - orgmouse + Evt.GetMouse()[self._direction]
pos = max(pos, minpos)
pos = min(pos, maxpos)
if pos == lastpos:
continue
Qd.PenPat(Qd.qd.gray)
Qd.PaintRect(rect)
if self._direction:
rect = l, pos - 1, r, pos
else:
rect = pos - 1, t, pos, b
Qd.PenPat(Qd.qd.gray)
Qd.PaintRect(rect)
lastpos = pos
Qd.PaintRect(rect)
Qd.PenNormal()
SetCursor("watch")
newpos = (pos - begin) / float(end - begin)
self._gutters[i] = newpos
self._panesizes[i] = self._panesizes[i][0], newpos
self._panesizes[i+1] = newpos, self._panesizes[i+1][1]
self.makepanebounds()
self.installbounds()
self._calcbounds()
class VerticalPanes(HorizontalPanes):
"""see HorizontalPanes"""
_direction = 0
boundstemplate = "lambda width, height: (width * %s + %d, 0, width * %s + %d, height)"
class ColorPicker(ClickableWidget):
"""Color picker widget. Allows the user to choose a color."""
def __init__(self, possize, color = (0, 0, 0), callback = None):
ClickableWidget.__init__(self, possize)
self._color = color
self._callback = callback
self._enabled = 1
def click(self, point, modifiers):
if not self._enabled:
return
import ColorPicker
newcolor, ok = ColorPicker.GetColor("", self._color)
if ok:
self._color = newcolor
self.SetPort()
self.draw()
if self._callback:
return CallbackCall(self._callback, 0, self._color)
def set(self, color):
self._color = color
self.SetPort()
self.draw()
def get(self):
return self._color
def draw(self, visRgn=None):
if self._visible:
if not visRgn:
visRgn = self._parentwindow.wid.GetWindowPort().visRgn
Qd.PenPat(Qd.qd.gray)
rect = self._bounds
Qd.FrameRect(rect)
rect = Qd.InsetRect(rect, 3, 3)
Qd.PenNormal()
Qd.RGBForeColor(self._color)
Qd.PaintRect(rect)
Qd.RGBForeColor((0, 0, 0))
# misc utils
def CallbackCall(callback, mustfit, *args):
"""internal helper routine for W"""
# XXX this function should die.
if type(callback) == FunctionType:
func = callback
maxargs = func.func_code.co_argcount
elif type(callback) == MethodType:
func = callback.im_func
maxargs = func.func_code.co_argcount - 1
else:
if callable(callback):
return apply(callback, args)
else:
raise TypeError, "uncallable callback object"
if func.func_defaults:
minargs = maxargs - len(func.func_defaults)
else:
minargs = maxargs
if minargs <= len(args) <= maxargs:
return apply(callback, args)
elif not mustfit and minargs == 0:
return callback()
else:
if mustfit:
raise TypeError, "callback accepts wrong number of arguments: " + `len(args)`
else:
raise TypeError, "callback accepts wrong number of arguments: 0 or " + `len(args)`
def HasBaseClass(obj, class_):
try:
raise obj
except class_:
return 1
except:
pass
return 0
_cursors = {
"watch" : Qd.GetCursor(QuickDraw.watchCursor).data,
"arrow" : Qd.qd.arrow,
"iBeam" : Qd.GetCursor(QuickDraw.iBeamCursor).data,
"cross" : Qd.GetCursor(QuickDraw.crossCursor).data,
"plus" : Qd.GetCursor(QuickDraw.plusCursor).data,
"hand" : Qd.GetCursor(468).data,
"fist" : Qd.GetCursor(469).data,
"hmover" : Qd.GetCursor(470).data,
"vmover" : Qd.GetCursor(471).data,
"zoomin" : Qd.GetCursor(472).data,
"zoomout" : Qd.GetCursor(473).data,
"zoom" : Qd.GetCursor(474).data,
}
def SetCursor(what):
"""Set the cursorshape to any of these: 'arrow', 'cross', 'fist', 'hand', 'hmover', 'iBeam',
'plus', 'vmover', 'watch', 'zoom', 'zoomin', 'zoomout'."""
Qd.SetCursor(_cursors[what])

396
Mac/Tools/IDE/Wcontrols.py Normal file
View File

@ -0,0 +1,396 @@
import Ctl
import Controls
import Win
import Wbase
import Qd
import Evt
class ControlWidget(Wbase.ClickableWidget):
"""Baseclass for all native controls."""
def __init__(self, possize, title = "Control", procID = 0, callback = None, value = 0, min = 0, max = 1):
Wbase.ClickableWidget.__init__(self, possize)
self._control = None
self._title = title
self._callback = callback
self._procID = procID
self._value = value
self._min = min
self._max = max
self._enabled = 1
def open(self):
self._calcbounds()
self._control = Ctl.NewControl(self._parentwindow.wid,
self._bounds,
self._title,
1,
self._value,
self._min,
self._max,
self._procID,
0)
self.SetPort()
#Win.ValidRect(self._bounds)
self.enable(self._enabled)
def adjust(self, oldbounds):
self.SetPort()
self._control.HideControl()
self._control.MoveControl(self._bounds[0], self._bounds[1])
self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
if self._visible:
Qd.EraseRect(self._bounds)
self._control.ShowControl()
Win.ValidRect(self._bounds)
def close(self):
self._control.HideControl()
self._control = None
Wbase.ClickableWidget.close(self)
def enable(self, onoff):
if self._control and self._enabled <> onoff:
self._control.HiliteControl((not onoff) and 255)
self._enabled = onoff
def show(self, onoff):
self._visible = onoff
for w in self._widgets:
w.show(onoff)
if onoff:
self._control.ShowControl()
else:
self._control.HideControl()
def activate(self, onoff):
self._activated = onoff
if self._enabled:
self._control.HiliteControl((not onoff) and 255)
def draw(self, visRgn = None):
if self._visible:
self._control.Draw1Control()
def test(self, point):
ctltype, control = Ctl.FindControl(point, self._parentwindow.wid)
if self._enabled and control == self._control:
return 1
def click(self, point, modifiers):
if not self._enabled:
return
part = self._control.TrackControl(point)
if part:
if self._callback:
Wbase.CallbackCall(self._callback, 0)
def settitle(self, title):
if self._control:
self._control.SetControlTitle(title)
self._title = title
def gettitle(self):
return self._title
class Button(ControlWidget):
"""Standard push button."""
def __init__(self, possize, title = "Button", callback = None):
procID = Controls.pushButProc | Controls.useWFont
ControlWidget.__init__(self, possize, title, procID, callback, 0, 0, 1)
self._isdefault = 0
def push(self):
if not self._enabled:
return
import time
self._control.HiliteControl(1)
time.sleep(0.1)
self._control.HiliteControl(0)
if self._callback:
Wbase.CallbackCall(self._callback, 0)
def enable(self, onoff):
if self._control and self._enabled <> onoff:
self._control.HiliteControl((not onoff) and 255)
self._enabled = onoff
if self._isdefault and self._visible:
self.SetPort()
self.drawfatframe(onoff)
def activate(self, onoff):
self._activated = onoff
if self._enabled:
self._control.HiliteControl((not onoff) and 255)
if self._isdefault and self._visible:
self.SetPort()
self.drawfatframe(onoff)
def show(self, onoff):
ControlWidget.show(self, onoff)
if self._isdefault:
self.drawfatframe(onoff and self._enabled)
def draw(self, visRgn = None):
if self._visible:
self._control.Draw1Control()
if self._isdefault and self._activated:
self.drawfatframe(self._enabled)
def drawfatframe(self, onoff):
state = Qd.GetPenState()
if onoff:
Qd.PenPat(Qd.qd.black)
else:
Qd.PenPat(Qd.qd.white)
fatrect = Qd.InsetRect(self._bounds, -4, -4)
Qd.PenSize(3, 3)
Qd.FrameRoundRect(fatrect, 16, 16)
Qd.SetPenState(state)
def _setdefault(self, onoff):
self._isdefault = onoff
if self._control and self._enabled:
self.SetPort()
self.drawfatframe(onoff)
def adjust(self, oldbounds):
if self._isdefault:
old = Qd.InsetRect(oldbounds, -4, -4)
new = Qd.InsetRect(self._bounds, -4, -4)
Qd.EraseRect(old)
Win.InvalRect(old)
Win.InvalRect(new)
ControlWidget.adjust(self, oldbounds)
class CheckBox(ControlWidget):
"""Standard checkbox."""
def __init__(self, possize, title = "Checkbox", callback = None, value = 0):
procID = Controls.checkBoxProc | Controls.useWFont
ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
def click(self, point, modifiers):
if not self._enabled:
return
part = self._control.TrackControl(point)
if part:
self.toggle()
if self._callback:
Wbase.CallbackCall(self._callback, 0, self.get())
def push(self):
if not self._enabled:
return
self.toggle()
if self._callback:
Wbase.CallbackCall(self._callback, 0, self.get())
def toggle(self):
self.set(not self.get())
def set(self, value):
if self._control:
self._control.SetControlValue(value)
else:
self._value = value
def get(self):
if self._control:
return self._control.GetControlValue()
else:
return self._value
class RadioButton(ControlWidget):
"""Standard radiobutton."""
# XXX We need a radiogroup widget; this is too kludgy.
def __init__(self, possize, title, thebuttons, callback = None, value = 0):
procID = Controls.radioButProc | Controls.useWFont
ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
self.thebuttons = thebuttons
thebuttons.append(self)
def close(self):
self.thebuttons = None
ControlWidget.close(self)
def click(self, point, modifiers):
if not self._enabled:
return
part = self._control.TrackControl(point)
if part:
self.set(1)
if self._callback:
Wbase.CallbackCall(self._callback, 0, 1)
def push(self):
if not self._enabled:
return
self.set(1)
if self._callback:
Wbase.CallbackCall(self._callback, 0, 1)
def set(self, value):
for button in self.thebuttons:
if button._control:
button._control.SetControlValue(button == self)
else:
button._value = (button == self)
def get(self):
if self._control:
return self._control.GetControlValue()
else:
return self._value
class Scrollbar(ControlWidget):
"""Standard scrollbar."""
def __init__(self, possize, callback = None, value = 0, min = 0, max = 0):
procID = Controls.scrollBarProc
ControlWidget.__init__(self, possize, "", procID, callback, value, min, max)
# interface
def set(self, value):
if self._callback:
Wbase.CallbackCall(self._callback, 1, value)
def up(self):
if self._callback:
Wbase.CallbackCall(self._callback, 1, '+')
def down(self):
if self._callback:
Wbase.CallbackCall(self._callback, 1, '-')
def pageup(self):
if self._callback:
Wbase.CallbackCall(self._callback, 1, '++')
def pagedown(self):
if self._callback:
Wbase.CallbackCall(self._callback, 1, '--')
def setmin(self, min):
self._control.SetControlMinimum(min)
def setmax(self, min):
self._control.SetControlMinimum(max)
def getmin(self):
return self._control.GetControlMinimum()
def getmax(self):
return self._control.GetControlMinimum()
# internals
def click(self, point, modifiers):
if not self._enabled:
return
# custom TrackControl. A mousedown in a scrollbar arrow or page area should
# generate _control hits as long as the mouse is a) down, b) still in the same part
part = self._control.TestControl(point)
if Controls.inUpButton <= part <= Controls.inPageDown:
self._control.HiliteControl(part)
self._hit(part)
oldpart = part
while Evt.StillDown():
part = self._control.TestControl(point)
if part == oldpart:
self._control.HiliteControl(part)
self._hit(part)
else:
self._control.HiliteControl(0)
self.SetPort()
point = Evt.GetMouse()
self._control.HiliteControl(0)
elif part == Controls.inThumb:
part = self._control.TrackControl(point)
if part:
self._hit(part)
def _hit(self, part):
if part == Controls.inThumb:
value = self._control.GetControlValue()
elif part == Controls.inUpButton:
value = "+"
elif part == Controls.inDownButton:
value = "-"
elif part == Controls.inPageUp:
value = "++"
elif part == Controls.inPageDown:
value = "--"
if self._callback:
Wbase.CallbackCall(self._callback, 1, value)
def draw(self, visRgn = None):
if self._visible:
self._control.Draw1Control()
Qd.FrameRect(self._bounds)
def adjust(self, oldbounds):
self.SetPort()
Win.InvalRect(oldbounds)
self._control.HideControl()
self._control.MoveControl(self._bounds[0], self._bounds[1])
self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
if self._visible:
Qd.EraseRect(self._bounds)
if self._activated:
self._control.ShowControl()
else:
Qd.FrameRect(self._bounds)
Win.ValidRect(self._bounds)
def activate(self, onoff):
self._activated = onoff
if self._visible:
if onoff:
self._control.ShowControl()
else:
self._control.HideControl()
self.draw(None)
Win.ValidRect(self._bounds)
def set(self, value):
if self._control:
self._control.SetControlValue(value)
else:
self._value = value
def get(self):
if self._control:
return self._control.GetControlValue()
else:
return self._value
class __xxxx_PopupControl(ControlWidget):
def __init__(self, possize, title = "Button", callback = None):
procID = Controls.popupMenuProc # | Controls.useWFont
ControlWidget.__init__(self, possize, title, procID, callback, 0, 0, 1)
self._isdefault = 0
def _scalebarvalue(absmin, absmax, curmin, curmax):
if curmin <= absmin and curmax >= absmax:
return None
if curmin <= absmin:
return 0
if curmax >= absmax:
return 32767
perc = float(curmin-absmin) / float((absmax - absmin) - (curmax - curmin))
return int(perc*32767)

BIN
Mac/Tools/IDE/Widgets.rsrc Normal file

Binary file not shown.

45
Mac/Tools/IDE/Wkeys.py Normal file
View File

@ -0,0 +1,45 @@
spacekey = ' '
returnkey = '\r'
tabkey = '\t'
enterkey = '\003'
backspacekey = '\010'
deletekey = '\177'
helpkey = '\005'
leftarrowkey = '\034'
rightarrowkey = '\035'
uparrowkey = '\036'
downarrowkey = '\037'
arrowkeys = [leftarrowkey, rightarrowkey, uparrowkey, downarrowkey]
topkey = '\001'
bottomkey = '\004'
pageupkey = '\013'
pagedownkey = '\014'
scrollkeys = [topkey, bottomkey, pageupkey, pagedownkey]
navigationkeys = arrowkeys + scrollkeys
keycodes = {
"space" : ' ',
"return" : '\r',
"tab" : '\t',
"enter" : '\003',
"backspace" : '\010',
"delete" : '\177',
"help" : '\005',
"leftarrow" : '\034',
"rightarrow" : '\035',
"uparrow" : '\036',
"downarrow" : '\037',
"top" : '\001',
"bottom" : '\004',
"pageup" : '\013',
"pagedown" : '\014'
}
keynames = {}
for k, v in keycodes.items():
keynames[v] = k
del k, v

457
Mac/Tools/IDE/Wlists.py Normal file
View File

@ -0,0 +1,457 @@
import Wbase
import Wkeys
import Scrap
import string
import Evt
import Events
import Qd
import Win
class List(Wbase.SelectableWidget):
"""Standard list widget."""
LDEF_ID = 0
def __init__(self, possize, items = None, callback = None, flags = 0, cols = 1):
if items is None:
items = []
self.items = items
Wbase.SelectableWidget.__init__(self, possize)
self._selected = 0
self._enabled = 1
self._list = None
self._cols = cols
self._callback = callback
self._flags = flags
self.lasttyping = ""
self.lasttime = Evt.TickCount()
self.timelimit = 30
self.setitems(items)
self.drawingmode = 0
def open(self):
self.setdrawingmode(0)
self.createlist()
self.setdrawingmode(1)
def createlist(self):
import List
self._calcbounds()
self.SetPort()
rect = self._bounds
rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1
self._list = List.LNew(rect, (0, 0, self._cols, 0), (0, 0), self.LDEF_ID, self._parentwindow.wid,
0, 1, 0, 1)
if self.drawingmode:
self._list.LSetDrawingMode(0)
self._list.selFlags = self._flags
self.setitems(self.items)
if hasattr(self, "_sel"):
self.setselection(self._sel)
del self._sel
def adjust(self, oldbounds):
self.SetPort()
if self._selected:
Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3))
Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3))
else:
Win.InvalRect(oldbounds)
Win.InvalRect(self._bounds)
if oldbounds[:2] == self._bounds[:2]:
# set visRgn to empty, to prevent nasty drawing side effect of LSize()
Qd.RectRgn(self._parentwindow.wid.GetWindowPort().visRgn, (0, 0, 0, 0))
# list still has the same upper/left coordinates, use LSize
l, t, r, b = self._bounds
width = r - l - 17
height = b - t - 2
self._list.LSize(width, height)
# now *why* doesn't the list manager recalc the cellrect???
l, t, r, b = self._list.LRect((0,0))
cellheight = b - t
self._list.LCellSize((width, cellheight))
# reset visRgn
self._parentwindow.wid.CalcVis()
else:
# oh well, since the list manager doesn't have a LMove call,
# we have to make the list all over again...
sel = self.getselection()
topcell = self.gettopcell()
self._list = None
self.setdrawingmode(0)
self.createlist()
self.setselection(sel)
self.settopcell(topcell)
self.setdrawingmode(1)
def close(self):
self._list = None
self._callback = None
self.items[:] = []
Wbase.SelectableWidget.close(self)
def set(self, items):
self.setitems(items)
def setitems(self, items):
self.items = items
the_list = self._list
if not self._parent or not self._list:
return
self.setdrawingmode(0)
topcell = self.gettopcell()
the_list.LDelRow(0, 1)
the_list.LAddRow(len(self.items), 0)
self_itemrepr = self.itemrepr
set_cell = the_list.LSetCell
for i in range(len(items)):
set_cell(self_itemrepr(items[i]), (0, i))
self.settopcell(topcell)
self.setdrawingmode(1)
def click(self, point, modifiers):
if not self._enabled:
return
isdoubleclick = self._list.LClick(point, modifiers)
if self._callback:
Wbase.CallbackCall(self._callback, 0, isdoubleclick)
return 1
def key(self, char, event):
(what, message, when, where, modifiers) = event
sel = self.getselection()
newselection = []
if char == Wkeys.uparrowkey:
if len(sel) >= 1 and min(sel) > 0:
newselection = [min(sel) - 1]
else:
newselection = [0]
elif char == Wkeys.downarrowkey:
if len(sel) >= 1 and max(sel) < (len(self.items) - 1):
newselection = [max(sel) + 1]
else:
newselection = [len(self.items) - 1]
else:
modifiers = 0
if (self.lasttime + self.timelimit) < Evt.TickCount():
self.lasttyping = ""
self.lasttyping = self.lasttyping + string.lower(char)
self.lasttime = Evt.TickCount()
i = self.findmatch(self.lasttyping)
newselection = [i]
if modifiers & Events.shiftKey:
newselection = newselection + sel
self.setselection(newselection)
self._list.LAutoScroll()
self.click((-1, -1), 0)
def findmatch(self, tag):
lower = string.lower
items = self.items
taglen = len(tag)
match = '\377' * 100
match_i = -1
for i in range(len(items)):
item = lower(str(items[i]))
if tag <= item < match:
match = item
match_i = i
if match_i >= 0:
return match_i
else:
return len(items) - 1
def domenu_copy(self, *args):
sel = self.getselection()
selitems = []
for i in sel:
selitems.append(str(self.items[i]))
text = string.join(selitems, '\r')
if text:
Scrap.ZeroScrap()
Scrap.PutScrap('TEXT', text)
def can_copy(self, *args):
return len(self.getselection()) <> 0
def domenu_selectall(self, *args):
self.selectall()
def selectall(self):
self.setselection(range(len(self.items)))
self._list.LAutoScroll()
self.click((-1, -1), 0)
def getselection(self):
if not self._parent or not self._list:
if hasattr(self, "_sel"):
return self._sel
return []
items = []
point = (0,0)
while 1:
ok, point = self._list.LGetSelect(1, point)
if not ok:
break
items.append(point[1])
point = point[0], point[1]+1
return items
def setselection(self, selection):
if not self._parent or not self._list:
self._sel = selection
return
set_sel = self._list.LSetSelect
for i in range(len(self.items)):
if i in selection:
set_sel(1, (0, i))
else:
set_sel(0, (0, i))
self._list.LAutoScroll()
def getselectedobjects(self):
sel = self.getselection()
objects = []
for i in sel:
objects.append(self.items[i])
return objects
def setselectedobjects(self, objects):
sel = []
for o in objects:
try:
sel.append(self.items.index(o))
except:
pass
self.setselection(sel)
def gettopcell(self):
l, t, r, b = self._bounds
t = t + 1
cl, ct, cr, cb = self._list.LRect((0, 0))
cellheight = cb - ct
return (t - ct) / cellheight
def settopcell(self, topcell):
top = self.gettopcell()
diff = topcell - top
self._list.LScroll(0, diff)
def draw(self, visRgn = None):
if self._visible:
if not visRgn:
visRgn = self._parentwindow.wid.GetWindowPort().visRgn
self._list.LUpdate(visRgn)
Qd.FrameRect(self._bounds)
if self._selected and self._activated:
self.drawselframe(1)
def select(self, onoff, isclick = 0):
if Wbase.SelectableWidget.select(self, onoff):
return
self.SetPort()
self.drawselframe(onoff)
def activate(self, onoff):
self._activated = onoff
if self._visible:
self._list.LActivate(onoff)
if self._selected:
self.drawselframe(onoff)
def get(self):
return self.items
def itemrepr(self, item):
return str(item)[:255]
def __getitem__(self, index):
return self.items[index]
def __setitem__(self, index, item):
if self._parent and self._list:
self._list.LSetCell(self.itemrepr(item), (0, index))
self.items[index] = item
def __delitem__(self, index):
if self._parent and self._list:
self._list.LDelRow(1, index)
del self.items[index]
def __getslice__(self, a, b):
return self.items[a:b]
def __delslice__(self, a, b):
if b-a:
if self._parent and self._list:
self._list.LDelRow(b-a, a)
del self.items[a:b]
def __setslice__(self, a, b, items):
if self._parent and self._list:
l = len(items)
the_list = self._list
self.setdrawingmode(0)
if b-a:
if b > len(self.items):
# fix for new 1.5 "feature" where b is sys.maxint instead of len(self)...
# LDelRow doesn't like maxint.
b = len(self.items)
the_list.LDelRow(b-a, a)
the_list.LAddRow(l, a)
self_itemrepr = self.itemrepr
set_cell = the_list.LSetCell
for i in range(len(items)):
set_cell(self_itemrepr(items[i]), (0, i + a))
self.items[a:b] = items
self.setdrawingmode(1)
else:
self.items[a:b] = items
def __len__(self):
return len(self.items)
def append(self, item):
if self._parent and self._list:
index = len(self.items)
self._list.LAddRow(1, index)
self._list.LSetCell(self.itemrepr(item), (0, index))
self.items.append(item)
def remove(self, item):
index = self.items.index(item)
self.__delitem__(index)
def index(self, item):
return self.items.index(item)
def insert(self, index, item):
if index < 0:
index = 0
if self._parent and self._list:
self._list.LAddRow(1, index)
self._list.LSetCell(self.itemrepr(item), (0, index))
self.items.insert(index, item)
def setdrawingmode(self, onoff):
if onoff:
self.drawingmode = self.drawingmode - 1
if self.drawingmode == 0 and self._list is not None:
self._list.LSetDrawingMode(1)
if self._visible:
bounds = l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
cl, ct, cr, cb = self._list.LRect((0, len(self.items)-1))
if cb < b:
self.SetPort()
Qd.EraseRect((l, cb, cr, b))
self._list.LUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
Win.ValidRect(bounds)
else:
if self.drawingmode == 0 and self._list is not None:
self._list.LSetDrawingMode(0)
self.drawingmode = self.drawingmode + 1
class TwoLineList(List):
LDEF_ID = 468
def createlist(self):
import List
self._calcbounds()
self.SetPort()
rect = self._bounds
rect = rect[0]+1, rect[1]+1, rect[2]-16, rect[3]-1
self._list = List.LNew(rect, (0, 0, 1, 0), (0, 28), self.LDEF_ID, self._parentwindow.wid,
0, 1, 0, 1)
self.set(self.items)
class ResultsWindow:
"""Simple results window. The user cannot make this window go away completely:
closing it will just hide it. It will remain in the windows list. The owner of this window
should call the done() method to indicate it's done with it.
"""
def __init__(self, possize=None, title="Results", callback=None):
import W
if possize is None:
possize = (500, 200)
self.w = W.Window(possize, title, minsize=(200, 100))
self.w.results = W.TwoLineList((-1, -1, 1, -14), callback=None)
self.w.bind("<close>", self.hide)
self.w.open()
self._done = 0
def done(self):
self._done = 1
if not self.w.isvisible():
self.w.close()
def hide(self):
if not self._done:
self.w.show(0)
return -1
def append(self, msg):
if not self.w.isvisible():
self.w.show(1)
self.w.select()
msg = string.replace(msg, '\n', '\r')
self.w.results.append(msg)
self.w.results.setselection([len(self.w.results)-1])
def __getattr__(self, attr):
return getattr(self.w.results, attr)
class MultiList(List):
"""XXX Experimantal!!!"""
def setitems(self, items):
self.items = items
if not self._parent or not self._list:
return
self._list.LDelRow(0, 1)
self.setdrawingmode(0)
self._list.LAddRow(len(self.items), 0)
self_itemrepr = self.itemrepr
set_cell = self._list.LSetCell
for i in range(len(items)):
row = items[i]
for j in range(len(row)):
item = row[j]
set_cell(self_itemrepr(item), (j, i))
self.setdrawingmode(1)
def getselection(self):
if not self._parent or not self._list:
if hasattr(self, "_sel"):
return self._sel
return []
items = []
point = (0,0)
while 1:
ok, point = self._list.LGetSelect(1, point)
if not ok:
break
items.append(point[1])
point = point[0], point[1]+1
return items
def setselection(self, selection):
if not self._parent or not self._list:
self._sel = selection
return
set_sel = self._list.LSetSelect
for i in range(len(self.items)):
if i in selection:
set_sel(1, (0, i))
else:
set_sel(0, (0, i))
#self._list.LAutoScroll()

196
Mac/Tools/IDE/Wmenus.py Normal file
View File

@ -0,0 +1,196 @@
import FrameWork
import Qd
import Wbase
from types import *
import Wapplication
_arrowright = Qd.GetPicture(472)
_arrowdown = Qd.GetPicture(473)
class PopupWidget(Wbase.ClickableWidget):
"""Simple title-less popup widget. Should be 16x16 pixels.
Builds the menu items on the fly, good for dynamic popup menus."""
def __init__(self, possize, items = [], callback = None):
Wbase.Widget.__init__(self, possize)
self._items = items
self._itemsdict = {}
self._callback = callback
self._enabled = 1
def close(self):
Wbase.Widget.close(self)
self._items = None
self._itemsdict = {}
def draw(self, visRgn = None):
if self._visible:
Qd.FrameRect(self._bounds)
Qd.EraseRect(Qd.InsetRect(self._bounds, 1, 1))
l, t, r, b = self._bounds
l = l + 2
t = t + 3
pictframe = (l, t, l + 10, t + 10)
Qd.DrawPicture(_arrowright, pictframe)
def click(self, point, modifiers):
if not self._enabled:
return
self.menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
self._additems(self._items, self.menu)
self.SetPort()
l, t, r, b = self._bounds
l, t = Qd.LocalToGlobal((l+1, t+1))
Wbase.SetCursor("arrow")
self.menu.menu.EnableItem(0)
reply = self.menu.menu.PopUpMenuSelect(t, l, 1)
if reply:
id = (reply & 0xffff0000) >> 16
item = reply & 0xffff
self._menu_callback(id, item)
self._emptymenu()
def set(self, items):
self._items = items
def get(self):
return self._items
def _additems(self, items, menu):
from FrameWork import SubMenu, MenuItem
menu_id = menu.id
for item in items:
if item == "-":
menu.addseparator()
continue
elif type(item) == ListType:
submenu = SubMenu(menu, item[0])
self._additems(item[1:], submenu)
continue
elif type(item) == StringType:
menuitemtext = object = item
elif type(item) == TupleType and len(item) == 2:
menuitemtext, object = item
else:
raise Wbase.WidgetsError, "illegal itemlist for popup menu"
if menuitemtext[:1] == '\0':
check = ord(menuitemtext[1])
menuitemtext = menuitemtext[2:]
else:
check = 0
menuitem = MenuItem(menu, menuitemtext, None, None)
if check:
menuitem.check(1)
self._itemsdict[(menu_id, menuitem.item)] = object
def _emptymenu(self):
menus = self._parentwindow.parent.menubar.menus
for id, item in self._itemsdict.keys():
if menus.has_key(id):
self.menu = menus[id]
self.menu.delete()
self._itemsdict = {}
def _menu_callback(self, id, item):
thing = self._itemsdict[(id, item)]
if callable(thing):
thing()
elif self._callback:
Wbase.CallbackCall(self._callback, 0, thing)
class PopupMenu(PopupWidget):
"""Simple title-less popup widget. Should be 16x16 pixels.
Prebuilds the menu items, good for static (non changing) popup menus."""
def open(self):
self._calcbounds()
self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
self._additems(self._items, self.menu)
def close(self):
self._emptymenu()
Wbase.Widget.close(self)
self._items = None
self._itemsdict = {}
self.menu = None
def set(self, items):
if self._itemsdict:
self._emptymenu()
self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1)
self._items = items
self._additems(self._items, self.menu)
def click(self, point, modifiers):
if not self._enabled:
return
self.SetPort()
l, t, r, b = self._bounds
l, t = Qd.LocalToGlobal((l+1, t+1))
Wbase.SetCursor("arrow")
self.menu.menu.EnableItem(0)
reply = self.menu.menu.PopUpMenuSelect(t, l, 1)
if reply:
id = (reply & 0xffff0000) >> 16
item = reply & 0xffff
self._menu_callback(id, item)
class FontMenu(PopupMenu):
"""A font popup menu."""
menu = None
def __init__(self, possize, callback):
PopupMenu.__init__(self, possize)
_makefontmenu()
self._callback = callback
self._enabled = 1
def open(self):
self._calcbounds()
def close(self):
del self._callback
def set(self):
raise Wbase.WidgetsError, "can't change font menu widget"
def _menu_callback(self, id, item):
fontname = self.menu.menu.GetMenuItemText(item)
if self._callback:
Wbase.CallbackCall(self._callback, 0, fontname)
def click(self, point, modifiers):
if not self._enabled:
return
_makefontmenu()
return PopupMenu.click(self, point, modifiers)
def _makefontmenu():
"""helper for font menu"""
if FontMenu.menu is not None:
return
import W
FontMenu.menu = Wapplication.Menu(W.getapplication().menubar, 'Foo', -1)
W.SetCursor('watch')
for i in range(FontMenu.menu.menu.CountMItems(), 0, -1):
FontMenu.menu.menu.DeleteMenuItem(i)
FontMenu.menu.menu.AppendResMenu('FOND')
def _getfontlist():
import Res
fontnames = []
for i in range(1, Res.CountResources('FOND') + 1):
r = Res.GetIndResource('FOND', i)
fontnames.append(r.GetResInfo()[2])
return fontnames

119
Mac/Tools/IDE/Wquicktime.py Normal file
View File

@ -0,0 +1,119 @@
import os
import Qd
import Win
import Qt, QuickTime
import W
import macfs
import Evt, Events
_moviesinitialized = 0
def EnterMovies():
global _moviesinitialized
if not _moviesinitialized:
Qt.EnterMovies()
_moviesinitialized = 1
class Movie(W.Widget):
def __init__(self, possize):
EnterMovies()
self.movie = None
self.running = 0
W.Widget.__init__(self, possize)
def adjust(self, oldbounds):
self.SetPort()
Win.InvalRect(oldbounds)
Win.InvalRect(self._bounds)
self.calcmoviebox()
def set(self, path_or_fss, start = 0):
self.SetPort()
if self.movie:
#Win.InvalRect(self.movie.GetMovieBox())
Qd.PaintRect(self.movie.GetMovieBox())
if type(path_or_fss) == type(''):
path = path_or_fss
fss = macfs.FSSpec(path)
else:
path = path_or_fss.as_pathname()
fss = path_or_fss
self.movietitle = os.path.basename(path)
movieResRef = Qt.OpenMovieFile(fss, 1)
self.movie, dummy, dummy = Qt.NewMovieFromFile(movieResRef, 0, QuickTime.newMovieActive)
self.moviebox = self.movie.GetMovieBox()
self.calcmoviebox()
Qd.ObscureCursor() # XXX does this work at all?
self.movie.GoToBeginningOfMovie()
if start:
self.movie.StartMovie()
self.running = 1
else:
self.running = 0
self.movie.MoviesTask(0)
def get(self):
return self.movie
def getmovietitle(self):
return self.movietitle
def start(self):
if self.movie:
Qd.ObscureCursor()
self.movie.StartMovie()
self.running = 1
def stop(self):
if self.movie:
self.movie.StopMovie()
self.running = 0
def rewind(self):
if self.movie:
self.movie.GoToBeginningOfMovie()
def calcmoviebox(self):
if not self.movie:
return
ml, mt, mr, mb = self.moviebox
wl, wt, wr, wb = widgetbox = self._bounds
mheight = mb - mt
mwidth = mr - ml
wheight = wb - wt
wwidth = wr - wl
if (mheight * 2 < wheight) and (mwidth * 2 < wwidth):
scale = 2
elif mheight > wheight or mwidth > wwidth:
scale = min(float(wheight) / mheight, float(wwidth) / mwidth)
else:
scale = 1
mwidth, mheight = mwidth * scale, mheight * scale
ml, mt = wl + (wwidth - mwidth) / 2, wt + (wheight - mheight) / 2
mr, mb = ml + mwidth, mt + mheight
self.movie.SetMovieBox((ml, mt, mr, mb))
def idle(self, *args):
if self.movie:
if not self.movie.IsMovieDone() and self.running:
Qd.ObscureCursor()
while 1:
self.movie.MoviesTask(0)
gotone, event = Evt.EventAvail(Events.everyEvent)
if gotone or self.movie.IsMovieDone():
break
elif self.running:
box = self.movie.GetMovieBox()
self.SetPort()
Win.InvalRect(box)
self.movie = None
self.running = 0
def draw(self, visRgn = None):
if self._visible:
Qd.PaintRect(self._bounds)
if self.movie:
self.movie.UpdateMovie()
self.movie.MoviesTask(0)

979
Mac/Tools/IDE/Wtext.py Normal file
View File

@ -0,0 +1,979 @@
import Qd
import TE
import Fm
import waste
import WASTEconst
import Res
import Evt
import Events
import Scrap
import string
import Win
import Wbase
import Wkeys
import Wcontrols
import PyFontify
from types import *
import Fonts
import TextEdit
class TextBox(Wbase.Widget):
"""A static text widget"""
def __init__(self, possize, text = "", align = TextEdit.teJustLeft,
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
backgroundcolor = (0xffff, 0xffff, 0xffff)
):
Wbase.Widget.__init__(self, possize)
self.fontsettings = fontsettings
self.text = text
self.align = align
self._backgroundcolor = backgroundcolor
def draw(self, visRgn = None):
if self._visible:
(font, style, size, color) = self.fontsettings
fontid = GetFNum(font)
savestate = Qd.GetPenState()
Qd.TextFont(fontid)
Qd.TextFace(style)
Qd.TextSize(size)
Qd.RGBForeColor(color)
Qd.RGBBackColor(self._backgroundcolor)
TE.TETextBox(self.text, self._bounds, self.align)
Qd.RGBBackColor((0xffff, 0xffff, 0xffff))
Qd.SetPenState(savestate)
def get(self):
return self.text
def set(self, text):
self.text = text
if self._parentwindow and self._parentwindow.wid:
self.SetPort()
self.draw()
class _ScrollWidget:
# to be overridden
def getscrollbarvalues(self):
return None, None
# internal method
def updatescrollbars(self):
vx, vy = self.getscrollbarvalues()
if self._parent._barx:
if vx <> None:
self._parent._barx.enable(1)
self._parent._barx.set(vx)
else:
self._parent._barx.enable(0)
if self._parent._bary:
if vy <> None:
self._parent._bary.enable(1)
self._parent._bary.set(vy)
else:
self._parent._bary.enable(0)
UNDOLABELS = [ # Indexed by WEGetUndoInfo() value
None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"]
class EditText(Wbase.SelectableWidget, _ScrollWidget):
"""A text edit widget, mainly for simple entry fields."""
def __init__(self, possize, text = "",
callback = None, inset = (3, 3),
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
tabsettings = (32, 0),
readonly = 0):
Wbase.SelectableWidget.__init__(self, possize)
self.temptext = text
self.ted = None
self.selection = None
self._callback = callback
self.changed = 0
self.selchanged = 0
self._selected = 0
self._enabled = 1
self.wrap = 1
self.readonly = readonly
self.fontsettings = fontsettings
self.tabsettings = tabsettings
if type(inset) <> TupleType:
self.inset = (inset, inset)
else:
self.inset = inset
def open(self):
if not hasattr(self._parent, "_barx"):
self._parent._barx = None
if not hasattr(self._parent, "_bary"):
self._parent._bary = None
self._calcbounds()
self.SetPort()
viewrect, destrect = self._calctextbounds()
flags = self._getflags()
self.ted = waste.WENew(destrect, viewrect, flags)
self.ted.WEInstallTabHooks()
self.ted.WESetAlignment(WASTEconst.weFlushLeft)
self.setfontsettings(self.fontsettings)
self.settabsettings(self.tabsettings)
self.ted.WEUseText(Res.Resource(self.temptext))
self.ted.WECalText()
if self.selection:
self.setselection(self.selection[0], self.selection[1])
self.selection = None
else:
self.selview()
self.temptext = None
self.updatescrollbars()
self.bind("pageup", self.scrollpageup)
self.bind("pagedown", self.scrollpagedown)
self.bind("top", self.scrolltop)
self.bind("bottom", self.scrollbottom)
self.selchanged = 0
def close(self):
self._parent._barx = None
self._parent._bary = None
self.ted = None
self.temptext = None
Wbase.SelectableWidget.close(self)
def gettabsettings(self):
return self.tabsettings
def settabsettings(self, (tabsize, tabmode)):
self.tabsettings = (tabsize, tabmode)
if hasattr(self.ted, "WESetTabSize"):
port = self._parentwindow.wid.GetWindowPort()
if tabmode:
(font, style, size, color) = self.getfontsettings()
savesettings = GetPortFontSettings(port)
SetPortFontSettings(port, (font, style, size))
tabsize = Qd.StringWidth(' ' * tabsize)
SetPortFontSettings(port, savesettings)
tabsize = max(tabsize, 1)
self.ted.WESetTabSize(tabsize)
self.SetPort()
Qd.EraseRect(self.ted.WEGetViewRect())
self.ted.WEUpdate(port.visRgn)
def getfontsettings(self):
import Res
(font, style, size, color) = self.ted.WEGetRunInfo(0)[4]
font = Fm.GetFontName(font)
return (font, style, size, color)
def setfontsettings(self, (font, style, size, color)):
self.SetPort()
if type(font) <> StringType:
font = Fm.GetFontName(font)
self.fontsettings = (font, style, size, color)
fontid = GetFNum(font)
readonly = self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, -1)
if readonly:
self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
try:
self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 1)
selstart, selend = self.ted.WEGetSelection()
self.ted.WESetSelection(0, self.ted.WEGetTextLength())
self.ted.WESetStyle(WASTEconst.weDoFace, (0, 0, 0, (0, 0, 0)))
self.ted.WESetStyle(WASTEconst.weDoFace |
WASTEconst.weDoColor |
WASTEconst.weDoFont |
WASTEconst.weDoSize,
(fontid, style, size, color))
self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 0)
self.ted.WECalText()
self.ted.WESetSelection(selstart, selend)
finally:
if readonly:
self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
viewrect = self.ted.WEGetViewRect()
Qd.EraseRect(viewrect)
self.ted.WEUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
self.selchanged = 1
self.updatescrollbars()
def adjust(self, oldbounds):
self.SetPort()
if self._selected and self._parentwindow._hasselframes:
Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3))
Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3))
else:
Win.InvalRect(oldbounds)
Win.InvalRect(self._bounds)
viewrect, destrect = self._calctextbounds()
self.ted.WESetViewRect(viewrect)
self.ted.WESetDestRect(destrect)
if self.wrap:
self.ted.WECalText()
if self.ted.WEGetDestRect()[3] < viewrect[1]:
self.selview()
self.updatescrollbars()
# interface -----------------------
# selection stuff
def selview(self):
self.ted.WESelView()
def selectall(self):
self.ted.WESetSelection(0, self.ted.WEGetTextLength())
self.selchanged = 1
self.updatescrollbars()
def selectline(self, lineno, charoffset = 0):
newselstart, newselend = self.ted.WEGetLineRange(lineno)
# Autoscroll makes the *end* of the selection visible, which,
# in the case of a whole line, is the beginning of the *next* line.
# So sometimes it leaves our line just above the view rect.
# Let's fool Waste by initially selecting one char less:
self.ted.WESetSelection(newselstart + charoffset, newselend-1)
self.ted.WESetSelection(newselstart + charoffset, newselend)
self.selchanged = 1
self.updatescrollbars()
def getselection(self):
if self.ted:
return self.ted.WEGetSelection()
else:
return self.selection
def setselection(self, selstart, selend):
self.selchanged = 1
if self.ted:
self.ted.WESetSelection(selstart, selend)
self.ted.WESelView()
self.updatescrollbars()
else:
self.selection = selstart, selend
def offsettoline(self, offset):
return self.ted.WEOffsetToLine(offset)
def countlines(self):
return self.ted.WECountLines()
def getselectedtext(self):
selstart, selend = self.ted.WEGetSelection()
return self.ted.WEGetText().data[selstart:selend]
def expandselection(self):
oldselstart, oldselend = self.ted.WEGetSelection()
selstart, selend = min(oldselstart, oldselend), max(oldselstart, oldselend)
if selstart <> selend and chr(self.ted.WEGetChar(selend-1)) == '\r':
selend = selend - 1
newselstart, dummy = self.ted.WEFindLine(selstart, 0)
dummy, newselend = self.ted.WEFindLine(selend, 0)
if oldselstart <> newselstart or oldselend <> newselend:
self.ted.WESetSelection(newselstart, newselend)
self.updatescrollbars()
self.selchanged = 1
def insert(self, text):
self.ted.WEInsert(text, None, None)
self.changed = 1
self.selchanged = 1
# text
def set(self, text):
if not self.ted:
self.temptext = text
else:
self.ted.WEUseText(Res.Resource(text))
self.ted.WECalText()
self.SetPort()
viewrect, destrect = self._calctextbounds()
self.ted.WESetViewRect(viewrect)
self.ted.WESetDestRect(destrect)
rgn = Qd.NewRgn()
Qd.RectRgn(rgn, viewrect)
Qd.EraseRect(viewrect)
self.draw(rgn)
#Win.InvalRect(self.ted.WEGetViewRect())
self.updatescrollbars()
def get(self):
if not self._parent:
return self.temptext
else:
return self.ted.WEGetText().data
# events
def key(self, char, event):
(what, message, when, where, modifiers) = event
if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
self.ted.WEKey(ord(char), modifiers)
if char not in Wkeys.navigationkeys:
self.changed = 1
if char not in Wkeys.scrollkeys:
self.selchanged = 1
self.updatescrollbars()
if self._callback:
Wbase.CallbackCall(self._callback, 0, char, modifiers)
def click(self, point, modifiers):
if not self._enabled:
return
self.ted.WEClick(point, modifiers, Evt.TickCount())
self.selchanged = 1
self.updatescrollbars()
return 1
def idle(self):
self.SetPort()
self.ted.WEIdle()
def rollover(self, point, onoff):
if onoff:
Wbase.SetCursor("iBeam")
def activate(self, onoff):
self._activated = onoff
if self._selected and self._visible:
if onoff:
self.ted.WEActivate()
else:
self.ted.WEDeactivate()
if self._selected:
self.drawselframe(onoff)
def select(self, onoff, isclick = 0):
if Wbase.SelectableWidget.select(self, onoff):
return
self.SetPort()
if onoff:
self.ted.WEActivate()
if self._parentwindow._tabbable and not isclick:
self.selectall()
else:
self.ted.WEDeactivate()
self.drawselframe(onoff)
def draw(self, visRgn = None):
if self._visible:
if not visRgn:
visRgn = self._parentwindow.wid.GetWindowPort().visRgn
self.ted.WEUpdate(visRgn)
if self._selected and self._activated:
self.drawselframe(1)
Qd.FrameRect(self._bounds)
# scrolling
def scrollpageup(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll("++")
def scrollpagedown(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll("--")
def scrolltop(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll(0)
if self._parent._barx and self._parent._barx._enabled:
self.hscroll(0)
def scrollbottom(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll(32767)
# menu handlers
def domenu_copy(self, *args):
selbegin, selend = self.ted.WEGetSelection()
if selbegin == selend:
return
Scrap.ZeroScrap()
self.ted.WECopy()
self.updatescrollbars()
def domenu_cut(self, *args):
selbegin, selend = self.ted.WEGetSelection()
if selbegin == selend:
return
Scrap.ZeroScrap()
self.ted.WECut()
self.updatescrollbars()
self.selview()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def domenu_paste(self, *args):
if not self.ted.WECanPaste():
return
self.selview()
self.ted.WEPaste()
self.updatescrollbars()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def domenu_clear(self, *args):
self.ted.WEDelete()
self.selview()
self.updatescrollbars()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def domenu_undo(self, *args):
which, redo = self.ted.WEGetUndoInfo()
if not which:
return
self.ted.WEUndo()
self.updatescrollbars()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def can_undo(self, menuitem):
#doundo = self.ted.WEFeatureFlag(WASTEconst.weFUndo, -1)
#print doundo
#if not doundo:
# return 0
which, redo = self.ted.WEGetUndoInfo()
which = UNDOLABELS[which]
if which == None:
return None
if redo:
which = "Redo "+which
else:
which = "Undo "+which
menuitem.settext(which)
return 1
def domenu_selectall(self, *args):
self.selectall()
# private
def getscrollbarvalues(self):
dr = self.ted.WEGetDestRect()
vr = self.ted.WEGetViewRect()
vx = Wcontrols._scalebarvalue(dr[0], dr[2], vr[0], vr[2])
vy = Wcontrols._scalebarvalue(dr[1], dr[3], vr[1], vr[3])
return vx, vy
def vscroll(self, value):
lineheight = self.ted.WEGetHeight(0, 1)
dr = self.ted.WEGetDestRect()
vr = self.ted.WEGetViewRect()
destheight = dr[3] - dr[1]
viewheight = vr[3] - vr[1]
viewoffset = maxdelta = vr[1] - dr[1]
mindelta = vr[3] - dr[3]
if value == "+":
delta = lineheight
elif value == "-":
delta = - lineheight
elif value == "++":
delta = viewheight - lineheight
elif value == "--":
delta = lineheight - viewheight
else: # in thumb
cur = (32767 * viewoffset) / (destheight - viewheight)
delta = (cur-value)*(destheight - viewheight)/32767
if abs(delta - viewoffset) <=2:
# compensate for irritating rounding error
delta = viewoffset
delta = min(maxdelta, delta)
delta = max(mindelta, delta)
self.ted.WEScroll(0, delta)
self.updatescrollbars()
def hscroll(self, value):
dr = self.ted.WEGetDestRect()
vr = self.ted.WEGetViewRect()
destwidth = dr[2] - dr[0]
viewwidth = vr[2] - vr[0]
viewoffset = maxdelta = vr[0] - dr[0]
mindelta = vr[2] - dr[2]
if value == "+":
delta = 32
elif value == "-":
delta = - 32
elif value == "++":
delta = 0.5 * (vr[2] - vr[0])
elif value == "--":
delta = 0.5 * (vr[0] - vr[2])
else: # in thumb
cur = (32767 * viewoffset) / (destwidth - viewwidth)
delta = (cur-value)*(destwidth - viewwidth)/32767
if abs(delta - viewoffset) <=2:
# compensate for irritating rounding error
delta = viewoffset
delta = min(maxdelta, delta)
delta = max(mindelta, delta)
self.ted.WEScroll(delta, 0)
self.updatescrollbars()
# some internals
def _getflags(self):
flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled
if self.readonly:
flags = flags | WASTEconst.weDoReadOnly
else:
flags = flags | WASTEconst.weDoUndo
return flags
def _getviewrect(self):
return Qd.InsetRect(self._bounds, self.inset[0], self.inset[1])
def _calctextbounds(self):
viewrect = l, t, r, b = self._getviewrect()
if self.ted:
dl, dt, dr, db = self.ted.WEGetDestRect()
vl, vt, vr, vb = self.ted.WEGetViewRect()
yshift = t - vt
if (db - dt) < (b - t):
destrect = viewrect
else:
destrect = l, dt + yshift, r, db + yshift
else:
destrect = viewrect
return viewrect, destrect
class TextEditor(EditText):
"""A text edit widget."""
def __init__(self, possize, text = "", callback = None, wrap = 1, inset = (4, 4),
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
tabsettings = (32, 0),
readonly = 0):
EditText.__init__(self, possize, text, callback, inset, fontsettings, tabsettings, readonly)
self.wrap = wrap
def _getflags(self):
flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled | \
WASTEconst.weDoOutlineHilite
if self.readonly:
flags = flags | WASTEconst.weDoReadOnly
else:
flags = flags | WASTEconst.weDoUndo
return flags
def _getviewrect(self):
l, t, r, b = self._bounds
return (l + 5, t + 2, r, b - 2)
def _calctextbounds(self):
if self.wrap:
return EditText._calctextbounds(self)
else:
viewrect = l, t, r, b = self._getviewrect()
if self.ted:
dl, dt, dr, db = self.ted.WEGetDestRect()
vl, vt, vr, vb = self.ted.WEGetViewRect()
xshift = l - vl
yshift = t - vt
if (db - dt) < (b - t):
yshift = t - dt
destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
else:
destrect = (l, t, r + 5000, b)
return viewrect, destrect
def draw(self, visRgn = None):
if self._visible:
if not visRgn:
visRgn = self._parentwindow.wid.GetWindowPort().visRgn
self.ted.WEUpdate(visRgn)
if self._selected and self._activated:
self.drawselframe(1)
import regex
commentPat = regex.compile("[ \t]*\(#\)")
indentPat = regex.compile("\t*")
class PyEditor(TextEditor):
"""A specialized Python source edit widget"""
def __init__(self, possize, text = "", callback = None, inset = (4, 4),
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
tabsettings = (32, 0),
readonly = 0,
debugger = None,
file = ''):
TextEditor.__init__(self, possize, text, callback, 0, inset, fontsettings, tabsettings, readonly)
self.bind("cmd[", self.domenu_shiftleft)
self.bind("cmd]", self.domenu_shiftright)
self.bind("cmdshift[", self.domenu_uncomment)
self.bind("cmdshift]", self.domenu_comment)
self.file = file # only for debugger reference
self._debugger = debugger
if debugger:
debugger.register_editor(self, self.file)
def domenu_shiftleft(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
for i in range(len(lines)):
if lines[i][:1] == '\t':
lines[i] = lines[i][1:]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def domenu_shiftright(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
for i in range(len(lines) - (not lines[-1])):
lines[i] = '\t' + lines[i]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def domenu_uncomment(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
for i in range(len(lines)):
res = commentPat.match(lines[i]) >= 0
if res > 0:
pos = commentPat.regs[1][0]
lines[i] = lines[i][:pos] + lines[i][pos+1:]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def domenu_comment(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
indent = 3000 # arbitrary large number...
for line in lines:
if string.strip(line):
if indentPat.match(line):
indent = min(indent, indentPat.regs[0][1])
else:
indent = 0
break
for i in range(len(lines) - (not lines[-1])):
lines[i] = lines[i][:indent] + "#" + lines[i][indent:]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def setfile(self, file):
self.file = file
def set(self, text, file = ''):
oldfile = self.file
self.file = file
if self._debugger:
self._debugger.unregister_editor(self, oldfile)
self._debugger.register_editor(self, file)
TextEditor.set(self, text)
def close(self):
if self._debugger:
self._debugger.unregister_editor(self, self.file)
self._debugger = None
TextEditor.close(self)
def click(self, point, modifiers):
if not self._enabled:
return
if self._debugger and self.pt_in_breaks(point):
self.breakhit(point, modifiers)
elif self._debugger:
bl, bt, br, bb = self._getbreakrect()
Qd.EraseRect((bl, bt, br-1, bb))
TextEditor.click(self, point, modifiers)
self.drawbreakpoints()
else:
TextEditor.click(self, point, modifiers)
if self.ted.WEGetClickCount() >= 3:
# select block with our indent
lines = string.split(self.get(), '\r')
selstart, selend = self.ted.WEGetSelection()
lineno = self.ted.WEOffsetToLine(selstart)
tabs = 0
line = lines[lineno]
while line[tabs:] and line[tabs] == '\t':
tabs = tabs + 1
tabstag = '\t' * tabs
fromline = 0
toline = len(lines)
if tabs:
for i in range(lineno - 1, -1, -1):
line = lines[i]
if line[:tabs] <> tabstag:
fromline = i + 1
break
for i in range(lineno + 1, toline):
line = lines[i]
if line[:tabs] <> tabstag:
toline = i - 1
break
selstart, dummy = self.ted.WEGetLineRange(fromline)
dummy, selend = self.ted.WEGetLineRange(toline)
self.ted.WESetSelection(selstart, selend)
def breakhit(self, point, modifiers):
if not self.file:
return
destrect = self.ted.WEGetDestRect()
offset, edge = self.ted.WEGetOffset(point)
lineno = self.ted.WEOffsetToLine(offset) + 1
if point[1] <= destrect[3]:
self._debugger.clear_breaks_above(self.file, self.countlines())
self._debugger.toggle_break(self.file, lineno)
else:
self._debugger.clear_breaks_above(self.file, lineno)
def key(self, char, event):
(what, message, when, where, modifiers) = event
if modifiers & Events.cmdKey and not char in Wkeys.arrowkeys:
return
if char == '\r':
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
lastchar = chr(self.ted.WEGetChar(selstart-1))
if lastchar <> '\r' and selstart:
pos, dummy = self.ted.WEFindLine(selstart, 0)
lineres = Res.Resource('')
self.ted.WECopyRange(pos, selstart, lineres, None, None)
line = lineres.data + '\n'
tabcount = self.extratabs(line)
self.ted.WEKey(ord('\r'), 0)
for i in range(tabcount):
self.ted.WEKey(ord('\t'), 0)
else:
self.ted.WEKey(ord('\r'), 0)
elif char in ')]}':
self.ted.WEKey(ord(char), modifiers)
self.balanceparens(char)
else:
self.ted.WEKey(ord(char), modifiers)
if char not in Wkeys.navigationkeys:
self.changed = 1
self.selchanged = 1
self.updatescrollbars()
def balanceparens(self, char):
if char == ')':
target = '('
elif char == ']':
target = '['
elif char == '}':
target = '{'
recursionlevel = 1
selstart, selend = self.ted.WEGetSelection()
count = min(selstart, selend) - 2
mincount = max(0, count - 2048)
lastquote = None
while count > mincount:
testchar = chr(self.ted.WEGetChar(count))
if testchar in "\"'" and chr(self.ted.WEGetChar(count - 1)) <> '\\':
if lastquote == testchar:
recursionlevel = recursionlevel - 1
lastquote = None
elif not lastquote:
recursionlevel = recursionlevel + 1
lastquote = testchar
elif not lastquote and testchar == char:
recursionlevel = recursionlevel + 1
elif not lastquote and testchar == target:
recursionlevel = recursionlevel - 1
if recursionlevel == 0:
import time
autoscroll = self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, -1)
if autoscroll:
self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 0)
self.ted.WESetSelection(count, count + 1)
time.sleep(0.2)
self.ted.WESetSelection(selstart, selend)
if autoscroll:
self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 1)
break
count = count - 1
def extratabs(self, line):
tabcount = 0
for c in line:
if c <> '\t':
break
tabcount = tabcount + 1
last = 0
cleanline = ''
tags = PyFontify.fontify(line)
# strip comments and strings
for tag, start, end, sublist in tags:
if tag in ('string', 'comment'):
cleanline = cleanline + line[last:start]
last = end
cleanline = cleanline + line[last:]
cleanline = string.strip(cleanline)
if cleanline and cleanline[-1] == ':':
tabcount = tabcount + 1
else:
# extra indent after unbalanced (, [ or {
for open, close in (('(', ')'), ('[', ']'), ('{', '}')):
count = string.count(cleanline, open)
if count and count > string.count(cleanline, close):
tabcount = tabcount + 2
break
return tabcount
def rollover(self, point, onoff):
if onoff:
if self._debugger and self.pt_in_breaks(point):
Wbase.SetCursor("arrow")
else:
Wbase.SetCursor("iBeam")
def draw(self, visRgn = None):
TextEditor.draw(self, visRgn)
if self._debugger:
self.drawbreakpoints()
def showbreakpoints(self, onoff):
if (not not self._debugger) <> onoff:
if onoff:
if not __debug__:
import W
raise W.AlertError, "CanÕt debug in ÒOptimize bytecodeÓ mode.\r(see ÒDefault startup optionsÓ in EditPythonPreferences)"
import PyDebugger
self._debugger = PyDebugger.getdebugger()
self._debugger.register_editor(self, self.file)
elif self._debugger:
self._debugger.unregister_editor(self, self.file)
self._debugger = None
self.adjust(self._bounds)
def togglebreakpoints(self):
self.showbreakpoints(not self._debugger)
def clearbreakpoints(self):
if self.file:
self._debugger.clear_all_file_breaks(self.file)
def editbreakpoints(self):
if self._debugger:
self._debugger.edit_breaks()
self._debugger.breaksviewer.selectfile(self.file)
def drawbreakpoints(self, eraseall = 0):
breakrect = bl, bt, br, bb = self._getbreakrect()
br = br - 1
self.SetPort()
Qd.PenPat(Qd.qd.gray)
Qd.PaintRect((br, bt, br + 1, bb))
Qd.PenNormal()
self._parentwindow.tempcliprect(breakrect)
Qd.RGBForeColor((0xffff, 0, 0))
try:
lasttop = bt
self_ted = self.ted
Qd_PaintOval = Qd.PaintOval
Qd_EraseRect = Qd.EraseRect
for lineno in self._debugger.get_file_breaks(self.file):
start, end = self_ted.WEGetLineRange(lineno - 1)
if lineno <> self_ted.WEOffsetToLine(start) + 1:
# breakpoints beyond our text: erase rest, and back out
Qd_EraseRect((bl, lasttop, br, bb))
break
(x, y), h = self_ted.WEGetPoint(start, 0)
bottom = y + h
#print y, (lasttop, bottom)
if bottom > lasttop:
Qd_EraseRect((bl, lasttop, br, y + h * eraseall))
lasttop = bottom
redbullet = bl + 2, y + 3, bl + 8, y + 9
Qd_PaintOval(redbullet)
else:
Qd_EraseRect((bl, lasttop, br, bb))
Qd.RGBForeColor((0, 0, 0))
finally:
self._parentwindow.restoreclip()
def updatescrollbars(self):
if self._debugger:
self.drawbreakpoints(1)
TextEditor.updatescrollbars(self)
def pt_in_breaks(self, point):
return Qd.PtInRect(point, self._getbreakrect())
def _getbreakrect(self):
if self._debugger:
l, t, r, b = self._bounds
return (l+1, t+1, l + 12, b-1)
else:
return (0, 0, 0, 0)
def _getviewrect(self):
l, t, r, b = self._bounds
if self._debugger:
return (l + 17, t + 2, r, b - 2)
else:
return (l + 5, t + 2, r, b - 2)
def _calctextbounds(self):
viewrect = l, t, r, b = self._getviewrect()
if self.ted:
dl, dt, dr, db = self.ted.WEGetDestRect()
vl, vt, vr, vb = self.ted.WEGetViewRect()
xshift = l - vl
yshift = t - vt
if (db - dt) < (b - t):
yshift = t - dt
destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
else:
destrect = (l, t, r + 5000, b)
return viewrect, destrect
def GetFNum(fontname):
"""Same as Fm.GetFNum(), but maps a missing font to Monaco instead of the system font."""
if fontname <> Fm.GetFontName(0):
fontid = Fm.GetFNum(fontname)
if fontid == 0:
fontid = Fonts.monaco
else:
fontid = 0
return fontid
# b/w compat. Anyone using this?
GetFName = Fm.GetFontName
def GetPortFontSettings(port):
return Fm.GetFontName(port.txFont), port.txFace, port.txSize
def SetPortFontSettings(port, (font, face, size)):
saveport = Qd.GetPort()
Qd.SetPort(port)
Qd.TextFont(GetFNum(font))
Qd.TextFace(face)
Qd.TextSize(size)
Qd.SetPort(saveport)

188
Mac/Tools/IDE/Wtraceback.py Normal file
View File

@ -0,0 +1,188 @@
import traceback
import sys
import W
import os
import types
import List
class TraceBack:
def __init__(self, title = "Traceback"):
app = W.getapplication() # checks if W is properly initialized
self.title = title
self.w = None
self.closed = 1
self.start = 0
self.lastwindowtitle = ""
self.bounds = (360, 298)
def traceback(self, start = 0, lastwindowtitle = ""):
try:
self.lastwindowtitle = lastwindowtitle
self.start = start
self.type, self.value, self.tb = sys.exc_type, sys.exc_value, sys.exc_traceback
if self.type is not SyntaxError:
self.show()
if type(self.type) == types.ClassType:
errortext = self.type.__name__
else:
errortext = str(self.type)
value = str(self.value)
if self.value and value:
errortext = errortext + ": " + value
self.w.text.set(errortext)
self.buildtblist()
self.w.list.set(self.textlist)
self.w.list.setselection([len(self.textlist) - 1])
self.w.wid.SelectWindow()
self.closed = 0
else:
self.syntaxerror()
except:
traceback.print_exc()
def syntaxerror(self):
try:
value, (filename, lineno, charno, line) = self.value
except:
filename = ""
lineno = None
value = self.value
if not filename and self.lastwindowtitle:
filename = self.lastwindowtitle
elif not filename:
filename = "<unknown>"
if filename and os.path.exists(filename):
filename = os.path.split(filename)[1]
if lineno:
charno = charno - 1
text = str(value) + '\rFile: "' + str(filename) + '", line ' + str(lineno) + '\r\r' + line[:charno] + "¥" + line[charno:-1]
else:
text = str(value) + '\rFile: "' + str(filename) + '"'
self.syntaxdialog = W.ModalDialog((360, 120), "Syntax Error")
self.syntaxdialog.text = W.TextBox((10, 10, -10, -40), text)
self.syntaxdialog.cancel = W.Button((-190, -32, 80, 16), "Cancel", self.syntaxclose)
self.syntaxdialog.edit = W.Button((-100, -32, 80, 16), "Edit", self.syntaxedit)
self.syntaxdialog.setdefaultbutton(self.syntaxdialog.edit)
self.syntaxdialog.bind("cmd.", self.syntaxdialog.cancel.push)
self.syntaxdialog.open()
def syntaxclose(self):
self.syntaxdialog.close()
del self.syntaxdialog
def syntaxedit(self):
try:
value, (filename, lineno, charno, line) = self.value
except:
filename = ""
lineno = None
if not filename and self.lastwindowtitle:
filename = self.lastwindowtitle
elif not filename:
filename = "<unknown>"
self.syntaxclose()
if lineno:
W.getapplication().openscript(filename, lineno, charno - 1)
else:
W.getapplication().openscript(filename)
def show(self):
if self.closed:
self.setupwidgets()
self.w.open()
else:
self.w.wid.ShowWindow()
self.w.wid.SelectWindow()
def hide(self):
if self.closed:
return
self.w.close()
def close(self):
self.bounds = self.w.getbounds()
self.closed = 1
self.type, self.value, self.tb = None, None, None
self.tblist = None
def activate(self, onoff):
if onoff:
if self.closed:
self.traceback()
self.closed = 0
self.checkbuttons()
def setupwidgets(self):
self.w = W.Window(self.bounds, self.title, minsize = (316, 168))
self.w.text = W.TextBox((10, 10, -10, 30))
self.w.tbtitle = W.TextBox((10, 40, -10, 10), "Traceback (innermost last):")
self.w.list = W.TwoLineList((10, 60, -10, -40), callback = self.listhit)
self.w.editbutton = W.Button((10, -30, 60, 16), "Edit", self.edit)
self.w.editbutton.enable(0)
self.w.browselocalsbutton = W.Button((80, -30, 100, 16), "Browse localsÉ", self.browselocals)
self.w.browselocalsbutton.enable(0)
self.w.postmortembutton = W.Button((190, -30, 100, 16), "Post mortemÉ", self.postmortem)
self.w.setdefaultbutton(self.w.editbutton)
self.w.bind("cmdb", self.w.browselocalsbutton.push)
self.w.bind("<close>", self.close)
self.w.bind("<activate>", self.activate)
def buildtblist(self):
tb = self.tb
for i in range(self.start):
if tb.tb_next is None:
break
tb = tb.tb_next
self.tblist = traceback.extract_tb(tb)
self.textlist = []
for filename, lineno, func, line in self.tblist:
tbline = ""
if os.path.exists(filename):
filename = os.path.split(filename)[1]
tbline = 'File "' + filename + '", line ' + `lineno` + ', in ' + func
else:
tbline = 'File "' + filename + '", line ' + `lineno` + ', in ' + func
if line:
tbline = tbline + '\r ' + line
self.textlist.append(tbline[:255])
def edit(self):
sel = self.w.list.getselection()
for i in sel:
filename, lineno, func, line = self.tblist[i]
W.getapplication().openscript(filename, lineno)
def browselocals(self):
sel = self.w.list.getselection()
for i in sel:
tb = self.tb
for j in range(i + self.start):
tb = tb.tb_next
self.browse(tb.tb_frame.f_locals)
def browse(self, object):
import PyBrowser
PyBrowser.Browser(object)
def postmortem(self):
import PyDebugger
PyDebugger.postmortem(self.type, self.value, self.tb)
def listhit(self, isdbl):
if isdbl:
self.w.editbutton.push()
else:
self.checkbuttons()
def checkbuttons(self):
havefile = len(self.w.list.getselection()) > 0
self.w.editbutton.enable(havefile)
self.w.browselocalsbutton.enable(havefile)
self.w.setdefaultbutton(havefile and self.w.editbutton or self.w.postmortembutton)

611
Mac/Tools/IDE/Wwindows.py Normal file
View File

@ -0,0 +1,611 @@
import Qd
import Win
import Evt
import Fm
import FrameWork
import Windows
import Events
import Wbase
import Dlg
import MacOS
import Menu
import struct
import traceback
from types import *
class Window(FrameWork.Window, Wbase.SelectableWidget):
windowkind = Windows.documentProc
def __init__(self, possize, title = "", minsize = None, maxsize = None, tabbable = 1, show = 1):
import W
W.SelectableWidget.__init__(self, possize)
self._globalbounds = l, t, r, b = self.getwindowbounds(possize, minsize)
self._bounds = (0, 0, r - l, b - t)
self._tabchain = []
self._currentwidget = None
self.title = title
self._parentwindow = self
self._tabbable = tabbable
self._defaultbutton = None
self._drawwidgetbounds = 0
self._show = show
self._lastrollover = None
# XXX the following is not really compatible with the
# new (system >= 7.5) window procs.
if minsize:
self._hasgrowbox = 1
self.windowkind = self.windowkind | 8
l, t = minsize
if maxsize:
r, b = maxsize[0] + 1, maxsize[1] + 1
else:
r, b = 32000, 32000
self.growlimit = (l, t, r, b)
else:
self._hasgrowbox = 0
if (self.windowkind == 0 or self.windowkind >= 8) and self.windowkind < 1000:
self.windowkind = self.windowkind | 4
FrameWork.Window.__init__(self, W.getapplication())
def gettitle(self):
return self.title
def settitle(self, title):
self.title = title
if self.wid:
self.wid.SetWTitle(title)
def getwindowbounds(self, size, minsize = None):
return windowbounds(size, minsize)
def getcurrentwidget(self):
return self._currentwidget
def show(self, onoff):
if onoff:
self.wid.ShowWindow()
else:
self.wid.HideWindow()
def isvisible(self):
return self.wid.IsWindowVisible()
def getbounds(self):
if 0: #self.isvisible():
self.wid.GetWindowContentRgn(scratchRegion)
self._globalbounds = GetRgnBounds(scratchRegion)
return self._globalbounds
def select(self):
self.wid.SelectWindow()
# not sure if this is the best place, I need it when
# an editor gets selected, and immediately scrolled
# to a certain line, waste scroll assumes everything
# to be in tact.
self.do_rawupdate(self.wid, "DummyEvent")
def open(self):
self.wid = Win.NewCWindow(self._globalbounds, self.title, self._show,
self.windowkind, -1, 1, 0)
self.SetPort()
fnum = Fm.GetFNum("Python-Sans")
if fnum == 0:
fnum = Fm.GetFNum("Geneva")
Qd.TextFont(fnum) # XXX font&size from a function?
Qd.TextSize(9) # XXX font&size from a function?
if self._bindings.has_key("<open>"):
callback = self._bindings["<open>"]
callback()
for w in self._widgets:
w.forall_frombottom("open")
self._maketabchain()
if self._tabchain:
self._tabchain[0].select(1)
if self._tabbable:
self.bind('tab', self.nextwidget)
self.bind('shifttab', self.previouswidget)
self.do_postopen()
def close(self):
if not self.wid:
return # we are already closed
if self._bindings.has_key("<close>"):
callback = self._bindings["<close>"]
try:
rv = callback()
except:
print 'error in <close> callback'
traceback.print_exc()
else:
if rv:
return rv
#for key in self._widgetsdict.keys():
# self._removewidget(key)
self.forall_butself("close")
Wbase.SelectableWidget.close(self)
self._tabchain = []
self._currentwidget = None
self.wid.HideWindow()
self.do_postclose()
def domenu_close(self, *args):
self.close()
def move(self, x, y = None):
"""absolute move"""
if y == None:
x, y = x
self.wid.MoveWindow(x, y, 0)
def resize(self, x, y = None):
if y == None:
x, y = x
if self._hasgrowbox:
self.SetPort()
Win.InvalRect(self.getgrowrect())
self.wid.SizeWindow(x, y, 1)
self._calcbounds()
def test(self, point):
return 1
def draw(self, visRgn = None):
if self._hasgrowbox:
self.tempcliprect(self.getgrowrect())
self.wid.DrawGrowIcon()
self.restoreclip()
def idle(self, *args):
self.SetPort()
point = Evt.GetMouse()
widget = self.findwidget(point, 0)
if self._bindings.has_key("<idle>"):
callback = self._bindings["<idle>"]
if callback():
return
if self._currentwidget is not None and hasattr(self._currentwidget, "idle"):
if self._currentwidget._bindings.has_key("<idle>"):
callback = self._currentwidget._bindings["<idle>"]
if callback():
return
if self._currentwidget.idle():
return
if widget is not None and hasattr(widget, "rollover"):
if 1: #self._lastrollover <> widget:
if self._lastrollover:
self._lastrollover.rollover(point, 0)
self._lastrollover = widget
self._lastrollover.rollover(point, 1)
else:
if self._lastrollover:
self._lastrollover.rollover(point, 0)
self._lastrollover = None
Wbase.SetCursor("arrow")
def xxx___select(self, widget):
if self._currentwidget == widget:
return
if self._bindings.has_key("<select>"):
callback = self._bindings["<select>"]
if callback(widget):
return
if widget is None:
if self._currentwidget is not None:
self._currentwidget.select(0)
elif type(widget) == InstanceType and widget._selectable:
widget.select(1)
elif widget == -1 or widget == 1:
if len(self._tabchain) <= 1:
return
temp = self._tabchain[(self._tabchain.index(self._currentwidget) + widget) % len(self._tabchain)]
temp.select(1)
else:
raise TypeError, "Widget is not selectable"
def setdefaultbutton(self, newdefaultbutton = None, *keys):
if newdefaultbutton == self._defaultbutton:
return
if self._defaultbutton:
self._defaultbutton._setdefault(0)
if not newdefaultbutton:
self.bind("return", None)
self.bind("enter", None)
return
import Wcontrols
if not isinstance(newdefaultbutton, Wcontrols.Button):
raise TypeError, "widget is not a button"
self._defaultbutton = newdefaultbutton
self._defaultbutton._setdefault(1)
if not keys:
self.bind("return", self._defaultbutton.push)
self.bind("enter", self._defaultbutton.push)
else:
for key in keys:
self.bind(key, self._defaultbutton.push)
def nextwidget(self):
self.xxx___select(1)
def previouswidget(self):
self.xxx___select(-1)
def drawwidgetbounds(self, onoff):
self._drawwidgetbounds = onoff
self.SetPort()
Win.InvalRect(self._bounds)
def _drawbounds(self):
pass
def _maketabchain(self):
# XXX This has to change, it's no good when we are adding or deleting widgets.
# XXX Perhaps we shouldn't keep a "tabchain" at all.
self._hasselframes = 0
self._collectselectablewidgets(self._widgets)
if self._hasselframes and len(self._tabchain) > 1:
self._hasselframes = 1
else:
self._hasselframes = 0
def _collectselectablewidgets(self, widgets):
import W
for w in widgets:
if w._selectable:
self._tabchain.append(w)
if isinstance(w, W.List):
self._hasselframes = 1
self._collectselectablewidgets(w._widgets)
def _calcbounds(self):
self._possize = self.wid.GetWindowPort().portRect[2:]
w, h = self._possize
self._bounds = (0, 0, w, h)
self.wid.GetWindowContentRgn(scratchRegion)
l, t, r, b = GetRgnBounds(scratchRegion)
self._globalbounds = l, t, l + w, t + h
for w in self._widgets:
w._calcbounds()
# FrameWork override methods
def do_inDrag(self, partcode, window, event):
where = event[3]
self.wid.GetWindowContentRgn(scratchRegion)
was_l, was_t, r, b = GetRgnBounds(scratchRegion)
window.DragWindow(where, self.draglimit)
self.wid.GetWindowContentRgn(scratchRegion)
is_l, is_t, r, b = GetRgnBounds(scratchRegion)
self._globalbounds = Qd.OffsetRect(self._globalbounds,
is_l - was_l, is_t - was_t)
def do_char(self, char, event):
import Wkeys
(what, message, when, where, modifiers) = event
key = char
if Wkeys.keynames.has_key(key):
key = Wkeys.keynames[char]
if modifiers & Events.shiftKey:
key = 'shift' + key
if modifiers & Events.cmdKey:
key = 'cmd' + key
if modifiers & Events.controlKey:
key = 'control' + key
if self._bindings.has_key("<key>"):
callback = self._bindings["<key>"]
if Wbase.CallbackCall(callback, 0, char, event):
return
if self._bindings.has_key(key):
callback = self._bindings[key]
Wbase.CallbackCall(callback, 0, char, event)
elif self._currentwidget is not None:
if self._currentwidget._bindings.has_key(key):
callback = self._currentwidget._bindings[key]
Wbase.CallbackCall(callback, 0, char, event)
else:
if self._currentwidget._bindings.has_key("<key>"):
callback = self._currentwidget._bindings["<key>"]
if Wbase.CallbackCall(callback, 0, char, event):
return
self._currentwidget.key(char, event)
def do_contentclick(self, point, modifiers, event):
widget = self.findwidget(point)
if widget is not None:
if self._bindings.has_key("<click>"):
callback = self._bindings["<click>"]
if Wbase.CallbackCall(callback, 0, point, modifiers):
return
if widget._bindings.has_key("<click>"):
callback = widget._bindings["<click>"]
if Wbase.CallbackCall(callback, 0, point, modifiers):
return
if widget._selectable:
widget.select(1, 1)
widget.click(point, modifiers)
def do_update(self, window, event):
Qd.EraseRgn(window.GetWindowPort().visRgn)
self.forall_frombottom("draw", window.GetWindowPort().visRgn)
if self._drawwidgetbounds:
self.forall_frombottom("_drawbounds")
def do_activate(self, onoff, event):
if not onoff:
if self._lastrollover:
self._lastrollover.rollover((0, 0), 0)
self._lastrollover = None
self.SetPort()
self.forall("activate", onoff)
self.draw()
def do_postresize(self, width, height, window):
Win.InvalRect(self.getgrowrect())
self._calcbounds()
def do_inGoAway(self, partcode, window, event):
where = event[3]
closeall = event[4] & Events.optionKey
if window.TrackGoAway(where):
if not closeall:
self.close()
else:
for window in self.parent._windows.values():
rv = window.close()
if rv and rv > 0:
return
# utilities
def tempcliprect(self, tempcliprect):
tempclip = Qd.NewRgn()
Qd.RectRgn(tempclip, tempcliprect)
self.tempclip(tempclip)
Qd.DisposeRgn(tempclip)
def tempclip(self, tempclip):
if not hasattr(self, "saveclip"):
self.saveclip = []
saveclip = Qd.NewRgn()
Qd.GetClip(saveclip)
self.saveclip.append(saveclip)
Qd.SetClip(tempclip)
def restoreclip(self):
Qd.SetClip(self.saveclip[-1])
Qd.DisposeRgn(self.saveclip[-1])
del self.saveclip[-1]
def getgrowrect(self):
l, t, r, b = self.wid.GetWindowPort().portRect
return (r - 15, b - 15, r, b)
def has_key(self, key):
return self._widgetsdict.has_key(key)
def __getattr__(self, attr):
global _successcount, _failcount, _magiccount
if self._widgetsdict.has_key(attr):
_successcount = _successcount + 1
return self._widgetsdict[attr]
if self._currentwidget is None or (attr[:7] <> 'domenu_' and
attr[:4] <> 'can_' and attr <> 'insert'):
_failcount = _failcount + 1
raise AttributeError, attr
# special case: if a domenu_xxx, can_xxx or insert method is asked for,
# see if the active widget supports it
_magiccount = _magiccount + 1
return getattr(self._currentwidget, attr)
_successcount = 0
_failcount = 0
_magiccount = 0
class Dialog(Window):
windowkind = Windows.movableDBoxProc
# this __init__ seems redundant, but it's not: it has less args
def __init__(self, possize, title = ""):
Window.__init__(self, possize, title)
def can_close(self, *args):
return 0
def getwindowbounds(self, size, minsize = None):
screenbounds = sl, st, sr, sb = Qd.qd.screenBits.bounds
w, h = size
l = sl + (sr - sl - w) / 2
t = st + (sb - st - h) / 3
return l, t, l + w, t + h
class ModalDialog(Dialog):
def __init__(self, possize, title = ""):
Dialog.__init__(self, possize, title)
if title:
self.windowkind = Windows.movableDBoxProc
else:
self.windowkind = Windows.dBoxProc
def open(self):
import W
Dialog.open(self)
self.app = W.getapplication()
self.done = 0
Menu.HiliteMenu(0)
app = self.parent
app.enablemenubar(0)
try:
self.mainloop()
finally:
app.enablemenubar(1)
def close(self):
if not self.wid:
return # we are already closed
self.done = 1
del self.app
Dialog.close(self)
def mainloop(self):
saveyield = MacOS.EnableAppswitch(-1)
while not self.done:
#self.do1event()
self.do1event( Events.keyDownMask +
Events.autoKeyMask +
Events.activMask +
Events.updateMask +
Events.mDownMask +
Events.mUpMask,
10)
MacOS.EnableAppswitch(saveyield)
def do1event(self, mask = Events.everyEvent, wait = 0):
ok, event = self.app.getevent(mask, wait)
if Dlg.IsDialogEvent(event):
if self.app.do_dialogevent(event):
return
if ok:
self.dispatch(event)
else:
self.app.idle(event)
def do_keyDown(self, event):
self.do_key(event)
def do_autoKey(self, event):
if not event[-1] & Events.cmdKey:
self.do_key(event)
def do_key(self, event):
(what, message, when, where, modifiers) = event
w = Win.FrontWindow()
if w <> self.wid:
return
c = chr(message & Events.charCodeMask)
if modifiers & Events.cmdKey:
self.app.checkmenus(self)
result = Menu.MenuKey(ord(c))
id = (result>>16) & 0xffff # Hi word
item = result & 0xffff # Lo word
if id:
self.app.do_rawmenu(id, item, None, event)
return
self.do_char(c, event)
def do_mouseDown(self, event):
(what, message, when, where, modifiers) = event
partcode, wid = Win.FindWindow(where)
#
# Find the correct name.
#
if FrameWork.partname.has_key(partcode):
name = "do_" + FrameWork.partname[partcode]
else:
name = "do_%d" % partcode
if name == "do_inDesk":
MacOS.HandleEvent(event)
return
if wid == self.wid:
try:
handler = getattr(self, name)
except AttributeError:
handler = self.app.do_unknownpartcode
else:
#MacOS.HandleEvent(event)
if name == 'do_inMenuBar':
handler = getattr(self.parent, name)
else:
return
handler(partcode, wid, event)
def dispatch(self, event):
(what, message, when, where, modifiers) = event
if FrameWork.eventname.has_key(what):
name = "do_" + FrameWork.eventname[what]
else:
name = "do_%d" % what
try:
handler = getattr(self, name)
except AttributeError:
try:
handler = getattr(self.app, name)
except AttributeError:
handler = self.app.do_unknownevent
handler(event)
def FrontWindowInsert(stuff):
if not stuff:
return
if type(stuff) <> StringType:
raise TypeError, 'string expected'
import W
app = W.getapplication()
wid = Win.FrontWindow()
if wid and app._windows.has_key(wid):
window = app._windows[wid]
if hasattr(window, "insert"):
try:
window.insert(stuff)
return
except:
pass
import EasyDialogs
if EasyDialogs.AskYesNoCancel(
"CanÕt find window or widget to insert text into; copy to clipboard instead?",
1) == 1:
import Scrap
Scrap.ZeroScrap()
Scrap.PutScrap('TEXT', stuff)
# not quite based on the same function in FrameWork
_windowcounter = 0
def getnextwindowpos():
global _windowcounter
rows = 8
l = 4 * (rows + 1 - (_windowcounter % rows) + _windowcounter / rows)
t = 44 + 20 * (_windowcounter % rows)
_windowcounter = _windowcounter + 1
return l, t
def windowbounds(preferredsize, minsize = None):
"Return sensible window bounds"
global _windowcounter
if len(preferredsize) == 4:
bounds = l, t, r, b = preferredsize
union = Qd.UnionRect(bounds, Qd.qd.screenBits.bounds)
if union == Qd.qd.screenBits.bounds:
return bounds
else:
preferredsize = r - l, b - t
if not minsize:
minsize = preferredsize
minwidth, minheight = minsize
width, height = preferredsize
sl, st, sr, sb = screenbounds = Qd.InsetRect(Qd.qd.screenBits.bounds, 4, 4)
l, t = getnextwindowpos()
if (l + width) > sr:
_windowcounter = 0
l, t = getnextwindowpos()
r = l + width
b = t + height
if (t + height) > sb:
b = sb
if (b - t) < minheight:
b = t + minheight
return l, t, r, b
scratchRegion = Qd.NewRgn()
# util -- move somewhere convenient???
def GetRgnBounds(the_Rgn):
(t, l, b, r) = struct.unpack("hhhh", the_Rgn.data[2:10])
return (l, t, r, b)