summaryrefslogtreecommitdiffstats
path: root/Lib/lib-stdwin/wdbframewin.py
blob: 13bd1731a9cac03fab164588cb10defbe547606a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# wdbframewin.py -- frame window for wdb.py

# XXX To do:
# - display function name in window title
# - execute arbitrary statements instead of just evaluating expressions
# - allow setting variables by editing their values


import stdwin
from stdwinevents import *
import basewin
import sys

WIDTH = 40
MINHEIGHT = 8
MAXHEIGHT = 16

class FrameWindow(basewin.BaseWindow):

	def __init__(self, debugger, frame, dict, name):
		self.debugger = debugger
		self.frame = frame # Not used except for identity tests
		self.dict = dict
		self.name = name
		nl = max(MINHEIGHT, len(self.dict) + 5)
		nl = min(nl, MAXHEIGHT)
		width = WIDTH*stdwin.textwidth('0')
		height = nl*stdwin.lineheight()
		stdwin.setdefwinsize(width, height)
		basewin.BaseWindow.__init__(
			  self, '--Frame ' + name + '--')
		# XXX Should use current function name
		self.initeditor()
		self.displaylist = ['>>>', '', '-'*WIDTH]
		self.refreshframe()
	
	def initeditor(self):
		r = (stdwin.textwidth('>>> '), 0), (30000, stdwin.lineheight())
		self.editor = self.win.textcreate(r)
	
	def closeeditor(self):
		self.editor.close()
	
	def dispatch(self, event):
		type, win, detail = event
		if type == WE_NULL: return # Dummy tested by mainloop
		if type in (WE_DRAW, WE_COMMAND) \
				or not self.editor.event(event):
			basewin.BaseWindow.dispatch(self, event)
	
	def close(self):
		del self.debugger.framewindows[self.name]
		del self.debugger, self.dict
		self.closeeditor()
		basewin.BaseWindow.close(self)
	
	def command(self, detail):
		if detail == WC_RETURN:
			self.re_eval()
		else:
			dummy = self.editor.event(WE_COMMAND, \
						self.win, detail)
	
	def mouse_down(self, detail):
		(h, v), clicks, button, mask = detail
		if clicks != 2:
			return
		i = v / stdwin.lineheight()
		if 5 <= i < len(self.displaylist):
			import string
			name = string.splitfields(self.displaylist[i],' = ')[0]
			if not self.dict.has_key(name):
				stdwin.fleep()
				return
			value = self.dict[name]
			if not hasattr(value, '__dict__'):
				stdwin.fleep()
				return
			name = 'instance ' + `value`
			if self.debugger.framewindows.has_key(name):
				self.debugger.framewindows[name].popup()
			else:
				self.debugger.framewindows[name] = \
					  FrameWindow(self.debugger,
						  self.frame, value.__dict__,
						  name)
			return
		stdwin.fleep()

	def re_eval(self):
		import string, repr
		expr = string.strip(self.editor.gettext())
		if expr == '':
			output = ''
		else:
			globals = self.frame.f_globals
			globals['__privileged__'] = 1
			locals = self.dict
			try:
				value = eval(expr, globals, locals)
				output = repr.repr(value)
			except:
				output = sys.exc_type + ': ' + `sys.exc_value`
		self.displaylist[1] = output
		lh = stdwin.lineheight()
		r = (-10, 0), (30000, 2*lh)
		self.win.change(r)
		self.editor.setfocus(0, len(expr))
	
	def draw(self, detail):
		(left, top), (right, bottom) = detail
		dummy = self.editor.draw(detail)
		d = self.win.begindrawing()
		try:
			lh = d.lineheight()
			h, v = 0, 0
			for line in self.displaylist:
				if v+lh > top and v < bottom:
					d.text((h, v), line)
				v = v + lh
		finally:
			d.close()
	
	def refreshframe(self):
		import repr
		del self.displaylist[3:]
		self.re_eval()
		names = self.dict.keys()
		for key, label in ('__args__', 'Args: '), \
				  ('__return__', 'Return: '):
			if self.dict.has_key(key):
				names.remove(key)
				value = self.dict[key]
				label = label + repr.repr(value)
			self.displaylist.append(label)
		names.sort()
		for name in names:
			value = self.dict[name]
			line = name + ' = ' + repr.repr(value)
			self.displaylist.append(line)
		self.win.setdocsize(0, \
			stdwin.lineheight() * len(self.displaylist))
		self.refreshall() # XXX Be more subtle later