Kaydet (Commit) a1560cfb authored tarafından Jack Jansen's avatar Jack Jansen

- Simplified inheritance structure (still not good enough)

- Added menubar in stead of buttons
- (optionally) switch menubar back and forth to facilitate debugging
  FrameWork applications
- Handle "Open Document" appleevent
- Fixed click in grow-box location
- Allow a new debug session after previous one has finished
üst b1667ef7
......@@ -3,6 +3,7 @@ import sys
import types
import bdb
import types
import os
SIMPLE_TYPES=(
types.NoneType,
......@@ -20,9 +21,6 @@ ICON_CALL=516
ICON_ZERO=517
ICON_DEAD=518
def Initialize():
pass
class DebuggerStuff(bdb.Bdb):
def __init__(self, parent):
......@@ -38,15 +36,19 @@ class DebuggerStuff(bdb.Bdb):
self.forget()
def forget(self):
print 'FORGET'
self.lineno = None
self.stack = []
self.curindex = 0
self.curframe = None
def run(self, cmd, locals, globals):
self.reason = 'Running'
bdb.Bdb.run(self, cmd, locals, globals)
print 'RETURN from run'
self.reason = 'Not running'
def setup(self, f, t):
self.forget()
print 'SETUP', f, t
self.stack, self.curindex = self.get_stack(f, t)
self.curframe = self.stack[self.curindex][0]
......@@ -55,10 +57,10 @@ class DebuggerStuff(bdb.Bdb):
self.parent.interact()
self.exception_info = (None, None)
def user_call(self, frame, argument_list):
self.reason = 'Calling'
self.icon = ICON_CALL
self.interaction(frame, None)
# def user_call(self, frame, argument_list):
# self.reason = 'Calling'
# self.icon = ICON_CALL
# self.interaction(frame, None)
def user_line(self, frame):
self.reason = 'Stopped'
......@@ -73,6 +75,7 @@ class DebuggerStuff(bdb.Bdb):
def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
self.reason = 'Exception occurred'
self.icon = ICON_DEAD
self.parent.setstate('tb')
self.exception_info = (exc_type, exc_value)
self.interaction(frame, exc_traceback)
......@@ -85,7 +88,6 @@ class DebuggerStuff(bdb.Bdb):
return tp, value
def getstacktrace(self):
print 'DBG GETSTACKTRACE', self.stack
names, locations = [], []
for frame, lineno in self.stack:
name = frame.f_code.co_name
......@@ -104,7 +106,6 @@ class DebuggerStuff(bdb.Bdb):
if not modname: modname = "<unknown>"
locations.append("%s:%d" % (modname, lineno))
print 'DBG RETURNS', names, locations
return names, locations
def getframe(self, number):
......@@ -138,35 +139,41 @@ class DebuggerStuff(bdb.Bdb):
class Application:
"""Base code for the application"""
def mi_init(self, run_args, pm_args):
def mi_init(self, sessiontype, arg):
self.dbg = DebuggerStuff(self)
self.run_dialog = self.new_stack_browser(self)
self.run_dialog.open()
self.module_dialog = None
self.initial_cmd = None
self.cur_string_name = None
if pm_args:
while pm_args.tb_next <> None:
pm_args = pm_args.tb_next
self.dbg.setup(pm_args.tb_frame, pm_args)
self.run_dialog.setsession_pm()
self.run_dialog.update_views()
elif run_args:
self.run_dialog.setsession_run()
self.initial_cmd = run_args
else:
self.run_dialog.setsession_none()
if sessiontype == 'tb':
while arg.tb_next <> None:
arg = arg.tb_next
self.dbg.setup(arg.tb_frame, arg)
self.run_dialog.setup()
elif sessiontype == 'run':
self.initial_cmd = arg
def breaks_changed(self, filename):
self.run_dialog.breaks_changed(filename)
if self.module_dialog:
self.module_dialog.breaks_changed(filename)
def to_debugger(self):
apply(self.dbg.run, self.initial_cmd)
cmd = self.initial_cmd
self.initial_cmd = None
self.setstate('run')
self.switch_to_app()
apply(self.dbg.run, cmd)
self.setstate('none')
self.switch_to_dbg()
self.run_dialog.update_views()
if self.module_dialog:
self.module_dialog.update_views()
def interact(self):
# Interact with user. First, display correct info
self.switch_to_dbg()
self.run_dialog.update_views()
if self.module_dialog:
self.module_dialog.update_views()
......@@ -175,21 +182,35 @@ class Application:
self.one_mainloop()
# Finally (before we start the debuggee again) show state
self.switch_to_app()
self.run_dialog.show_it_running()
def quit_bdb(self):
self.dbg.set_quit()
def run(self):
cmd = AskString('Statement to execute:')
cmd = self.AskString('Statement to execute:')
self.runstring(cmd)
def runfile(self, path):
dir, file = os.path.split(path)
try:
os.chdir(dir)
except os.error, arg:
self.Message("%s: %s"%(dir, arg))
return
ns = {'__name__':'__main__', '__file__':path}
cmd = "execfile('%s')"%file
self.runstring(cmd, ns, ns)
def runstring(self, cmd, globals={}, locals={}):
self.cur_string_name = '<string: "%s">'%cmd
try:
cmd = compile(cmd, self.cur_string_name, 'exec')
except SyntaxError, arg:
ShowMessage('Syntax error: %s'%`arg`)
self.Message('Syntax error: %s'%`arg`)
return
self.initial_cmd = (cmd, None, None)
self.run_dialog.setsession_run()
self.initial_cmd = (cmd, globals, locals)
self.exit_mainloop()
def cont(self):
......@@ -208,6 +229,10 @@ class Application:
self.dbg.set_return(frame)
self.exit_mainloop()
def kill(self):
self.dbg.set_quit()
self.exit_mainloop()
def quit(self):
self.do_quit()
......@@ -237,7 +262,7 @@ class StackBrowser:
# create_items(self) should create self.modules, self.vars and self.source
def setup(self):
SetWatch()
self.parent.SetWatch()
"""Fill the various widgets with values"""
name, value = self.parent.dbg.getexception()
self.setexception(name, value)
......@@ -251,7 +276,7 @@ class StackBrowser:
def setup_frame(self):
"""Setup frame-dependent widget data"""
SetWatch()
self.parent.SetWatch()
self.cont_varnames, self.cont_varvalues = \
self.parent.dbg.getframevars(self.cur_stackitem,
self.show_complex, self.show_system)
......@@ -276,8 +301,6 @@ class StackBrowser:
self.cur_source[:8] == '<string:':
msg = "Executing from "+self.cur_source
self.cur_source = None
print 'SOURCE', self.cur_source
print 'LINE', self.cur_line
self.setsource(msg)
if not self.cur_line:
......@@ -287,7 +310,7 @@ class StackBrowser:
self.breaks_changed(self.cur_source)
SetCursor()
self.parent.SetCursor()
# setsource(msg) should display cur_source+content, or msg if None
......@@ -349,6 +372,9 @@ class StackBrowser:
self.parent.step_out(frame)
else:
self.parent.step_in()
def click_kill(self):
self.parent.kill()
def click_browse(self):
self.parent.browse(self.cur_modname)
......@@ -377,7 +403,7 @@ class ModuleBrowser:
def setup(self):
"""Fill the various widgets with values"""
SetWatch()
self.parent.SetWatch()
modnames = getmodulenames()
if not self.cur_module in modnames:
self.cur_module = None
......@@ -392,7 +418,7 @@ class ModuleBrowser:
def setup_module(self):
"""Setup module-dependent widget data"""
SetWatch()
self.parent.SetWatch()
if not self.cur_module:
self.vars.setcontent([], [])
else:
......@@ -415,7 +441,7 @@ class ModuleBrowser:
self.source.select(self.cur_line)
self.breaks_changed(self.cur_source)
SetCursor()
self.parent.SetCursor()
# setsource(msg) should display cur_source+content, or msg if None
......
......@@ -14,6 +14,9 @@ MARGIN=2
ICONSIZE=16
TEXTWIDTH=4096 # More-or-less random value
TEXTFONT=4
TEXTSIZE=9
PIC_BREAK=513
picture_cache={}
......@@ -26,8 +29,8 @@ class MT_TextWidget:
right-(MARGIN+SCROLLBAR), bottom-(MARGIN+SCROLLBAR)
dr = self.terect[0], self.terect[1], TEXTWIDTH, self.terect[3]
Qd.SetPort(wid)
Qd.TextFont(4)
Qd.TextSize(9)
Qd.TextFont(TEXTFONT)
Qd.TextSize(TEXTSIZE)
self.ted = TE.TENew(dr, self.terect)
self.ted.TEAutoView(1)
self.activate(1)
......@@ -130,7 +133,10 @@ class MT_TextWidget:
return None, 0
off = self.ted.TEGetOffset(where)
inborder = where[0] < self.terect[0]
return self.offsettoline(off), inborder
l, t, r, b = self.terect
if l <= where[0] <= r and t <= where[1] <= b or inborder:
return self.offsettoline(off), inborder
return None, 0 # In the grow box or something.
def offsettoline(self, offset):
for i in range(len(self.line_index)):
......@@ -233,7 +239,6 @@ class MT_IconTextWidget(MT_TextWidget):
rect = self.rect[0]+2, boty-self.ted.lineHeight, \
self.rect[0]+ICONSIZE-2, boty
if not picture_cache.has_key(which):
print 'Get picture', which
picture_cache[which] = Qd.GetPicture(which)
self.drawicon(rect, picture_cache[which])
......
import FrameWork
import MiniAEFrame
import EasyDialogs
import AE
import AppleEvents
import Res
import sys
import Qd
......@@ -7,6 +10,13 @@ import Evt
import Events
import Dlg
import Win
import Menu
import TwitCore
import mactwit_mod
import mactwit_stack
import mactwit_browser
import mactwit_edit
import macfs
# Resource-id (for checking existence)
ID_MODULES=512
......@@ -16,48 +26,92 @@ ID_ABOUT=515
_arrow = Qd.qd.arrow
_watch = Qd.GetCursor(4).data
# Made available to TwitCore:
AskString = EasyDialogs.AskString
ShowMessage = EasyDialogs.Message
def SetCursor():
Qd.SetCursor(_arrow)
def SetWatch():
Qd.SetCursor(_watch)
# Exception for temporarily exiting the loop and program
ExitMainloop = 'ExitMainloop'
ExitFully = 'ExitFully'
class Application(FrameWork.Application):
class Twit(FrameWork.Application, TwitCore.Application, MiniAEFrame.AEServer):
"""The twit main class - mac-dependent part"""
def __init__(self, run_args, pm_args):
def __init__(self, sessiontype, arg=None):
# First init menus, etc.
self.app_menu_bar = Menu.GetMenuBar()
FrameWork.Application.__init__(self)
MiniAEFrame.AEServer.__init__(self)
AE.AESetInteractionAllowed(AppleEvents.kAEInteractWithAll)
self.installaehandler('aevt', 'odoc', self.ae_open_doc)
self.installaehandler('aevt', 'quit', self.do_quit)
self.dbg_menu_bar = Menu.GetMenuBar()
self.setstate(sessiontype)
self._quitting = 0
self.real_quit = 0
self.window_aware = 1
# Next create our dialogs
self.mi_init(run_args, pm_args)
if self.real_quit:
return
if not run_args:
# Go into mainloop once
self.one_mainloop()
self.mi_init(sessiontype, arg)
while 1:
if self.real_quit:
return
break
if self.initial_cmd:
self.to_debugger() # Will get to mainloop via debugger
else:
self.one_mainloop() # Else do it ourselves.
def switch_to_app(self):
if not self.window_aware:
return
self.dbg_menu_bar = Menu.GetMenuBar()
Menu.SetMenuBar(self.app_menu_bar)
Menu.DrawMenuBar()
if not pm_args:
# And give the debugger control.
self.to_debugger()
def switch_to_dbg(self):
if not self.window_aware:
return
self.app_menu_bar = Menu.GetMenuBar()
Menu.SetMenuBar(self.dbg_menu_bar)
Menu.DrawMenuBar()
self.run_dialog.force_redraw()
if self.module_dialog:
self.module_dialog.force_redraw()
def makeusermenus(self):
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
self.filemenu = m = FrameWork.Menu(self.menubar, "Debug")
self._openitem = FrameWork.MenuItem(m, "Run File...", "O", self.do_open)
self._runitem = FrameWork.MenuItem(m, "Run String...", "R", self.do_run)
FrameWork.Separator(m)
self._awareitem = FrameWork.MenuItem(m, "Window-aware", "", self.do_aware)
self._awareitem.check(1)
FrameWork.Separator(m)
self._quititem = FrameWork.MenuItem(m, "Quit", "Q", self.do_quit)
self.controlmenu = m = FrameWork.Menu(self.menubar, "Control")
self._stepitem = FrameWork.MenuItem(m, "Step Next", "N", self.do_step)
self._stepinitem = FrameWork.MenuItem(m, "Step In", "S", self.do_stepin)
self._stepoutitem = FrameWork.MenuItem(m, "Step Out", "U", self.do_stepout)
self._continueitem = FrameWork.MenuItem(m, "Continue", "G", self.do_continue)
FrameWork.Separator(m)
self._killitem = FrameWork.MenuItem(m, "Kill", "K", self.do_kill)
def setstate(self, state):
self.state = state
if state == 'run':
self._stepitem.enable(1)
self._stepoutitem.enable(1)
self._stepinitem.enable(1)
self._continueitem.enable(1)
self._killitem.enable(1)
else:
self._stepitem.enable(0)
self._stepoutitem.enable(0)
self._stepinitem.enable(0)
self._continueitem.enable(0)
self._killitem.enable(0)
def asknewsession(self):
if self.state == 'none':
return 1
if EasyDialogs.AskYesNoCancel("Abort current debug session?") == 1:
self.quit_bdb()
return 1
return 0
def do_about(self, id, item, window, event):
import time
d = Dlg.GetNewDialog(ID_ABOUT, -1)
......@@ -102,12 +156,54 @@ class Application(FrameWork.Application):
while 1:
ok, evt = self.getevent(Events.mDownMask|Events.keyDownMask, -1)
if ok: return
def do_open(self, *args):
if not self.asknewsession():
return
fss, ok = macfs.StandardGetFile('TEXT')
if not ok: return
self.runfile(fss.as_pathname())
def ae_open_doc(self, object=None, **args):
if not object: return
if self.state <> 'none':
if AE.AEInteractWithUser(AppleEvents.kAEDefaultTimeout) == 0:
if not self.asknewsession():
return
if type(object) == type([]):
object = object[0]
fss, changed = object.Resolve()
self.runfile(fss.as_pathname())
def do_run(self, *args):
if not self.asknewsession():
return
self.run()
def do_aware(self, *args):
self.window_aware = not self.window_aware
self._awareitem.check(self.window_aware)
def do_quit(self, *args):
self._quit() # Signal FrameWork.Application to stop
self.real_quit = 1
self.quit_bdb() # Tell debugger to quit.
def do_step(self, *args):
self.run_dialog.click_step()
def do_stepin(self, *args):
self.run_dialog.click_step_in()
def do_stepout(self, *args):
self.run_dialog.click_step_out()
def do_continue(self, *args):
self.run_dialog.click_continue()
def do_kill(self, *args):
self.run_dialog.click_kill()
def exit_mainloop(self):
self._quit() # Signal FrameWork.Application to stop
self.real_quit = 0
......@@ -115,6 +211,31 @@ class Application(FrameWork.Application):
def one_mainloop(self):
self.quitting = 0
self.mainloop()
def SetCursor(self):
Qd.SetCursor(_arrow)
def SetWatch(self):
Qd.SetCursor(_watch)
def AskString(self, *args):
return apply(EasyDialogs.AskString, args)
def Message(self, *args):
return apply(EasyDialogs.Message, args)
def new_module_browser(self, parent):
return mactwit_mod.ModuleBrowser(parent)
def new_stack_browser(self, parent):
return mactwit_stack.StackBrowser(parent)
def new_var_browser(self, parent, var):
return mactwit_browser.VarBrowser(parent).open(var)
def edit(self, file, line):
return mactwit_edit(file, line)
def Initialize():
try:
......
......@@ -6,6 +6,7 @@ import Win
import FrameWork
import EasyDialogs
import sys
import TwitCore
from mac_widgets import MT_AnyList, MT_IconTextWidget
# Our dialogs
......@@ -19,7 +20,7 @@ I_SOURCE=6
I_RULER=7
I_EDIT=8
class ModuleBrowser(FrameWork.DialogWindow):
class ModuleBrowser(FrameWork.DialogWindow, TwitCore.ModuleBrowser):
"""The module-browser dialog - mac-dependent part"""
def open(self, module):
FrameWork.DialogWindow.open(self, ID_MODULES)
......@@ -74,6 +75,10 @@ class ModuleBrowser(FrameWork.DialogWindow):
self.vars.update(rgn)
self.source.update(rgn)
def force_redraw(self):
Qd.SetPort(self.wid)
Win.InvalRgn(self.wid.GetWindowPort().visRgn)
def do_activate(self, activate, event):
self.modules.activate(activate)
self.vars.activate(activate)
......
......@@ -6,6 +6,7 @@ import Win
import FrameWork
import EasyDialogs
import sys
import TwitCore
from mac_widgets import MT_AnyList, MT_IndexList, MT_IconTextWidget
# Our dialogs
......@@ -20,22 +21,16 @@ I_EXC_TITLE=7
I_EXC=8
I_EXCVALUE_TITLE=9
I_EXCVALUE=10
I_QUIT=11
I_CONTINUE=12
I_STEP=13
I_BROWSE=14
I_RULER1=15
I_RULER2=16
I_STATE_TITLE=17
I_STATE=18
I_STEP_IN=19
I_STEP_OUT=20
I_RUN=21
I_SHOW_COMPLEX=22
I_SHOW_SYSTEM=23
I_EDIT=24
I_BROWSE=11
I_RULER1=12
I_RULER2=13
I_STATE_TITLE=14
I_STATE=15
I_SHOW_COMPLEX=16
I_SHOW_SYSTEM=17
I_EDIT=18
class StackBrowser(FrameWork.DialogWindow):
class StackBrowser(FrameWork.DialogWindow, TwitCore.StackBrowser):
"""The stack-browser dialog - mac-dependent part"""
def open(self):
FrameWork.DialogWindow.open(self, ID_STACK)
......@@ -62,7 +57,6 @@ class StackBrowser(FrameWork.DialogWindow):
self.source.setcontent(self.cur_source)
def setexception(self, name, value):
print 'SETEXC', (name, value)
if name == None:
self.wid.HideDialogItem(I_EXC)
self.wid.HideDialogItem(I_EXC_TITLE)
......@@ -85,46 +79,11 @@ class StackBrowser(FrameWork.DialogWindow):
tp, h, rect = self.wid.GetDialogItem(I_STATE)
Dlg.SetDialogItemText(h, msg)
def setsession_none(self):
"""Nothing running, no stack trace"""
self.wid.HideDialogItem(I_CONTINUE)
self.wid.HideDialogItem(I_STEP)
self.wid.HideDialogItem(I_STEP_IN)
self.wid.HideDialogItem(I_STEP_OUT)
self.wid.ShowDialogItem(I_RUN)
def setsession_run(self):
"""Running"""
self.wid.HideDialogItem(I_RUN)
self.wid.ShowDialogItem(I_CONTINUE)
self.wid.ShowDialogItem(I_STEP)
self.wid.ShowDialogItem(I_STEP_IN)
self.wid.ShowDialogItem(I_STEP_OUT)
def setsession_pm(self):
"""Post-mortem debugging"""
self.wid.HideDialogItem(I_CONTINUE)
self.wid.HideDialogItem(I_STEP)
self.wid.HideDialogItem(I_STEP_IN)
self.wid.HideDialogItem(I_STEP_OUT)
self.wid.HideDialogItem(I_RUN)
def setsession_none(self):
"""Nothing running, no stack trace"""
self.wid.HideDialogItem(I_CONTINUE)
self.wid.HideDialogItem(I_STEP)
self.wid.HideDialogItem(I_STEP_IN)
self.wid.HideDialogItem(I_STEP_OUT)
self.wid.ShowDialogItem(I_RUN)
def do_itemhit(self, item, event):
(what, message, when, where, modifiers) = event
Qd.SetPort(self.wid)
where = Qd.GlobalToLocal(where)
print 'STACKHIT', item
if item == I_STACK:
new_stackitem, double = self.stack.click(where, 0)
self.click_stack(new_stackitem)
......@@ -136,20 +95,8 @@ class StackBrowser(FrameWork.DialogWindow):
lineno, inborder = self.source.click(where, 0)
if lineno <> None and lineno >= 0:
self.click_source(lineno, inborder)
elif item == I_QUIT:
self.click_quit()
elif item == I_CONTINUE:
self.click_continue()
elif item == I_STEP:
self.click_step()
elif item == I_STEP_IN:
self.click_step_in()
elif item == I_STEP_OUT:
self.click_step_out()
elif item == I_BROWSE:
self.click_browse()
elif item == I_RUN:
self.click_run()
elif item == I_SHOW_COMPLEX:
self.show_complex = not self.show_complex
self.setup_frame()
......@@ -177,6 +124,10 @@ class StackBrowser(FrameWork.DialogWindow):
self.stack.update(rgn)
self.vars.update(rgn)
self.source.update(rgn)
def force_redraw(self):
Qd.SetPort(self.wid)
Win.InvalRgn(self.wid.GetWindowPort().visRgn)
def do_activate(self, activate, event):
self.stack.activate(activate)
......
......@@ -15,11 +15,7 @@ if os.name == 'mac':
# Not supported in distributed 1.4b3:
## import MacOS
## MacOS.splash(515) # Try to show the splash screen
import mactwit_mod; twit_mod = mactwit_mod
import mactwit_stack; twit_stack = mactwit_stack
import mactwit_app; twit_app = mactwit_app
import mactwit_browser; twit_browser = mactwit_browser
import mactwit_edit; twit_edit = mactwit_edit
else:
try:
import _tkinter
......@@ -27,65 +23,26 @@ else:
except ImportError:
have_tk = 0
if have_tk:
import tktwit_mod; twit_mod = tktwit_mod
import tktwit_stack; twit_stack = tktwit_stack
import tktwit_app; twit_app = tktwit_app
else:
print 'Please implementent twit_mod, twit_stack and twit_app and try again:-)'
print 'Please implementent machine-dependent code and try again:-)'
sys.exit(1)
import TwitCore
import sys
class Twit(twit_app.Application, TwitCore.Application):
def new_module_browser(self, *args):
return apply(TWIT_ModuleBrowser, args)
def new_stack_browser(self, *args):
return apply(TWIT_StackBrowser, args)
def new_var_browser(self, *args):
return apply(TWIT_VarBrowser, args)
def edit(self, *args):
return apply(twit_edit.edit, args)
class TWIT_ModuleBrowser(twit_mod.ModuleBrowser, TwitCore.ModuleBrowser):
pass
class TWIT_StackBrowser(twit_stack.StackBrowser, TwitCore.StackBrowser):
pass
def TWIT_VarBrowser(parent, var):
return twit_browser.VarBrowser(parent).open(var)
def Initialize():
# Gross...
TwitCore.AskString = twit_app.AskString
TwitCore.ShowMessage = twit_app.ShowMessage
TwitCore.SetWatch = twit_app.SetWatch
TwitCore.SetCursor = twit_app.SetCursor
def main():
twit_app.Initialize()
TwitCore.Initialize()
Initialize()
## if os.name == 'mac':
## MacOS.splash()
Twit(None, None)
twit_app.Twit('none', None)
def run(statement, globals=None, locals=None):
twit_app.Initialize()
TwitCore.Initialize()
Initialize()
Twit((statement, globals, locals), None)
twit_app.Twit('run', (statement, globals, locals))
def post_mortem(t):
twit_app.Initialize()
TwitCore.Initialize()
Initialize()
Twit(None, t)
twit_app.Twit('pm', t)
def pm():
post_mortem(sys.last_traceback)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment