#!/usr/bin/env python
#
# $Id: ScrolledST.py,v 1.3 2001/11/03 11:05:22 doughellmann Exp $
#
# Copyright 2001 Doug Hellmann.
#
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of Doug
# Hellmann not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
#
# DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
# NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
"""Scrolled StructuredText display widget.
The ScrolledStructuredText display widget uses the StructuredText.py
module from "Zope":http://www.zope.org to parse text and derive
layout and formatting instructions.
"""
__rcs_info__ = {
#
# Creation Information
#
'module_name' : '$RCSfile: ScrolledST.py,v $',
'rcs_id' : '$Id: ScrolledST.py,v 1.3 2001/11/03 11:05:22 doughellmann Exp $',
'creator' : 'Doug Hellmann <doug@hellfly.net>',
'project' : 'PmwContribD',
'created' : 'Sun, 27-May-2001 19:03:12 EDT',
#
# Current Information
#
'author' : '$Author: doughellmann $',
'version' : '$Revision: 1.3 $',
'date' : '$Date: 2001/11/03 11:05:22 $',
}
#
# Import system modules
#
from Tkinter import *
import Pmw
import re
import os
import tkFileDialog
#
# Import Local modules
#
from GuiAppD import GuiAppD
from StructuredText import StructuredText
import ts_regex
#
# Module
#
class TkStructuredText(StructuredText):
paraTypes = [
('bullet',
ts_regex.compile('[ \t\n]*[o*-][ \t\n]+\([^\0]*\)'
).match_group,
(1,)),
# ('example', ts_regex.compile('[\0- ]examples?:[\0- ]*$'
# ).search,
# None),
('descriptivelist',
ts_regex.compile('\([^\n]+\)[ \t]+--[ \t\n]+\([^\0]*\)'
).match_group,
(1,2)),
# ('nl', ts_regex.compile('\n').search,
# None),
('orderedlist',
ts_regex.compile('[ \t]*\(\([0-9]+\|[a-zA-Z]+\)[.)]\)+[ \t\n]+\([^\0]*\|$\)'
).match_group,
(3,)),
('olp',
ts_regex.compile('[ \t]*([0-9]+)[ \t\n]+\([^\0]*\|$\)'
).match_group,
(1,)),
('heading',
ts_regex.compile('[^\n]+\n').search,
None),
]
def getParaType(self, text):
for name, check, groups in self.paraTypes:
if groups:
ts_results = check(text, groups)
else:
ts_results = check(text)
if ts_results:
return name
return 'normal'
def processStructure(self,
structure,
callback,
data,
level=0,
):
"Iterate/recurse over the structure of the DOM."
for s in structure:
paraType = self.getParaType(s[0])
callback(s[0], paraType, level, data)
self.processStructure(s[1], callback, data, level+1)
return
def walk(self, callback, level=0, data=None):
"""Traverse the DOM for the StructuredText.
Arguments
callback -- Callable object to execute with each node.
Should match the signature 'callback(text, paraType, level,
data)' where text is the actual string of the node, paraType
is the paragraph type, level is the indention nesting level,
and data is the data argument to this method.
level -- The starting indention nesting level of the text.
data -- Data to be provided to the callback.
"""
self.processStructure(self.structure, callback, data, level)
return
def insertInWidget(self, widget, where):
"""Insert the StructuredText content at 'where' in the 'widget'.
This method walks through the structure of the text document
and inserts the components into the 'widget' at the index
identified by 'where'.
"""
self.walk(self.__insertCB, data=(widget, where))
return
def __getFormattedParts(self, text):
"""Returns parsed sub-paragraphs and their formatting instructions.
Returns a list of tuples consisting of ('format', text) where
'format' is one of self.CHARACTER_FORMATS.
"""
return [('normal', text)]
def __insertCB(self, text, paraType, level, data):
"Callback used by self.walk() to insert text into a widget."
widget, where = data
indent = '\t' * level
widget.insert(where, '%s ' % paraType)
widget.insert(where, indent)
for subpara_format, subpara_text in self.__getFormattedParts(text):
widget.insert(where, '<%s>%s</%s>' % (subpara_format, text, subpara_format))
widget.insert(where, '\n\n')
return
class ScrolledStructuredText(Pmw.ScrolledText):
"""Scrolled StructuredText display widget.
The ScrolledStructuredText display widget uses the
StructuredText.py module from "Zope":http://www.zope.org to
parse text and derive layout and formatting instructions.
"""
def __init__(self, parent, **kw):
INITOPT = Pmw.INITOPT
optiondefs = (
('labelpos', 'nw', INITOPT),
('text_height', 40, INITOPT),
('text_width', 80, INITOPT),
('progress', None, INITOPT),
)
self.defineoptions(kw, optiondefs)
Pmw.ScrolledText.__init__(self, parent)
self.parent = parent
self.initialiseoptions(self.__class__)
return
def importfile(self, fileName, where='end'):
#Pmw.ScrolledText.importfile(self, fileName, where)
if not fileName:
return
contents = open(fileName, 'rt').read()
#st = TkStructuredText(contents)
#self.insertST(st, where)
self.settext(contents)
return
def settext(self, text):
#
# Remove existing text
#
disabled = (self._textbox.cget('state') == 'disabled')
if disabled:
self._textbox.configure(state='normal')
self._textbox.delete('0.0', 'end')
if disabled:
self._textbox.configure(state='disabled')
#
# Replace with new text.
#
st = TkStructuredText(text)
st.insertInWidget(self, 'end', )
return
def insert(self, where, text, style=None):
self._textbox.insert(where, text, style)
return
def test():
"Test function."
class TestSST(GuiAppD):
def createInterface(self):
testSST = self.createcomponent( 'testSST',
(), None,
ScrolledStructuredText,
(self.interior(),),
progress=self.updateProgress,
)
testSST.pack(expand=YES, fill=BOTH)
return
def createMenuBar(self):
self.addMenuItem('File', 'command', 'Import a file...',
label='Import...',
command=self.importFile,
)
GuiAppD.createMenuBar(self)
return
def importFile(self):
filename = self.getFilenameToOpen()
if not filename:
return
self.component('testSST').importfile(filename)
return
TestSST().run()
return
if __name__ == '__main__':
test()
|