reportlab/platypus/flowables.py
author aaron_watters
Tue, 13 Jun 2000 13:03:31 +0000
changeset 268 8414113fa500
parent 255 ee9e321e747d
child 307 c439e402b404
permissions -rw-r--r--
more documentation changes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     1
###############################################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     2
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     3
#	ReportLab Public License Version 1.0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     4
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     5
#	Except for the change of names the spirit and intention of this
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     6
#	license is the same as that of Python
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     7
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     8
#	(C) Copyright ReportLab Inc. 1998-2000.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     9
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    10
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    11
# All Rights Reserved
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    12
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    13
# Permission to use, copy, modify, and distribute this software and its
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    14
# documentation for any purpose and without fee is hereby granted, provided
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    15
# that the above copyright notice appear in all copies and that both that
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    16
# copyright notice and this permission notice appear in supporting
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    17
# documentation, and that the name of ReportLab not be used
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    18
# in advertising or publicity pertaining to distribution of the software
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    19
# without specific, written prior permission.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    20
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    21
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    22
# Disclaimer
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    23
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    24
# ReportLab Inc. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    25
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    26
# IN NO EVENT SHALL ReportLab BE LIABLE FOR ANY SPECIAL, INDIRECT
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    27
# OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    28
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    29
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    30
# PERFORMANCE OF THIS SOFTWARE.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    31
#
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    32
###############################################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    33
#	$Log: flowables.py,v $
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    34
#	Revision 1.3  2000/06/13 13:03:31  aaron_watters
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    35
#	more documentation changes
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    36
#
255
ee9e321e747d pageSize is wrong at present
rgbecker
parents: 253
diff changeset
    37
#	Revision 1.2  2000/06/01 16:27:56  rgbecker
ee9e321e747d pageSize is wrong at present
rgbecker
parents: 253
diff changeset
    38
#	pageSize is wrong at present
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    39
#	
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    40
#	Revision 1.1  2000/06/01 15:23:06  rgbecker
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    41
#	Platypus re-organisation
255
ee9e321e747d pageSize is wrong at present
rgbecker
parents: 253
diff changeset
    42
#	
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    43
#	
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    44
__version__=''' $Id: flowables.py,v 1.3 2000/06/13 13:03:31 aaron_watters Exp $ '''
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    45
__doc__="""
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    46
A flowable is a "floating element" in a document whose exact position is determined by the
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    47
other elements that precede it, such as a paragraph, a diagram interspersed between paragraphs,
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    48
a section header, etcetera.  Examples of non-flowables include page numbering annotations,
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    49
headers, footers, fixed diagrams or logos, among others.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    50
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    51
Flowables are defined here as objects which know how to determine their size and which
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    52
can draw themselves onto a page with respect to a relative "origin" position determined
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    53
at a higher level.  Some Flowables also know how to "split themselves".  For example a
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    54
long paragraph might split itself between one page and the next.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    55
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    56
The "text" of a document usually consists mainly of a sequence of flowables which
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    57
flow into a document from top to bottom (with column and page breaks controlled by
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    58
higher level components).
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    59
"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    60
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    61
# 200-10-13 gmcm
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    62
#	packagizing
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    63
#	rewrote grid stuff - now in tables.py
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    64
import os
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    65
import string
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    66
from copy import deepcopy
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    67
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    68
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    69
from reportlab.pdfgen import canvas
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    70
from reportlab.lib.units import inch
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    71
from reportlab.lib.colors import red
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    72
from reportlab.pdfbase import pdfutils
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    73
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    74
from reportlab.lib.pagesizes import DEFAULT_PAGE_SIZE
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    75
PAGE_HEIGHT = DEFAULT_PAGE_SIZE[1]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    76
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    77
#############################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    78
#	Flowable Objects - a base class and a few examples.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    79
#	One is just a box to get some metrics.	We also have
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    80
#	a paragraph, an image and a special 'page break'
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    81
#	object which fills the space.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    82
#############################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    83
class Flowable:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    84
	"""Abstract base class for things to be drawn.	Key concepts:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    85
	1. It knows its size
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    86
	2. It draws in its own coordinate system (this requires the
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    87
		base API to provide a translate() function.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    88
	"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    89
	def __init__(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    90
		self.width = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    91
		self.height = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    92
		self.wrapped = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    93
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    94
	def drawOn(self, canvas, x, y):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    95
		"Tell it to draw itself on the canvas.	Do not override"
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    96
		self.canv = canvas
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    97
		self.canv.saveState()
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    98
		self.canv.translate(x, y)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    99
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   100
		self.draw()   #this is the bit you overload
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   101
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   102
		self.canv.restoreState()
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   103
		del self.canv
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   104
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   105
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   106
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   107
		"""This will be called by the enclosing frame before objects
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   108
		are asked their size, drawn or whatever.  It returns the
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   109
		size actually used."""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   110
		return (self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   111
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   112
	def split(self, availWidth, availheight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   113
		"""This will be called by more sophisticated frames when
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   114
		wrap fails. Stupid flowables should return []. Clever flowables
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   115
		should split themselves and return a list of flowables"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   116
		return []
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   117
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   118
	def getSpaceAfter(self):
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   119
	        """returns how much space should follow this item if another item follows on the same page."""
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   120
		if hasattr(self,'spaceAfter'): return self.spaceAfter
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   121
		elif hasattr(self,'style') and hasattr(self.style,'spaceAfter'): return self.style.spaceAfter
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   122
		else: return 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   123
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   124
	def getSpaceBefore(self):
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   125
	        """returns how much space should precede this item if another item precedess on the same page."""
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   126
		if hasattr(self,'spaceBefore'): return self.spaceBefore
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   127
		elif hasattr(self,'style') and hasattr(self.style,'spaceBefore'): return self.style.spaceBefore
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   128
		else: return 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   129
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   130
class XBox(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   131
	"""Example flowable - a box with an x through it and a caption.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   132
	This has a known size, so does not need to respond to wrap()."""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   133
	def __init__(self, width, height, text = 'A Box'):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   134
		Flowable.__init__(self)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   135
		self.width = width
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   136
		self.height = height
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   137
		self.text = text
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   138
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   139
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   140
		self.canv.rect(0, 0, self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   141
		self.canv.line(0, 0, self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   142
		self.canv.line(0, self.height, self.width, 0)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   143
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   144
		#centre the text
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   145
		self.canv.setFont('Times-Roman',12)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   146
		self.canv.drawCentredString(0.5*self.width, 0.5*self.height, self.text)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   147
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   148
class Preformatted(Flowable):
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   149
	"""This is like the HTML <PRE> tag.  
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   150
	It attempts to display text exactly as you typed it in a fixed width "typewriter" font.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   151
	The line breaks are exactly where you put
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   152
	them, and it will not be wrapped."""
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   153
	def __init__(self, text, style, bulletText = None, dedent=0):
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   154
	        """text is the text to display. If dedent is set then common leading space
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   155
	           will be chopped off the front (for example if the entire text is indented
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   156
	           6 spaces or more then each line will have 6 spaces removed from the front).
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   157
	        """
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   158
		self.style = style
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   159
		self.bulletText = bulletText
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   160
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   161
		#tidy up text - carefully, it is probably code.  If people want to
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   162
		#indent code within a source script, you can supply an arg to dedent
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   163
		#and it will chop off that many character, otherwise it leaves
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   164
		#left edge intact.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   165
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   166
		templines = string.split(text, '\n')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   167
		self.lines = []
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   168
		for line in templines:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   169
			line = string.rstrip(line[dedent:])
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   170
			self.lines.append(line)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   171
		#don't want the first or last to be empty
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   172
		while string.strip(self.lines[0]) == '':
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   173
			self.lines = self.lines[1:]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   174
		while string.strip(self.lines[-1]) == '':
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   175
			self.lines = self.lines[:-1]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   176
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   177
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   178
		self.width = availWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   179
		self.height = self.style.leading*len(self.lines)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   180
		return (self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   181
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   182
	def split(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   183
		#returns two Preformatted objects
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   184
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   185
		#not sure why they can be called with a negative height		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   186
		if availHeight < self.style.leading:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   187
			return []
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   188
		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   189
		linesThatFit = int(availHeight * 1.0 / self.style.leading)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   190
		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   191
		text1 = string.join(self.lines[0:linesThatFit], '\n')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   192
		text2 = string.join(self.lines[linesThatFit:], '\n')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   193
		style = self.style
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   194
		if style.firstLineIndent != 0:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   195
			style = deepcopy(style)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   196
			style.firstLineIndent = 0
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   197
		return [Preformatted(text1, self.style), Preformatted(text2, style)]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   198
		
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   199
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   200
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   201
		#call another method for historical reasons.  Besides, I
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   202
		#suspect I will be playing with alternate drawing routines
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   203
		#so not doing it here makes it easier to switch.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   204
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   205
		cur_x = self.style.leftIndent
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   206
		cur_y = self.height - self.style.fontSize
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   207
		self.canv.addLiteral('%PreformattedPara')
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   208
		if self.style.textColor:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   209
			self.canv.setFillColor(self.style.textColor)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   210
		tx = self.canv.beginText(cur_x, cur_y)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   211
		#set up the font etc.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   212
		tx.setFont(self.style.fontName,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   213
				   self.style.fontSize,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   214
				   self.style.leading)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   215
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   216
		for text in self.lines:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   217
			tx.textLine(text)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   218
		self.canv.drawText(tx)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   219
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   220
class Image(Flowable):
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   221
	"""an image (digital picture).  Formats supported by PIL (the Python Imaging Library
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   222
	   are supported.  At the present time images as flowables are always centered horozontally
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   223
	   in the frame.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   224
	"""
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   225
	def __init__(self, filename, width=None, height=None):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   226
		"""If size to draw at not specified, get it from the image."""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   227
		import Image  #this will raise an error if they do not have PIL.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   228
		self.filename = filename
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   229
		# if it is a JPEG, will be inlined within the file -
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   230
		# but we still need to know its size now
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   231
		if os.path.splitext(filename)[1] in ['.jpg', '.JPG', '.jpeg', '.JPEG']:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   232
			info = pdfutils.readJPEGInfo(open(filename, 'rb'))
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   233
			self.imageWidth = info[0]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   234
			self.imageHeight = info[1]
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   235
		else:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   236
			img = Image.open(filename)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   237
			(self.imageWidth, self.imageHeight) = img.size
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   238
		if width:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   239
			self.drawWidth = width
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   240
		else:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   241
			self.drawWidth = self.imageWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   242
		if height:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   243
			self.drawHeight = height
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   244
		else:
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   245
			self.drawHeight = self.imageHeight
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   246
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   247
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   248
		#the caller may decide it does not fit.
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   249
		self.availWidth = availWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   250
		return (self.drawWidth, self.drawHeight)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   251
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   252
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   253
		#center it
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   254
		startx = 0.5 * (self.availWidth - self.drawWidth)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   255
		self.canv.drawInlineImage(self.filename,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   256
								  startx,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   257
								  0,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   258
								  self.drawWidth,
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   259
								  self.drawHeight
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   260
								  )
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   261
class Spacer(Flowable):
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   262
	"""A spacer just takes up space and doesn't draw anything - it guarantees
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   263
	   a gap between objects."""
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   264
	def __init__(self, width, height):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   265
		self.width = width
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   266
		self.height = height
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   267
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   268
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   269
		return (self.width, self.height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   270
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   271
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   272
		pass
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   273
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   274
class PageBreak(Flowable):
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   275
	"""Move on to the next page in the document.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
   276
	   This works by consuming all remaining space in the frame!"""
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   277
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   278
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   279
		self.width = availWidth
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   280
		self.height = availHeight
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   281
		return (availWidth,availHeight)  #step back a point
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   282
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   283
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   284
		pass
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   285
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   286
class Macro(Flowable):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   287
	"""This is not actually drawn (i.e. it has zero height)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   288
	but is executed when it would fit in the frame.  Allows direct
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   289
	access to the canvas through the object 'canvas'"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   290
	def __init__(self, command):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   291
		self.command = command
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   292
	def wrap(self, availWidth, availHeight):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   293
		return (0,0)
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   294
	def draw(self):
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   295
		exec self.command in globals(), {'canvas':self.canv}
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   296
255
ee9e321e747d pageSize is wrong at present
rgbecker
parents: 253
diff changeset
   297
#from paragraph import Paragraph