From 7444eb5e89115007d0224e0edc833b50ffc0f9d8 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Fri, 21 Dec 2012 02:02:02 +0000 Subject: [PATCH] - Created a new canvas directive called ``bookmark``. - Added ``img`` directive, which is a simple image flowable. - Link support for rectangles. --- CHANGES.txt | 6 ++-- RML-DIFFERENCES.txt | 22 +++++------- src/z3c/rml/canvas.py | 31 +++++++++++++++-- src/z3c/rml/flowable.py | 77 +++++++++++++++++++++++++++++++++++++++++ src/z3c/rml/platypus.py | 5 +++ 5 files changed, 123 insertions(+), 18 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 9435c39..9709c24 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -46,7 +46,9 @@ CHANGES - Renamed ``bookmark`` to ``bookmarkPage``. -- Created a new Canvas directive called ``bookmark``. +- Created a new canvas directive called ``bookmark``. + +- Added ``img`` directive, which is a simple image flowable. - Don't show "doc" namespace in reference snippets. @@ -60,7 +62,7 @@ CHANGES - Implemented ``plugInGraphic`` which allows inserting graphics rendered in Python. -- Added `href` and `destination` to table cells. +- Added `href` and `destination` to table cells and rectangles. - Bug: Due to a logic error, bad directives were never properly detected and logged about. diff --git a/RML-DIFFERENCES.txt b/RML-DIFFERENCES.txt index f03bb27..c1e54d9 100644 --- a/RML-DIFFERENCES.txt +++ b/RML-DIFFERENCES.txt @@ -33,6 +33,14 @@ Incompatibilies - ``catchForms``: This feature requires PageCatcher, which is a ReportLab commercial product and there is no Open Source alternative. +- ``addMapping``: This is a useful API function that was supported in earlier + versions of RML2PDF. It is now gone, but this library still supports it. + +- ``drawing``: There is no documentation for this tag and I do not know what + it is supposed to do. Thus z3c.rml does not implement it. + +- ``widget``: There is no documentation for this tag and I do not know what it + is supposed to do. Thus z3c.rml does not implement it. To be Done ---------- @@ -56,10 +64,6 @@ naming. - blockTable: -repeatRows, -alignment -- drawing - -- widget - - evalString - image: -showBoundary, -preserveAspectRatio @@ -72,9 +76,6 @@ naming. - imageFigure -- img - - - checkBox - letterBoxes @@ -116,10 +117,6 @@ naming. - length -- param: -value - -- setFontSize (plain canvas op) - - log - debug @@ -136,6 +133,3 @@ naming. - -pdfInclude -- rectangle.: href and/or destination (Test 038) - -- -addMapping diff --git a/src/z3c/rml/canvas.py b/src/z3c/rml/canvas.py index d6d3f66..a496e28 100644 --- a/src/z3c/rml/canvas.py +++ b/src/z3c/rml/canvas.py @@ -221,6 +221,17 @@ class IRectangle(IShape): description=u'The radius of the rounded corners.', required=False) + href = attr.Text( + title=u'Link URL', + description=u'When specified, the rectangle becomes a link to that URL.', + required=False) + + destination = attr.Text( + title=u'Link Destination', + description=(u'When specified, the rectangle becomes a link to that ' + u'destination.'), + required=False) + class Rectangle(CanvasRMLDirective): signature = IRectangle callable = 'rect' @@ -229,8 +240,24 @@ class Rectangle(CanvasRMLDirective): def process(self): if 'round' in self.element.keys(): self.callable = 'roundRect' - super(Rectangle, self).process() - + kwargs = dict(self.getAttributeValues(attrMapping=self.attrMapping)) + canvas = attr.getManager(self, interfaces.ICanvasManager).canvas + # Create a link + url = kwargs.pop('href', None) + if url: + canvas.linkURL( + url, + (kwargs['x'], kwargs['y'], + kwargs['x']+kwargs['width'], kwargs['y']+kwargs['height'])) + dest = kwargs.pop('destination', None) + if dest: + canvas.linkRect( + '', dest, + (kwargs['x'], kwargs['y'], + kwargs['x']+kwargs['width'], kwargs['y']+kwargs['height'])) + + # Render the rectangle + getattr(canvas, self.callable)(**kwargs) class IGrid(interfaces.IRMLDirectiveSignature): """A shape to be drawn on the canvas.""" diff --git a/src/z3c/rml/flowable.py b/src/z3c/rml/flowable.py index 538e4dc..3e0ca1d 100644 --- a/src/z3c/rml/flowable.py +++ b/src/z3c/rml/flowable.py @@ -838,6 +838,50 @@ def process(self): frame = self.klass(flow.flow, **args) self.parent.flow.append(frame) +class IImage(interfaces.IRMLDirectiveSignature): + """An image.""" + + src = attr.Image( + title=u'Image Source', + description=u'The file that is used to extract the image data.', + onlyOpen=True, + required=True) + + width = attr.Measurement( + title=u'Image Width', + description=u'The width of the image.', + required=False) + + height = attr.Measurement( + title=u'Image Height', + description=u'The height the image.', + required=False) + + mask = attr.Color( + title=u'Mask', + description=u'The color mask used to render the image.', + required=False) + + vAlign = attr.Choice( + title=u'Vertical Alignment', + description=u'The vertical alignment of the image.', + choices=interfaces.VALIGN_TEXT_CHOICES, + required=False) + +class Image(Flowable): + signature = IImage + klass = reportlab.platypus.flowables.Image + attrMapping = {'src': 'filename'} + + def process(self): + args = dict(self.getAttributeValues(attrMapping=self.attrMapping)) + vAlign = args.pop('vAlign', None) + img = self.klass(**args) + if vAlign: + img.vAlign = vAlign + self.parent.flow.append(img) + + class IImageAndFlowables(interfaces.IRMLDirectiveSignature): """An image with flowables around it.""" @@ -1051,6 +1095,35 @@ class BookmarkPage(Flowable): attrMapping = {'name': 'key', 'fitType': 'fit'} +class IBookmark(interfaces.IRMLDirectiveSignature): + """ + This creates a bookmark to the current page which can be referred to with + the given key elsewhere. + """ + + name = attr.Text( + title=u'Name', + description=u'The name of the bookmark.', + required=True) + + x = attr.Measurement( + title=u'X Coordinate', + description=u'The x-position of the bookmark.', + default=0, + required=False) + + y = attr.Measurement( + title=u'Y Coordinate', + description=u'The y-position of the bookmark.', + default=0, + required=False) + +class Bookmark(Flowable): + signature = IBookmark + klass = platypus.Bookmark + attrMapping = {'name': 'key', 'x': 'relativeX', 'y': 'relativeY'} + + class ILink(interfaces.IRMLDirectiveSignature): """Place an internal link around a set of flowables.""" @@ -1287,11 +1360,13 @@ class IFlow(interfaces.IRMLDirectiveSignature): occurence.ZeroOrMore('condPageBreak', IConditionalPageBreak), occurence.ZeroOrMore('keepInFrame', IKeepInFrame), occurence.ZeroOrMore('keepTogether', IKeepTogether), + occurence.ZeroOrMore('img', IImage), occurence.ZeroOrMore('imageAndFlowables', IImageAndFlowables), occurence.ZeroOrMore('pto', IPTO), occurence.ZeroOrMore('indent', IIndent), occurence.ZeroOrMore('fixedSize', IFixedSize), occurence.ZeroOrMore('bookmarkPage', IBookmarkPage), + occurence.ZeroOrMore('bookmark', IBookmark), occurence.ZeroOrMore('link', ILink), occurence.ZeroOrMore('hr', IHorizontalRow), occurence.ZeroOrMore('showIndex', IShowIndex), @@ -1330,11 +1405,13 @@ class Flow(directive.RMLDirective): 'condPageBreak': ConditionalPageBreak, 'keepInFrame': KeepInFrame, 'keepTogether': KeepTogether, + 'img': Image, 'imageAndFlowables': ImageAndFlowables, 'pto': PTO, 'indent': Indent, 'fixedSize': FixedSize, 'bookmarkPage': BookmarkPage, + 'bookmark': Bookmark, 'link': Link, 'hr': HorizontalRow, 'showIndex': ShowIndex, diff --git a/src/z3c/rml/platypus.py b/src/z3c/rml/platypus.py index 9f93ec9..590f503 100644 --- a/src/z3c/rml/platypus.py +++ b/src/z3c/rml/platypus.py @@ -79,6 +79,11 @@ def draw(self): self.canv.bookmarkPage(*self.args, **self.kw) +class Bookmark(BaseFlowable): + def draw(self): + self.canv.bookmarkHorizontal(*self.args, **self.kw) + + class OutlineAdd(BaseFlowable): def draw(self): if self.kw.get('key', None) is None: