summaryrefslogtreecommitdiffstats
path: root/Lib/lib-stdwin/srcwin.py
blob: a71c568ace9031b4030fa8e912fd7921ef095eb4 (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
# srcwin.py -- a source listing window

import stdwin
from stdwinevents import *
import basewin

WIDTH = 40
MAXHEIGHT = 24


class TextWindow(basewin.BaseWindow):
	
	def init(self, title, contents):
		self.contents = contents
		self.linecount = countlines(self.contents)
		#
		self.lineheight = lh = stdwin.lineheight()
		self.leftmargin = self.getmargin()
		self.top = 0
		self.rightmargin = 30000 # Infinity
		self.bottom = lh * self.linecount
		#
		width = WIDTH*stdwin.textwidth('0')
		height = lh*min(MAXHEIGHT, self.linecount)
		stdwin.setdefwinsize(width, height)
		self = basewin.BaseWindow.init(self, title)
		#
		self.win.setdocsize(0, self.bottom)
		self.initeditor()
		return self
	
	def initeditor(self):
		r = (self.leftmargin, self.top), (self.rightmargin, self.bottom)
		self.editor = self.win.textcreate(r)
		self.editor.settext(self.contents)
	
	def closeeditor(self):
		self.editor.close()
	
#	def reopen(self):
#		self.closeeditor()
#		basewin.BaseWindow.reopen(self)
#		self.initeditor()
	
	# Override the following two methods to format line numbers differently
	
	def getmark(self, lineno):
		return `lineno`
	
	def getmargin(self):
		return stdwin.textwidth(`self.linecount + 1` + ' ')
	
	# Event dispatcher, called from mainloop.mainloop()
	
	def dispatch(self, event):
		if event[0] == WE_NULL: return # Dummy tested by mainloop
		if event[0] == WE_DRAW or not self.editor.event(event):
			basewin.BaseWindow.dispatch(self, event)
	
	# Event handlers
	
	def close(self):
		self.closeeditor()
		basewin.BaseWindow.close(self)
	
	def draw(self, detail):
		dummy = self.editor.draw(detail)
		# Draw line numbers
		(left, top), (right, bottom) = detail
		topline = top/self.lineheight
		botline = bottom/self.lineheight + 1
		botline = min(self.linecount, botline)
		d = self.win.begindrawing()
		try:
			h, v = 0, self.lineheight * topline
			for lineno in range(topline+1, botline+1):
				d.text((h, v), self.getmark(lineno))
				v = v + self.lineheight
		finally:
			d.close()
	
	# Calls from outside
	
	def changemark(self, lineno): # redraw the mark for a line
		left = 0
		top = (lineno-1) * self.lineheight
		right = self.leftmargin
		bottom = lineno * self.lineheight
		d = self.win.begindrawing()
		try:
			d.erase((left, top), (right, bottom))
			d.text((left, top), self.getmark(lineno))
		finally:
			d.close()

	def showline(self, lineno): # scroll to make a line visible
		left = 0
		top = (lineno-1) * self.lineheight
		right = self.leftmargin
		bottom = lineno * self.lineheight
		self.win.show((left, top), (right, bottom))


# Subroutine to count the number of lines in a string

def countlines(text):
	n = 0
	for c in text:
		if c == '\n': n = n+1
	if text and text[-1] != '\n': n = n+1 # Partial last line
	return n


class SourceWindow(TextWindow):

	def init(self, filename):
		self.filename = filename
		f = open(self.filename, 'r')
		contents = f.read()
		f.close()
		return TextWindow.init(self, self.filename, contents)

# ------------------------------ testing ------------------------------

TESTFILE = 'srcwin.py'

def test():
	import mainloop
	sw = SourceWindow().init(TESTFILE)
	mainloop.mainloop()