reportlab/platypus/flowables.py
author andy_robinson
Mon, 26 Nov 2001 21:49:01 +0000
changeset 1440 243d35446390
parent 1426 377351bbe539
child 1477 dc5c2ba1005a
permissions -rw-r--r--
Removed 0 from multiBuild stuff prior to further changes; ensured test suite really does run silently when making manuals.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 445
diff changeset
     1
#copyright ReportLab Inc. 2000
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 445
diff changeset
     2
#see license.txt for license details
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 445
diff changeset
     3
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/flowables.py?cvsroot=reportlab
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
     4
#$Header: /tmp/reportlab/reportlab/platypus/flowables.py,v 1.23 2001/11/19 09:21:23 rgbecker Exp $
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
     5
__version__=''' $Id: flowables.py,v 1.23 2001/11/19 09:21:23 rgbecker Exp $ '''
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
     6
__doc__="""
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
     7
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
     8
other elements that precede it, such as a paragraph, a diagram interspersed between paragraphs,
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
     9
a section header, etcetera.  Examples of non-flowables include page numbering annotations,
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    10
headers, footers, fixed diagrams or logos, among others.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    11
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    12
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
    13
can draw themselves onto a page with respect to a relative "origin" position determined
426
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    14
at a higher level. The object's draw() method should assume that (0,0) corresponds to the
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    15
bottom left corner of the enclosing rectangle that will contain the object. The attributes
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    16
vAlign and hAlign may be used by 'packers' as hints as to how the object should be placed.
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    17
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    18
Some Flowables also know how to "split themselves".  For example a
268
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    19
long paragraph might split itself between one page and the next.
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    20
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    21
The "text" of a document usually consists mainly of a sequence of flowables which
8414113fa500 more documentation changes
aaron_watters
parents: 255
diff changeset
    22
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
    23
higher level components).
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    24
"""
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    25
import os
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    26
import string
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    27
from copy import deepcopy
557
0ed50942f243 Allow for non string file names in Image.__init__
rgbecker
parents: 541
diff changeset
    28
from types import ListType, TupleType, StringType
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    29
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    30
from reportlab.pdfgen import canvas
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    31
from reportlab.lib.units import inch
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    32
from reportlab.lib.colors import red
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    33
from reportlab.pdfbase import pdfutils
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    34
724
0b10945bd324 Renamed config.py to rl_config.py
rgbecker
parents: 684
diff changeset
    35
from reportlab.rl_config import defaultPageSize
684
2a43c747527a Changed things to use config.py for defaults
rgbecker
parents: 558
diff changeset
    36
PAGE_HEIGHT = defaultPageSize[1]
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    37
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    38
#############################################################
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    39
#	Flowable Objects - a base class and a few examples.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    40
#	One is just a box to get some metrics.	We also have
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    41
#	a paragraph, an image and a special 'page break'
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    42
#	object which fills the space.
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    43
#############################################################
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    44
class Flowable:
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    45
	"""Abstract base class for things to be drawn.	Key concepts:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    46
	1. It knows its size
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    47
	2. It draws in its own coordinate system (this requires the
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    48
		base API to provide a translate() function.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    49
	"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    50
	def __init__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    51
		self.width = 0
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    52
		self.height = 0
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    53
		self.wrapped = 0
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    54
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    55
		#these are hints to packers/frames as to how the floable should be positioned
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    56
		self.hAlign = 'LEFT'	#CENTER/CENTRE or RIGHT
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    57
		self.vAlign = 'BOTTOM'	#MIDDLE or TOP
426
36a228f3e085 Changing to packer led positioning
rgbecker
parents: 368
diff changeset
    58
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    59
	def drawOn(self, canvas, x, y, _sW=0):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    60
		"Tell it to draw itself on the canvas.	Do not override"
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    61
		if _sW and hasattr(self,'hAlign'):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    62
			a = self.hAlign
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    63
			if a in ['CENTER','CENTRE']:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    64
				x = x + 0.5*_sW
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    65
			elif a == 'RIGHT':
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    66
				x = x + _sW
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    67
			elif a != 'LEFT':
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    68
				raise ValueError, "Bad hAlign value "+str(a)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    69
		self.canv = canvas
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    70
		self.canv.saveState()
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    71
		self.canv.translate(x, y)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    72
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    73
		self.draw()   #this is the bit you overload
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    74
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    75
		self.canv.restoreState()
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    76
		del self.canv
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    77
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    78
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    79
	def wrap(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    80
		"""This will be called by the enclosing frame before objects
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    81
		are asked their size, drawn or whatever.  It returns the
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    82
		size actually used."""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    83
		return (self.width, self.height)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    84
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    85
	def minWidth(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    86
		"""This should return the minimum required width"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    87
		return getattr(self,'_minWidth',self.width)
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 760
diff changeset
    88
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    89
	def split(self, availWidth, availheight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    90
		"""This will be called by more sophisticated frames when
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    91
		wrap fails. Stupid flowables should return []. Clever flowables
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    92
		should split themselves and return a list of flowables"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    93
		return []
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
    94
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    95
	def getKeepWithNext(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    96
		"""returns boolean determining whether the next flowabel should stay with this one"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    97
		if hasattr(self,'keepWithNext'): return self.keepWithNext
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    98
		elif hasattr(self,'style') and hasattr(self.style,'keepWithNext'): return self.style.keepWithNext
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
    99
		else: return 0
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   100
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   101
	def getSpaceAfter(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   102
		"""returns how much space should follow this item if another item follows on the same page."""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   103
		if hasattr(self,'spaceAfter'): return self.spaceAfter
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   104
		elif hasattr(self,'style') and hasattr(self.style,'spaceAfter'): return self.style.spaceAfter
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   105
		else: return 0
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   106
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   107
	def getSpaceBefore(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   108
		"""returns how much space should precede this item if another item precedess on the same page."""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   109
		if hasattr(self,'spaceBefore'): return self.spaceBefore
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   110
		elif hasattr(self,'style') and hasattr(self.style,'spaceBefore'): return self.style.spaceBefore
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   111
		else: return 0
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   112
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   113
	def isIndexing(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   114
		"""Hook for IndexingFlowables - things which have cross references"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   115
		return 0
512
c12ae96634d5 Added working table of contents framework
andy_robinson
parents: 496
diff changeset
   116
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   117
	def identity(self, maxLen=None):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   118
		'''
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   119
		This method should attempt to return a string that can be used to identify
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   120
		a particular flowable uniquely. The result can then be used for debugging
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   121
		and or error printouts
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   122
		'''
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   123
		if hasattr(self, 'getPlainText'):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   124
			r = self.getPlainText()
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   125
		elif hasattr(self, 'text'):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   126
			r = self.text
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   127
		else:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   128
			r = '...'
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   129
		if r and maxLen:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   130
			r = r[:maxLen]
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   131
		return "<%s at %d>%s" % (self.__class__.__name__, id(self), r)
1103
857af510186d Added identity method to Flowables
rgbecker
parents: 1036
diff changeset
   132
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   133
class XBox(Flowable):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   134
	"""Example flowable - a box with an x through it and a caption.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   135
	This has a known size, so does not need to respond to wrap()."""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   136
	def __init__(self, width, height, text = 'A Box'):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   137
		Flowable.__init__(self)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   138
		self.width = width
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   139
		self.height = height
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   140
		self.text = text
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   141
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   142
	def __repr__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   143
		return "XBox(w=%s, h=%s, t=%s)" % (self.width, self.height, self.text)
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 512
diff changeset
   144
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   145
	def draw(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   146
		self.canv.rect(0, 0, self.width, self.height)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   147
		self.canv.line(0, 0, self.width, self.height)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   148
		self.canv.line(0, self.height, self.width, 0)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   149
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   150
		#centre the text
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   151
		self.canv.setFont('Times-Roman',12)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   152
		self.canv.drawCentredString(0.5*self.width, 0.5*self.height, self.text)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   153
445
8b64b9812ca6 Fixes to _dedenter
rgbecker
parents: 442
diff changeset
   154
def _trimEmptyLines(lines):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   155
	#don't want the first or last to be empty
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   156
	while len(lines) and string.strip(lines[0]) == '':
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   157
		lines = lines[1:]
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   158
	while len(lines) and string.strip(lines[-1]) == '':
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   159
		lines = lines[:-1]
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   160
	return lines
445
8b64b9812ca6 Fixes to _dedenter
rgbecker
parents: 442
diff changeset
   161
442
e3eac15cddbd XPreformatted first fixes; now runs
rgbecker
parents: 426
diff changeset
   162
def _dedenter(text,dedent=0):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   163
	'''
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   164
	tidy up text - carefully, it is probably code.	If people want to
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   165
	indent code within a source script, you can supply an arg to dedent
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   166
	and it will chop off that many character, otherwise it leaves
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   167
	left edge intact.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   168
	'''
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   169
	lines = string.split(text, '\n')
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   170
	if dedent>0:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   171
		templines = _trimEmptyLines(lines)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   172
		lines = []
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   173
		for line in templines:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   174
			line = string.rstrip(line[dedent:])
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   175
			lines.append(line)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   176
	else:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   177
		lines = _trimEmptyLines(lines)
445
8b64b9812ca6 Fixes to _dedenter
rgbecker
parents: 442
diff changeset
   178
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   179
	return lines
442
e3eac15cddbd XPreformatted first fixes; now runs
rgbecker
parents: 426
diff changeset
   180
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   181
class Preformatted(Flowable):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   182
	"""This is like the HTML <PRE> tag.  
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   183
	It attempts to display text exactly as you typed it in a fixed width "typewriter" font.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   184
	The line breaks are exactly where you put
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   185
	them, and it will not be wrapped."""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   186
	def __init__(self, text, style, bulletText = None, dedent=0):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   187
		"""text is the text to display. If dedent is set then common leading space
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   188
		will be chopped off the front (for example if the entire text is indented
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   189
		6 spaces or more then each line will have 6 spaces removed from the front).
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   190
		"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   191
		self.style = style
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   192
		self.bulletText = bulletText
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   193
		self.lines = _dedenter(text,dedent)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   194
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   195
	def __repr__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   196
		bT = self.bulletText
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   197
		H = "Preformatted("
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   198
		if bT is not None:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   199
			H = "Preformatted(bulletText=%s," % repr(bT)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   200
		import string
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   201
		text = join(self.lines, "\n")
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   202
		return "%s'''\\ \n%s''')" % (H, text)
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 512
diff changeset
   203
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   204
	def wrap(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   205
		self.width = availWidth
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   206
		self.height = self.style.leading*len(self.lines)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   207
		return (self.width, self.height)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   208
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   209
	def split(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   210
		#returns two Preformatted objects
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   211
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   212
		#not sure why they can be called with a negative height		
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   213
		if availHeight < self.style.leading:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   214
			return []
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   215
		
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   216
		linesThatFit = int(availHeight * 1.0 / self.style.leading)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   217
		
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   218
		text1 = string.join(self.lines[0:linesThatFit], '\n')
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   219
		text2 = string.join(self.lines[linesThatFit:], '\n')
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   220
		style = self.style
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   221
		if style.firstLineIndent != 0:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   222
			style = deepcopy(style)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   223
			style.firstLineIndent = 0
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   224
		return [Preformatted(text1, self.style), Preformatted(text2, style)]
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   225
		
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   226
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   227
	def draw(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   228
		#call another method for historical reasons.  Besides, I
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   229
		#suspect I will be playing with alternate drawing routines
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   230
		#so not doing it here makes it easier to switch.
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   231
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   232
		cur_x = self.style.leftIndent
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   233
		cur_y = self.height - self.style.fontSize
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   234
		self.canv.addLiteral('%PreformattedPara')
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   235
		if self.style.textColor:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   236
			self.canv.setFillColor(self.style.textColor)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   237
		tx = self.canv.beginText(cur_x, cur_y)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   238
		#set up the font etc.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   239
		tx.setFont( self.style.fontName,
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   240
					self.style.fontSize,
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   241
					self.style.leading)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   242
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   243
		for text in self.lines:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   244
			tx.textLine(text)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   245
		self.canv.drawText(tx)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   246
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   247
class Image(Flowable):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   248
	"""an image (digital picture).	Formats supported by PIL (the Python Imaging Library
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   249
	   are supported.  At the present time images as flowables are always centered horozontally
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   250
	   in the frame.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   251
	"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   252
	def __init__(self, filename, width=None, height=None):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   253
		"""If size to draw at not specified, get it from the image."""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   254
		from reportlab.lib.utils import PIL_Image  #this will raise an error if they do not have PIL.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   255
		self._filename = self.filename = filename
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   256
		self.hAlign = 'CENTER'
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   257
		# if it is a JPEG, will be inlined within the file -
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   258
		# but we still need to know its size now
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   259
		if type(filename) is StringType and os.path.splitext(filename)[1] in ['.jpg', '.JPG', '.jpeg', '.JPEG']:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   260
			info = pdfutils.readJPEGInfo(open(filename, 'rb'))
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   261
			self.imageWidth = info[0]
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   262
			self.imageHeight = info[1]
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   263
		else:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   264
			# we have to assume this is a file like object
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   265
			self.filename = img = PIL_Image.open(filename)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   266
			(self.imageWidth, self.imageHeight) = img.size
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   267
		if width:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   268
			self.drawWidth = width
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   269
		else:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   270
			self.drawWidth = self.imageWidth
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   271
		if height:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   272
			self.drawHeight = height
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   273
		else:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   274
			self.drawHeight = self.imageHeight
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   275
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   276
	def wrap(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   277
		#the caller may decide it does not fit.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   278
		return (self.drawWidth, self.drawHeight)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   279
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   280
	def draw(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   281
		#center it
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   282
		self.canv.drawInlineImage(self.filename,
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   283
								0,
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   284
								0,
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   285
								self.drawWidth,
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   286
								self.drawHeight
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   287
								)
1103
857af510186d Added identity method to Flowables
rgbecker
parents: 1036
diff changeset
   288
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   289
	def identity(self,maxLen):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   290
		r = Flowable.identity(self,maxLen)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   291
		if r[-4:]=='>...' and type(self._filename) is StringType:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   292
			r = "%s filename=%s>" % (r[:-4],self._filename)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   293
		return r
1103
857af510186d Added identity method to Flowables
rgbecker
parents: 1036
diff changeset
   294
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   295
class Spacer(Flowable):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   296
	"""A spacer just takes up space and doesn't draw anything - it guarantees
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   297
	   a gap between objects."""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   298
	def __init__(self, width, height):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   299
		self.width = width
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   300
		self.height = height
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   301
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   302
	def __repr__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   303
		return "Spacer(%s, %s)" % (self.width, self.height)
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 512
diff changeset
   304
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   305
	def wrap(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   306
		return (self.width, self.height)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   307
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   308
	def draw(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   309
		pass
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   310
307
c439e402b404 Added CondPageBreak
rgbecker
parents: 268
diff changeset
   311
class PageBreak(Spacer):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   312
	"""Move on to the next page in the document.
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   313
	   This works by consuming all remaining space in the frame!"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   314
	def __init__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   315
		pass
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   316
	
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   317
	def __repr__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   318
		return "PageBreak()"
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   319
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   320
	def wrap(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   321
		self.width = availWidth
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   322
		self.height = availHeight
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   323
		return (availWidth,availHeight)  #step back a point
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   324
307
c439e402b404 Added CondPageBreak
rgbecker
parents: 268
diff changeset
   325
class CondPageBreak(Spacer):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   326
	"""Throw a page if not enough vertical space"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   327
	def __init__(self, height):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   328
		self.height = height
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   329
		
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   330
	def __repr__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   331
		return "CondPageBreak(%s)" %(self.height,)
307
c439e402b404 Added CondPageBreak
rgbecker
parents: 268
diff changeset
   332
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   333
	def wrap(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   334
		if availHeight<self.height:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   335
			return (availWidth, availHeight)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   336
		return (0, 0)
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   337
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   338
_SeqTypes = (ListType, TupleType)
558
f9013e25af9d Added a random text module
andy_robinson
parents: 557
diff changeset
   339
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   340
class KeepTogether(Flowable):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   341
	def __init__(self,flowables):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   342
		if type(flowables) not in _SeqTypes:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   343
			self._flowables = [flowables]
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   344
		else:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   345
			self._flowables = flowables
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   346
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   347
	def __repr__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   348
		f = self._flowables
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   349
		L = map(repr,f)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   350
		import string
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   351
		L = "\n"+string.join(L, "\n")
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   352
		L = string.replace(L, "\n", "\n  ")
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   353
		return "KeepTogether(%s) # end KeepTogether" % L
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 512
diff changeset
   354
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   355
	def wrap(self, aW, aH):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   356
		W = 0
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   357
		H = 0
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   358
		F = self._flowables
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   359
		for f in F:
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   360
			w,h = f.wrap(aW,0xfffffff)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   361
			if f is not F[0]: h = h + f.getSpaceBefore()
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   362
			if f is not F[-1]: h = h + f.getSpaceAfter()
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   363
			W = max(W,w)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   364
			H = H+h
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   365
		self._CPage = H>aH
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   366
		return W, 0xffffff	# force a split
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   367
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   368
	def split(self, aW, aH):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   369
		S = self._CPage and [CondPageBreak(aH+1)] or []
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   370
		for f in self._flowables: S.append(f)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   371
		return S
367
ca1adb0294f0 Added KeepTogether
rgbecker
parents: 307
diff changeset
   372
253
cfcf8d555a2c Platypus re-organisation
rgbecker
parents:
diff changeset
   373
class Macro(Flowable):
1426
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   374
	"""This is not actually drawn (i.e. it has zero height)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   375
	but is executed when it would fit in the frame.  Allows direct
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   376
	access to the canvas through the object 'canvas'"""
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   377
	def __init__(self, command):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   378
		self.command = command
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   379
	def __repr__(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   380
		return "Macro(%s)" % repr(self.command)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   381
	def wrap(self, availWidth, availHeight):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   382
		return (0,0)
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   383
	def draw(self):
377351bbe539 Add getKeepWithNext to Flowable
rgbecker
parents: 1360
diff changeset
   384
		exec self.command in globals(), {'canvas':self.canv}