diff options
Diffstat (limited to 'bin/reportlab/tools/docco/rl_doc_utils.py')
| -rw-r--r-- | bin/reportlab/tools/docco/rl_doc_utils.py | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/bin/reportlab/tools/docco/rl_doc_utils.py b/bin/reportlab/tools/docco/rl_doc_utils.py new file mode 100644 index 00000000000..a105b9d7e88 --- /dev/null +++ b/bin/reportlab/tools/docco/rl_doc_utils.py @@ -0,0 +1,411 @@ +#!/bin/env python +#Copyright ReportLab Europe Ltd. 2000-2004 +#see license.txt for license details +#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/tools/docco/rl_doc_utils.py +__version__=''' $Id: rl_doc_utils.py 2830 2006-04-05 15:18:32Z rgbecker $ ''' + + +__doc__ = """ +This module contains utilities for generating guides +""" + +import os, sys, glob +import string + +from rltemplate import RLDocTemplate +from stylesheet import getStyleSheet +styleSheet = getStyleSheet() + +#from reportlab.platypus.doctemplate import SimpleDocTemplate +from reportlab.lib.units import inch +from reportlab.lib.pagesizes import letter, A4, A5, A3 # latter two for testing +from reportlab.rl_config import defaultPageSize +from reportlab.platypus import figures +from reportlab.platypus import Paragraph, Spacer, Preformatted,\ + PageBreak, CondPageBreak, Flowable, Table, TableStyle, \ + NextPageTemplate, KeepTogether, Image, XPreformatted +from reportlab.lib.styles import ParagraphStyle +from reportlab.lib import colors +from reportlab.lib.sequencer import getSequencer + +import examples + +appmode=0 + + +from t_parse import Template +QFcodetemplate = Template("X$X$", "X") +QFreptemplate = Template("X^X^", "X") +codesubst = "%s<font name=Courier>%s</font>" +QFsubst = "%s<font name=Courier><i>%s</i></font>" + + +def quickfix(text): + """inside text find any subsequence of form $subsequence$. + Format the subsequence as code. If similarly if text contains ^arg^ + format the arg as replaceable. The escape sequence for literal + $ is $\\$ (^ is ^\\^. + """ + from string import join + for (template,subst) in [(QFcodetemplate, codesubst), (QFreptemplate, QFsubst)]: + fragment = text + parts = [] + try: + while fragment: + try: + (matches, index) = template.PARSE(fragment) + except: raise ValueError + else: + [prefix, code] = matches + if code == "\\": + part = fragment[:index] + else: + part = subst % (prefix, code) + parts.append(part) + fragment = fragment[index:] + except ValueError: + parts.append(fragment) + text = join(parts, "") + return text +#print quickfix("$testing$ testing $one$ ^two^ $three(^four^)$") + + + +H1 = styleSheet['Heading1'] +H2 = styleSheet['Heading2'] +H3 = styleSheet['Heading3'] +H4 = styleSheet['Heading4'] +B = styleSheet['BodyText'] +BU = styleSheet['Bullet'] +Comment = styleSheet['Comment'] +Centred = styleSheet['Centred'] +Caption = styleSheet['Caption'] + +#set up numbering +seq = getSequencer() +seq.setFormat('Chapter','1') +seq.setFormat('Section','1') +seq.setFormat('Appendix','A') +seq.setFormat('Figure', '1') +seq.chain('Chapter','Section') +seq.chain('Chapter','Figure') + +lessonnamestyle = H2 +discussiontextstyle = B +exampletextstyle = styleSheet['Code'] +# size for every example +examplefunctionxinches = 5.5 +examplefunctionyinches = 3 +examplefunctiondisplaysizes = (examplefunctionxinches*inch, examplefunctionyinches*inch) + +def getJustFontPaths(): + '''return afm and pfb for Just's files''' + import reportlab + folder = os.path.dirname(reportlab.__file__) + os.sep + 'fonts' + return os.path.join(folder, 'LeERC___.AFM'), os.path.join(folder, 'LeERC___.PFB') + +# for testing +def NOP(*x,**y): + return None + +def CPage(inches): + getStory().append(CondPageBreak(inches*inch)) + +def newPage(): + getStory().append(PageBreak()) + +def nextTemplate(templName): + f = NextPageTemplate(templName) + getStory().append(f) + +def disc(text, klass=Paragraph, style=discussiontextstyle): + text = quickfix(text) + P = klass(text, style) + getStory().append(P) + +def restartList(): + getSequencer().reset('list1') + +def list(text, doBullet=1): + text=quickfix(text) + if doBullet: + text='<bullet><seq id="list1"/>.</bullet>'+text + P = Paragraph(text, BU) + getStory().append(P) + +def bullet(text): + text='<bullet><font name="Symbol">\xe2\x80\xa2</font></bullet>' + quickfix(text) + P = Paragraph(text, BU) + getStory().append(P) + +def eg(text,before=0.1,after=0): + space(before) + disc(text, klass=Preformatted, style=exampletextstyle) + space(after) + +def space(inches=1./6): + if inches: getStory().append(Spacer(0,inches*inch)) + +def EmbeddedCode(code,name='t'): + eg(code) + disc("produces") + exec code+("\ngetStory().append(%s)\n"%name) + +def startKeep(): + return len(getStory()) + +def endKeep(s): + S = getStory() + k = KeepTogether(S[s:]) + S[s:] = [k] + +def title(text): + """Use this for the document title only""" + disc(text,style=styleSheet['Title']) + +#AR 3/7/2000 - defining three new levels of headings; code +#should be swapped over to using them. + +def heading1(text): + """Use this for chapters. Lessons within a big chapter + should now use heading2 instead. Chapters get numbered.""" + getStory().append(PageBreak()) + p = Paragraph('Chapter <seq id="Chapter"/> ' + quickfix(text), H1) + getStory().append(p) + +def Appendix1(text,): + global appmode + getStory().append(PageBreak()) + if not appmode: + seq.setFormat('Chapter','A') + seq.reset('Chapter') + appmode = 1 + p = Paragraph('Appendix <seq id="Chapter"/> ' + quickfix(text), H1) + getStory().append(p) + +def heading2(text): + """Used to be 'lesson'""" + getStory().append(CondPageBreak(inch)) + p = Paragraph('<seq template="%(Chapter)s.%(Section+)s "/>' + quickfix(text), H2) + getStory().append(p) + +def heading3(text): + """Used to be most of the plain old 'head' sections""" + getStory().append(CondPageBreak(inch)) + p = Paragraph(quickfix(text), H3) + getStory().append(p) + +def image(path, width=None, height=None ): + s = startKeep() + space(.2) + import reportlab + rlDocImageDir = os.path.join(os.path.dirname(reportlab.__file__), 'docs','images') + getStory().append(Image(os.path.join(rlDocImageDir,path),width,height)) + space(.2) + endKeep(s) + +def heading4(text): + """Used to be most of the plain old 'head' sections""" + getStory().append(CondPageBreak(inch)) + p = Paragraph(quickfix(text), H4) + getStory().append(p) + +def todo(text): + """Used for notes to ourselves""" + getStory().append(Paragraph(quickfix(text), Comment)) + +def centred(text): + getStory().append(Paragraph(quickfix(text), Centred)) + +def caption(text): + getStory().append(Paragraph(quickfix(text), Caption)) + +class Illustration(figures.Figure): + """The examples are all presented as functions which do + something to a canvas, with a constant height and width + used. This puts them inside a figure box with a caption.""" + + def __init__(self, operation, caption, width=None, height=None): + stdwidth, stdheight = examplefunctiondisplaysizes + if not width: + width = stdwidth + if not height: + height = stdheight + #figures.Figure.__init__(self, stdwidth * 0.75, stdheight * 0.75) + figures.Figure.__init__(self, width, height, + 'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption)) + self.operation = operation + + def drawFigure(self): + #shrink it a little... + #self.canv.scale(0.75, 0.75) + self.operation(self.canv) + + +def illust(operation, caption, width=None, height=None): + i = Illustration(operation, caption, width=width, height=height) + getStory().append(i) + + +class GraphicsDrawing(Illustration): + """Lets you include reportlab/graphics drawings seamlessly, + with the right numbering.""" + def __init__(self, drawing, caption): + figures.Figure.__init__(self, + drawing.width, + drawing.height, + 'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption) + ) + self.drawing = drawing + + def drawFigure(self): + d = self.drawing + d.wrap(d.width, d.height) + d.drawOn(self.canv, 0, 0) + +def draw(drawing, caption): + d = GraphicsDrawing(drawing, caption) + getStory().append(d) + +class ParaBox(figures.Figure): + """Illustrates paragraph examples, with style attributes on the left""" + descrStyle = ParagraphStyle('description', + fontName='Courier', + fontSize=8, + leading=9.6) + + def __init__(self, text, style, caption): + figures.Figure.__init__(self, 0, 0, caption) + self.text = text + self.style = style + self.para = Paragraph(text, style) + + styleText = self.getStyleText(style) + self.pre = Preformatted(styleText, self.descrStyle) + + def wrap(self, availWidth, availHeight): + """Left 30% is for attributes, right 50% for sample, + 10% gutter each side.""" + self.x0 = availWidth * 0.05 #left of box + self.x1 = availWidth * 0.1 #left of descriptive text + self.x2 = availWidth * 0.5 #left of para itself + self.x3 = availWidth * 0.9 #right of para itself + self.x4 = availWidth * 0.95 #right of box + self.width = self.x4 - self.x0 + self.dx = 0.5 * (availWidth - self.width) + + paw, self.pah = self.para.wrap(self.x3 - self.x2, availHeight) + self.pah = self.pah + self.style.spaceBefore + self.style.spaceAfter + prw, self.prh = self.pre.wrap(self.x2 - self.x1, availHeight) + self.figureHeight = max(self.prh, self.pah) * 10.0/9.0 + return figures.Figure.wrap(self, availWidth, availHeight) + + def getStyleText(self, style): + """Converts style to preformatted block of text""" + lines = [] + for (key, value) in style.__dict__.items(): + lines.append('%s = %s' % (key, value)) + lines.sort() + return string.join(lines, '\n') + + def drawFigure(self): + + #now we fill in the bounding box and before/after boxes + self.canv.saveState() + self.canv.setFillGray(0.95) + self.canv.setDash(1,3) + self.canv.rect(self.x2 - self.x0, + self.figureHeight * 0.95 - self.pah, + self.x3-self.x2, self.para.height, + fill=1,stroke=1) + + self.canv.setFillGray(0.90) + self.canv.rect(self.x2 - self.x0, #spaceBefore + self.figureHeight * 0.95 - self.pah + self.para.height, + self.x3-self.x2, self.style.spaceBefore, + fill=1,stroke=1) + + self.canv.rect(self.x2 - self.x0, #spaceBefore + self.figureHeight * 0.95 - self.pah - self.style.spaceAfter, + self.x3-self.x2, self.style.spaceAfter, + fill=1,stroke=1) + + self.canv.restoreState() + #self.canv.setFillColor(colors.yellow) + self.para.drawOn(self.canv, self.x2 - self.x0, + self.figureHeight * 0.95 - self.pah) + self.pre.drawOn(self.canv, self.x1 - self.x0, + self.figureHeight * 0.95 - self.prh) + + + def getStyleText(self, style): + """Converts style to preformatted block of text""" + lines = [] + for (key, value) in style.__dict__.items(): + if key not in ('name','parent'): + lines.append('%s = %s' % (key, value)) + return string.join(lines, '\n') + + +class ParaBox2(figures.Figure): + """Illustrates a paragraph side-by-side with the raw + text, to show how the XML works.""" + def __init__(self, text, caption): + figures.Figure.__init__(self, 0, 0, caption) + descrStyle = ParagraphStyle('description', + fontName='Courier', + fontSize=8, + leading=9.6) + textStyle = B + self.text = text + self.left = Paragraph('<![CDATA[' + text + ']]>', descrStyle) + self.right = Paragraph(text, B) + + + def wrap(self, availWidth, availHeight): + self.width = availWidth * 0.9 + colWidth = 0.4 * self.width + lw, self.lh = self.left.wrap(colWidth, availHeight) + rw, self.rh = self.right.wrap(colWidth, availHeight) + self.figureHeight = max(self.lh, self.rh) * 10.0/9.0 + return figures.Figure.wrap(self, availWidth, availHeight) + + def drawFigure(self): + self.left.drawOn(self.canv, + self.width * 0.05, + self.figureHeight * 0.95 - self.lh + ) + self.right.drawOn(self.canv, + self.width * 0.55, + self.figureHeight * 0.95 - self.rh + ) + +def parabox(text, style, caption): + p = ParaBox(text, style, + 'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption) + ) + getStory().append(p) + +def parabox2(text, caption): + p = ParaBox2(text, + 'Figure <seq template="%(Chapter)s-%(Figure+)s"/>: ' + quickfix(caption) + ) + getStory().append(p) + +def pencilnote(): + getStory().append(examples.NoteAnnotation()) + + +from reportlab.lib.colors import tan, green +def handnote(xoffset=0, size=None, fillcolor=tan, strokecolor=green): + getStory().append(examples.HandAnnotation(xoffset,size,fillcolor,strokecolor)) + + +#make a singleton, created when requested rather +#than each time a chapter imports it. +_story = [] +def setStory(story=[]): + global _story + _story = story +def getStory(): + return _story |
