| # 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) |
| basewin.BaseWindow.__init__(self, title) |
| # |
| self.win.setdocsize(0, self.bottom) |
| self.initeditor() |
| |
| 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() |
| TextWindow.__init__(self, self.filename, contents) |
| |
| # ------------------------------ testing ------------------------------ |
| |
| TESTFILE = 'srcwin.py' |
| |
| def test(): |
| import mainloop |
| sw = SourceWindow(TESTFILE) |
| mainloop.mainloop() |