First Checked In.
This commit is contained in:
parent
f59a89b5e3
commit
40f9b7bd7c
|
@ -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)
|
|
@ -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)))
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
|
@ -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)
|
||||
|
|
@ -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)
|
|
@ -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
|
|
@ -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())
|
File diff suppressed because it is too large
Load Diff
|
@ -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]`
|
|
@ -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
|
|
@ -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.
|
@ -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()
|
||||
|
|
@ -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()
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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])
|
|
@ -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)
|
||||
|
Binary file not shown.
|
@ -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
|
|
@ -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()
|
||||
|
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
@ -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)
|
Loading…
Reference in New Issue