reportlab/platypus/paragraph.py
author rgbecker
Mon, 01 Oct 2001 09:58:42 +0000
changeset 1268 158ffc339d38
parent 1160 2cb58079d830
child 1373 df3383c5f8bc
permissions -rw-r--r--
Fixed slight buglet in checkpagesize
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 488
diff changeset
     1
#copyright ReportLab Inc. 2000
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 488
diff changeset
     2
#see license.txt for license details
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 488
diff changeset
     3
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/paragraph.py?cvsroot=reportlab
1160
2cb58079d830 Removed Aaron's rather thoughtless hacks
rgbecker
parents: 1156
diff changeset
     4
#$Header: /tmp/reportlab/reportlab/platypus/paragraph.py,v 1.57 2001/08/23 08:38:59 rgbecker Exp $
2cb58079d830 Removed Aaron's rather thoughtless hacks
rgbecker
parents: 1156
diff changeset
     5
__version__=''' $Id: paragraph.py,v 1.57 2001/08/23 08:38:59 rgbecker Exp $ '''
938
36f66f88a4a6 Added find to imports
rgbecker
parents: 683
diff changeset
     6
from string import split, strip, join, whitespace, find
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
     7
from operator import truth
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
     8
from types import StringType, ListType
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
     9
from reportlab.pdfbase.pdfmetrics import stringWidth
518
5be3fcb26c78 Semantic Name changes
rgbecker
parents: 516
diff changeset
    10
from reportlab.platypus.paraparser import ParaParser
279
e7d8b3631d5c Global sequencer put in the 'story builder'.
andy_robinson
parents: 268
diff changeset
    11
from reportlab.platypus.flowables import Flowable
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    12
from reportlab.lib.colors import Color
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    13
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
449
1ba0d6fb0f9e XPreformatted fixed empty lines and leading space
rgbecker
parents: 438
diff changeset
    14
from reportlab.lib.utils import _className
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
    15
from copy import deepcopy
518
5be3fcb26c78 Semantic Name changes
rgbecker
parents: 516
diff changeset
    16
from reportlab.lib.abag import ABag
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    17
518
5be3fcb26c78 Semantic Name changes
rgbecker
parents: 516
diff changeset
    18
class ParaLines(ABag):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    19
	"""
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    20
	class ParaLines contains the broken into lines representation of Paragraphs
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    21
		kind=0	Simple
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    22
		fontName, fontSize, textColor apply to whole Paragraph
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    23
		lines	[(extraSpace1,words1),....,(extraspaceN,wordsN)]
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    24
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    25
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    26
		kind==1 Complex
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    27
		lines	[FragLine1,...,FragLineN]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    28
	"""
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    29
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    30
class FragLine(ABag):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    31
	"""class FragLine contains a styled line (ie a line with more than one style)
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
    32
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    33
	extraSpace	unused space for justification only
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    34
	wordCount	1+spaces in line for justification purposes
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    35
	words		[ParaFrags] style text lumps to be concatenated together
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    36
	fontSize	maximum fontSize seen on the line; not used at present,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    37
				but could be used for line spacing.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    38
	"""
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    39
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    40
#our one and only parser
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
    41
# XXXXX if the parser has any internal state using only one is probably a BAD idea!
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    42
_parser=ParaParser()
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    43
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    44
def _lineClean(L):
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    45
	return join(filter(truth,split(strip(L))))
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    46
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
    47
def cleanBlockQuotedText(text,joiner=' '):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    48
	"""This is an internal utility which takes triple-
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    49
	quoted text form within the document and returns
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    50
	(hopefully) the paragraph the user intended originally."""
540
b95b5bc8ff44 Try harder than ever for line cleaning and add bg alias
rgbecker
parents: 539
diff changeset
    51
	L=filter(truth,map(_lineClean, split(text, '\n')))
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    52
	return join(L, joiner)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    53
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    54
def setXPos(tx,dx):
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    55
	if dx>1e-6 or dx<-1e-6:
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    56
		tx.setXPos(dx)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    57
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
    58
def _leftDrawParaLine( tx, offset, extraspace, words, last=0):
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    59
	setXPos(tx,offset)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    60
	tx._textOut(join(words),1)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    61
	setXPos(tx,-offset)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    62
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
    63
def _centerDrawParaLine( tx, offset, extraspace, words, last=0):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    64
	m = offset + 0.5 * extraspace
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    65
	setXPos(tx,m)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    66
	tx._textOut(join(words),1)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    67
	setXPos(tx,-m)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    68
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
    69
def _rightDrawParaLine( tx, offset, extraspace, words, last=0):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    70
	m = offset + extraspace
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    71
	setXPos(tx,m)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    72
	tx._textOut(join(words),1)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    73
	setXPos(tx,-m)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    74
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
    75
def _justifyDrawParaLine( tx, offset, extraspace, words, last=0):
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    76
	setXPos(tx,offset)
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    77
	text  = join(words)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    78
	if last:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    79
		#last one, left align
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    80
		tx._textOut(text,1)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    81
	else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    82
		nSpaces = len(words)-1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    83
		if nSpaces:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    84
			tx.setWordSpace(extraspace / float(nSpaces))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    85
			tx._textOut(text,1)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    86
			tx.setWordSpace(0)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    87
		else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    88
			tx._textOut(text,1)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
    89
	setXPos(tx,-offset)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
    90
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
    91
def _putFragLine(tx,words):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    92
	for f in words:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    93
		if hasattr(f,'cbDefn'):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    94
			func = getattr(tx._canvas,f.cbDefn.name,None)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    95
			if not func:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    96
				raise AttributeError, "Missing %s callback attribute '%s'" % (f.cbDefn.kind,f.cbDefn.name)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    97
			func(tx._canvas,f.cbDefn.kind,f.cbDefn.label)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    98
			if f is words[-1]: tx._textOut('',1)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
    99
		else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   100
			if (tx._fontname,tx._fontsize)!=(f.fontName,f.fontSize):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   101
				tx._setFont(f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   102
			if tx.XtraState.textColor!=f.textColor:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   103
				tx.XtraState.textColor = f.textColor
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   104
				tx.setFillColor(f.textColor)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   105
			if tx.XtraState.rise!=f.rise:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   106
				tx.XtraState.rise=f.rise
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   107
				tx.setRise(f.rise)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   108
			tx._textOut(f.text,f is words[-1])	# cheap textOut
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   109
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   110
def _leftDrawParaLineX( tx, offset, line, last=0):
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   111
	setXPos(tx,offset)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   112
	_putFragLine(tx, line.words)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   113
	setXPos(tx,-offset)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   114
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   115
def _centerDrawParaLineX( tx, offset, line, last=0):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   116
	m = offset+0.5*line.extraSpace
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   117
	setXPos(tx,m)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   118
	_putFragLine(tx, line.words)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   119
	setXPos(tx,-m)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   120
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   121
def _rightDrawParaLineX( tx, offset, line, last=0):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   122
	m = offset+line.extraSpace
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   123
	setXPos(tx,m)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   124
	_putFragLine(tx, line.words)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   125
	setXPos(tx,-m)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   126
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   127
def _justifyDrawParaLineX( tx, offset, line, last=0):
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   128
	setXPos(tx,offset)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   129
	if last:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   130
		#last one, left align
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   131
		_putFragLine(tx, line.words)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   132
	else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   133
		nSpaces = line.wordCount - 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   134
		if nSpaces:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   135
			tx.setWordSpace(line.extraSpace / float(nSpaces))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   136
			_putFragLine(tx, line.words)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   137
			tx.setWordSpace(0)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   138
		else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   139
			_putFragLine(tx, line.words)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   140
	setXPos(tx,-offset)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   141
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   142
def _sameFrag(f,g):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   143
	'returns 1 if two ParaFrags map out the same'
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   144
	if hasattr(f,'cbDefn') or hasattr(g,'cbDefn'): return 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   145
	for a in ('fontName', 'fontSize', 'textColor', 'rise'):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   146
		if getattr(f,a)!=getattr(g,a): return 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   147
	return 1
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   148
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   149
def _getFragWords(frags):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   150
	''' given a Parafrag list return a list of fragwords
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   151
		[[size, (f00,w00), ..., (f0n,w0n)],....,[size, (fm0,wm0), ..., (f0n,wmn)]]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   152
		each pair f,w represents a style and some string
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   153
		each sublist represents a word
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   154
	'''
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   155
	R = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   156
	W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   157
	n = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   158
	for f in frags:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   159
		text = f.text
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   160
		#del f.text # we can't do this until we sort out splitting
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   161
					# of paragraphs
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   162
		if text!='':
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   163
			S = split(text)
543
7cdeef1a500a Delete fix
rgbecker
parents: 542
diff changeset
   164
			if S==[]: S = ['']
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   165
			if W!=[] and text[0] in whitespace:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   166
				W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   167
				R.append(W)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   168
				W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   169
				n = 0
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   170
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   171
			for w in S[:-1]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   172
				W.append((f,w))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   173
				n = n + stringWidth(w, f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   174
				W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   175
				R.append(W)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   176
				W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   177
				n = 0
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   178
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   179
			w = S[-1]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   180
			W.append((f,w))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   181
			n = n + stringWidth(w, f.fontName, f.fontSize)
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   182
			if text[-1] in whitespace:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   183
				W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   184
				R.append(W)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   185
				W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   186
				n = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   187
		elif hasattr(f,'cbDefn'):
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   188
			W.append((f,''))
508
37dc6fc3fa65 More <onDraw> hacks
rgbecker
parents: 506
diff changeset
   189
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   190
	if W!=[]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   191
		W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   192
		R.append(W)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   193
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   194
	return R
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   195
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   196
def _split_blParaSimple(blPara,start,stop):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   197
	f = blPara.clone()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   198
	for a in ('lines', 'kind', 'text'):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   199
		if hasattr(f,a): delattr(f,a)
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   200
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   201
	f.words = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   202
	for l in blPara.lines[start:stop]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   203
		for w in l[1]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   204
			f.words.append(w)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   205
	return [f]
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   206
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   207
def _split_blParaHard(blPara,start,stop):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   208
	f = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   209
	lines = blPara.lines[start:stop]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   210
	for l in lines:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   211
		for w in l.words:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   212
			f.append(w)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   213
		if l is not lines[-1]:
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   214
			i = len(f)-1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   215
			while hasattr(f[i],'cbDefn'): i = i-1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   216
			g = f[i]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   217
			if g.text[-1]!=' ': g.text = g.text+' '
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   218
	return f
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   219
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   220
def _drawBullet(canvas, offset, cur_y, bulletText, style):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   221
	'''draw a bullet text could be a simple string or a frag list'''
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   222
	tx2 = canvas.beginText(style.bulletIndent, cur_y)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   223
	tx2.setFont(style.bulletFontName, style.bulletFontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   224
	tx2.setFillColor(hasattr(style,'bulletColor') and style.bulletColor or style.textColor)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   225
	if type(bulletText) is StringType:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   226
		tx2.textOut(bulletText)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   227
	else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   228
		for f in bulletText:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   229
			tx2.setFont(f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   230
			tx2.setFillColor(f.textColor)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   231
			tx2.textOut(f.text)
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   232
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   233
	bulletEnd = tx2.getX()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   234
	offset = max(offset, bulletEnd - style.leftIndent)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   235
	canvas.drawText(tx2)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   236
	return offset
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   237
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   238
def _handleBulletWidth(bulletText,style,maxWidths):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   239
	'''work out bullet width and adjust maxWidths[0] if neccessary
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   240
	'''
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   241
	if bulletText <> None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   242
		if type(bulletText) is StringType:
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   243
			bulletWidth = stringWidth( bulletText, style.bulletFontName, style.bulletFontSize)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   244
		else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   245
			#it's a list of fragments
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   246
			bulletWidth = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   247
			for f in bulletText:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   248
				bulletWidth = bulletWidth + stringWidth(f.text, f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   249
		bulletRight = style.bulletIndent + bulletWidth
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   250
		indent = style.leftIndent+style.firstLineIndent
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   251
		if bulletRight > indent:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   252
			#..then it overruns, and we have less space available on line 1
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   253
			maxWidths[0] = maxWidths[0] - (bulletRight - indent)
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   254
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   255
def	splitLines0(frags,widths):
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   256
	'''
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   257
	given a list of ParaFrags we return a list of ParaLines
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   258
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   259
	each ParaLine has
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   260
	1)	ExtraSpace
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   261
	2)	blankCount
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   262
	3)	[textDefns....]
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   263
		each text definition is a (ParaFrag, start, limit) triplet
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   264
	'''
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   265
	#initialise the algorithm
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   266
	lines	= []
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   267
	lineNum	= 0
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   268
	maxW	= widths[lineNum]
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   269
	i		= -1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   270
	l		= len(frags)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   271
	lim		= start = 0
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   272
	while 1:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   273
		#find a non whitespace character
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   274
		while i<l:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   275
			while start<lim and text[start]==' ': start=start+1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   276
			if start==lim:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   277
				i = i + 1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   278
				if i==l: break
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   279
				start = 0
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   280
				f = frags[i]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   281
				text = f.text
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   282
				lim	= len(text)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   283
			else:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   284
				break	# we found one
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   285
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   286
		if start==lim: break	#if we didn't find one we are done
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   287
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   288
		#start of a line
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   289
		g		= (None,None,None)
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   290
		line	= []
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   291
		cLen	= 0
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   292
		nSpaces	= 0
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   293
		while cLen<maxW:
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   294
			j = find(text,' ',start)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   295
			if j<0: j==lim
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   296
			w = stringWidth(text[start:j],f.fontName,f.fontSize)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   297
			cLen = cLen + w
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   298
			if cLen>maxW and line!=[]:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   299
				cLen = cLen-w
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   300
				#this is the end of the line
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   301
				while g.text[lim]==' ':
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   302
					lim = lim - 1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   303
					nSpaces = nSpaces-1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   304
				break
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   305
			if j<0: j = lim
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   306
			if g[0] is f: g[2] = j	#extend
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   307
			else:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   308
				g = (f,start,j)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   309
				line.append(g)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   310
			if j==lim:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   311
				i=i+1
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   312
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   313
class Paragraph(Flowable):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   314
	""" Paragraph(text, style, bulletText=None)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   315
		text a string of stuff to go into the paragraph.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   316
		style is a style definition as in reportlab.lib.styles.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   317
		bulletText is an optional bullet defintion.
316
e15cf6a28eb8 Documentation fixes
rgbecker
parents: 302
diff changeset
   318
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   319
		This class is a flowable that can format a block of text
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   320
		into a paragraph with a given style.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   321
	
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   322
		The paragraph Text can contain XML-like markup including the tags:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   323
		<b> ... </b> - bold
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   324
		<i> ... </i> - italics
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   325
		<u> ... </u> - underline
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   326
		<super> ... </super> - superscript
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   327
		<sub> ... </sub> - subscript
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   328
		<font name=fontfamily/fontname color=colorname size=float>
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   329
		<onDraw name=callable label="a label">
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
   330
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   331
		The whole may be surrounded by <para> </para> tags
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
   332
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   333
		It will also be able to handle any MathML specified Greek characters.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   334
	"""
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   335
	def __init__(self, text, style, bulletText = None, frags=None):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   336
		self._setup(text, style, bulletText, frags, cleanBlockQuotedText)
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   337
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   338
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   339
	def __repr__(self):
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   340
		import string
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   341
		n = self.__class__.__name__
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   342
		L = [n+"("]
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   343
		keys = self.__dict__.keys()
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   344
		for k in keys:
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   345
			v = getattr(self, k)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   346
			rk = repr(k)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   347
			rv = repr(v)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   348
			rk = "  "+string.replace(rk, "\n", "\n  ")
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   349
			rv = "    "+string.replace(rv, "\n", "\n    ")
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   350
			L.append(rk)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   351
			L.append(rv)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   352
		L.append(") #"+n)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   353
		return string.join(L, "\n")		
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   354
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   355
	def _setup(self, text, style, bulletText, frags, cleaner):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   356
		if frags is None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   357
			text = cleaner(text)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   358
			style, frags, bulletTextFrags = _parser.parse(text,style)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   359
			if frags is None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   360
				raise "xml parser error (%s) in paragraph beginning\n'%s'"\
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   361
					% (_parser.errors[0],text[:min(30,len(text))])
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   362
			if bulletTextFrags: bulletText = bulletTextFrags
279
e7d8b3631d5c Global sequencer put in the 'story builder'.
andy_robinson
parents: 268
diff changeset
   363
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   364
		#AR hack
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   365
		self.text = text
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   366
		self.frags = frags
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   367
		self.style = style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   368
		self.bulletText = bulletText
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   369
		self.debug = 0	#turn this on to see a pretty one with all the margins etc.
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   370
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   371
	def wrap(self, availWidth, availHeight):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   372
		# work out widths array for breaking
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   373
		self.width = availWidth
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   374
		leftIndent = self.style.leftIndent
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   375
		first_line_width = availWidth - (leftIndent+self.style.firstLineIndent) - self.style.rightIndent
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   376
		later_widths = availWidth - leftIndent - self.style.rightIndent
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   377
		self.blPara = self.breakLines([first_line_width, later_widths])
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   378
		self.height = len(self.blPara.lines) * self.style.leading
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   379
		return (self.width, self.height)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   380
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   381
	def minWidth(self):
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   382
		'Attempt to determine a minimum sensible width'
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   383
		frags = self.frags
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   384
		nFrags= len(frags)
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   385
		if nFrags==1:
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   386
			f = frags[0]
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   387
			fS = f.fontSize
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   388
			fN = f.fontName
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   389
			words = hasattr(f,'text') and split(f.text, ' ') or f.words
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   390
			func = lambda w, fS=fS, fN=fN: stringWidth(w,fN,fS)
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   391
		else:
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   392
			words = _getFragWords(frags)
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   393
			func  = lambda x: x[0]
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   394
		return max(map(func,words))
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   395
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   396
	def _get_split_blParaFunc(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   397
		return self.blPara.kind==0 and _split_blParaSimple or _split_blParaHard
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   398
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   399
	def split(self,availWidth, availHeight):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   400
		if len(self.frags)<=0: return []
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   401
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   402
		#the split information is all inside self.blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   403
		if not hasattr(self,'blPara'):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   404
			self.wrap(availWidth,availHeight)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   405
		blPara = self.blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   406
		style = self.style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   407
		leading = style.leading
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   408
		lines = blPara.lines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   409
		n = len(lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   410
		s = int(availHeight/leading)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   411
		if s<=1: return []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   412
		if n<=s: return [self]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   413
		func = self._get_split_blParaFunc()
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   414
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   415
		P1=self.__class__(None,style,bulletText=self.bulletText,frags=func(blPara,0,s))
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   416
		#this is a major hack
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   417
		P1.blPara = ParaLines(kind=1,lines=blPara.lines[0:s],aH=availHeight,aW=availWidth)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   418
		P1._JustifyLast = 1
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   419
		if style.firstLineIndent != 0:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   420
			style = deepcopy(style)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   421
			style.firstLineIndent = 0
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   422
		P2=self.__class__(None,style,bulletText=None,frags=func(blPara,s,n))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   423
		return [P1,P2]
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   424
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   425
	def draw(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   426
		#call another method for historical reasons.  Besides, I
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   427
		#suspect I will be playing with alternate drawing routines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   428
		#so not doing it here makes it easier to switch.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   429
		self.drawPara(self.debug)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   430
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   431
	def breakLines(self, width):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   432
		"""
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   433
		Returns a broken line structure. There are two cases
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   434
		
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   435
		A) For the simple case of a single formatting input fragment the output is
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   436
			A fragment specifier with
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   437
				kind = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   438
				fontName, fontSize, leading, textColor
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   439
				lines=	A list of lines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   440
						Each line has two items.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   441
						1) unused width in points
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   442
						2) word list
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   443
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   444
		B) When there is more than one input formatting fragment the out put is
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   445
			A fragment specifier with
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   446
				kind = 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   447
				lines=	A list of fragments each having fields
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   448
							extraspace (needed for justified)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   449
							fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   450
							words=word list
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   451
								each word is itself a fragment with
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   452
								various settings
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   453
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   454
		This structure can be used to easily draw paragraphs with the various alignments.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   455
		You can supply either a single width or a list of widths; the latter will have its
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   456
		last item repeated until necessary. A 2-element list is useful when there is a
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   457
		different first line indent; a longer list could be created to facilitate custom wraps
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   458
		around irregular objects."""
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   459
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   460
		if type(width) <> ListType: maxWidths = [width]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   461
		else: maxWidths = width
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   462
		lines = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   463
		lineno = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   464
		style = self.style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   465
		fFontSize = float(style.fontSize)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   466
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   467
		#for bullets, work out width and ensure we wrap the right amount onto line one
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   468
		_handleBulletWidth(self.bulletText,style,maxWidths)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   469
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   470
		maxWidth = maxWidths[lineno]
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   471
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   472
		self.height = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   473
		frags = self.frags
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   474
		nFrags= len(frags)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   475
		if nFrags==1:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   476
			f = frags[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   477
			fontSize = f.fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   478
			fontName = f.fontName
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   479
			words = hasattr(f,'text') and split(f.text, ' ') or f.words
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   480
			spaceWidth = stringWidth(' ', fontName, fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   481
			cLine = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   482
			currentWidth = - spaceWidth   # hack to get around extra space for word 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   483
			for word in words:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   484
				wordWidth = stringWidth(word, fontName, fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   485
				newWidth = currentWidth + spaceWidth + wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   486
				if newWidth<=maxWidth or len(cLine)==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   487
					# fit one more on this line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   488
					cLine.append(word)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   489
					currentWidth = newWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   490
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   491
					if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   492
					#end of line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   493
					lines.append((maxWidth - currentWidth, cLine))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   494
					cLine = [word]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   495
					currentWidth = wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   496
					lineno = lineno + 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   497
					try:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   498
						maxWidth = maxWidths[lineno]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   499
					except IndexError:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   500
						maxWidth = maxWidths[-1]  # use the last one
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   501
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   502
			#deal with any leftovers on the final line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   503
			if cLine!=[]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   504
				if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   505
				lines.append((maxWidth - currentWidth, cLine))
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   506
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   507
			return f.clone(kind=0, lines=lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   508
		elif nFrags<=0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   509
			return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   510
							textColor=style.textColor, lines=[])
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   511
		else:
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   512
			if hasattr(self,'blPara'):
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   513
				#NB this is an utter hack that awaits the proper information
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   514
				#preserving splitting algorithm
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   515
				return self.blPara
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   516
			n = 0
553
7a1834c1f32b More Dinu related fixes/edits
rgbecker
parents: 551
diff changeset
   517
			nSp = 0
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   518
			for w in _getFragWords(frags):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   519
				spaceWidth = stringWidth(' ',w[-1][0].fontName, w[-1][0].fontSize)
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   520
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   521
				if n==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   522
					currentWidth = -spaceWidth	 # hack to get around extra space for word 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   523
					words = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   524
					maxSize = 0
496
bb47cf5c2739 Layout error fixes
rgbecker
parents: 494
diff changeset
   525
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   526
				wordWidth = w[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   527
				f = w[1][0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   528
				if wordWidth>0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   529
					newWidth = currentWidth + spaceWidth + wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   530
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   531
					newWidth = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   532
				if newWidth<=maxWidth or n==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   533
					# fit one more on this line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   534
					n = n + 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   535
					maxSize = max(maxSize,f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   536
					nText = w[1][1]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   537
					if words==[]:
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   538
						g = f.clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   539
						words = [g]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   540
						g.text = nText
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   541
					elif not _sameFrag(g,f):
553
7a1834c1f32b More Dinu related fixes/edits
rgbecker
parents: 551
diff changeset
   542
						if currentWidth>0 and ((nText!='' and nText[0]!=' ') or hasattr(f,'cbDefn')):
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   543
							if hasattr(g,'cbDefn'):
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   544
								i = len(words)-1
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   545
								while hasattr(words[i],'cbDefn'): i = i-1
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   546
								words[i].text = words[i].text + ' '
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   547
							else:
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   548
								g.text = g.text + ' '
553
7a1834c1f32b More Dinu related fixes/edits
rgbecker
parents: 551
diff changeset
   549
							nSp = nSp + 1
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   550
						g = f.clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   551
						words.append(g)
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   552
						g.text = nText
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   553
					else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   554
						if nText!='' and nText[0]!=' ':
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   555
							g.text = g.text + ' ' + nText
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   556
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   557
					for i in w[2:]:
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   558
						g = i[0].clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   559
						g.text=i[1]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   560
						words.append(g)
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   561
						maxSize = max(maxSize,g.fontSize)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   562
						
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   563
					currentWidth = newWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   564
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   565
					if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   566
					#end of line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   567
					lines.append(FragLine(extraSpace=(maxWidth - currentWidth),wordCount=n,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   568
										words=words, fontSize=maxSize))
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   569
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   570
					#start new line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   571
					lineno = lineno + 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   572
					try:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   573
						maxWidth = maxWidths[lineno]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   574
					except IndexError:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   575
						maxWidth = maxWidths[-1]  # use the last one
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   576
					currentWidth = wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   577
					n = 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   578
					maxSize = f.fontSize
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   579
					g = f.clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   580
					words = [g]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   581
					g.text = w[1][1]
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   582
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   583
					for i in w[2:]:
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   584
						g = i[0].clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   585
						g.text=i[1]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   586
						words.append(g)
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   587
						maxSize = max(maxSize,g.fontSize)
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   588
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   589
			#deal with any leftovers on the final line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   590
			if words<>[]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   591
				if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   592
				lines.append(ParaLines(extraSpace=(maxWidth - currentWidth),wordCount=n,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   593
									words=words, fontSize=maxSize))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   594
			return ParaLines(kind=1, lines=lines)
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   595
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   596
		return lines
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   597
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   598
	def drawPara(self,debug=0):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   599
		"""Draws a paragraph according to the given style.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   600
		Returns the final y position at the bottom. Not safe for
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   601
		paragraphs without spaces e.g. Japanese; wrapping
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   602
		algorithm will go infinite."""
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   603
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   604
		#stash the key facts locally for speed
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   605
		canvas = self.canv
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   606
		style = self.style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   607
		blPara = self.blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   608
		lines = blPara.lines
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   609
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   610
		#work out the origin for line 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   611
		cur_x = style.leftIndent
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   612
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   613
		#if has a background, draw it
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   614
		if style.backColor:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   615
			canvas.saveState()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   616
			canvas.setFillColor(style.backColor)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   617
			canvas.rect(style.leftIndent, 
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   618
						0,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   619
						self.width - style.rightIndent,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   620
						self.height,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   621
						fill=1,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   622
						stroke=0)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   623
			canvas.restoreState()
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   624
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   625
		if debug:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   626
			# This boxes and shades stuff to show how the paragraph
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   627
			# uses its space.  Useful for self-documentation so
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   628
			# the debug code stays!
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   629
			# box the lot
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   630
			canvas.rect(0, 0, self.width, self.height)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   631
			#left and right margins
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   632
			canvas.saveState()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   633
			canvas.setFillColor(Color(0.9,0.9,0.9))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   634
			canvas.rect(0, 0, style.leftIndent, self.height)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   635
			canvas.rect(self.width - style.rightIndent, 0, style.rightIndent, self.height)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   636
			# shade above and below
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   637
			canvas.setFillColor(Color(1.0,1.0,0.0))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   638
			canvas.restoreState()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   639
			#self.drawLine(x + style.leftIndent, y, x + style.leftIndent, cur_y)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   640
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   641
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   642
		nLines = len(lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   643
		bulletText = self.bulletText
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   644
		if nLines > 0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   645
			canvas.saveState()
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   646
			#canvas.addLiteral('%% %s.drawPara' % _className(self))
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   647
			alignment = style.alignment
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   648
			offset = style.firstLineIndent
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   649
			lim = nLines-1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   650
			noJustifyLast = not (hasattr(self,'_JustifyLast') and self._JustifyLast)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   651
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   652
			if blPara.kind==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   653
				if alignment == TA_LEFT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   654
					dpl = _leftDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   655
				elif alignment == TA_CENTER:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   656
					dpl = _centerDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   657
				elif self.style.alignment == TA_RIGHT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   658
					dpl = _rightDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   659
				elif self.style.alignment == TA_JUSTIFY:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   660
					dpl = _justifyDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   661
				f = blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   662
				cur_y = self.height - f.fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   663
				if bulletText <> None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   664
					offset = _drawBullet(canvas,offset,cur_y,bulletText,style)
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   665
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   666
				#set up the font etc.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   667
				canvas._code.append('%s %s %s rg' % (f.textColor.red, f.textColor.green, f.textColor.blue))
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   668
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   669
				tx = canvas.beginText(cur_x, cur_y)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   670
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   671
				#now the font for the rest of the paragraph
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   672
				tx.setFont(f.fontName, f.fontSize, style.leading)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   673
				dpl( tx, offset, lines[0][0], lines[0][1], noJustifyLast and nLines==1)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   674
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   675
				#now the middle of the paragraph, aligned with the left margin which is our origin.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   676
				for i in range(1, nLines):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   677
					dpl( tx, 0, lines[i][0], lines[i][1], noJustifyLast and i==lim)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   678
			else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   679
				f = lines[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   680
				cur_y = self.height - f.fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   681
				# default?
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   682
				dpl = _leftDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   683
				if bulletText <> None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   684
					offset = _drawBullet(canvas,offset,cur_y,bulletText,style)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   685
				if alignment == TA_LEFT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   686
					dpl = _leftDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   687
				elif alignment == TA_CENTER:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   688
					dpl = _centerDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   689
				elif self.style.alignment == TA_RIGHT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   690
					dpl = _rightDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   691
				elif self.style.alignment == TA_JUSTIFY:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   692
					dpl = _justifyDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   693
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   694
					raise ValueError, "bad align %s" % repr(alignment)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   695
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   696
				#set up the font etc.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   697
				tx = canvas.beginText(cur_x, cur_y)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   698
				tx.XtraState=ABag()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   699
				tx.XtraState.textColor=None
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   700
				tx.XtraState.rise=0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   701
				tx.setLeading(style.leading)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   702
				#f = lines[0].words[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   703
				#tx._setFont(f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   704
				tx._fontname,tx._fontsize = None, None
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   705
				dpl( tx, offset, lines[0], noJustifyLast and nLines==1)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   706
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   707
				#now the middle of the paragraph, aligned with the left margin which is our origin.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   708
				for i in range(1, nLines):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   709
					f = lines[i]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   710
					dpl( tx, 0, f, noJustifyLast and i==lim)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   711
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   712
			canvas.drawText(tx)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   713
			canvas.restoreState()
284
eabeb5f4e851 Added UserDocTemplate class, and paragraph.getPlainText()
andy_robinson
parents: 279
diff changeset
   714
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   715
	def getPlainText(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   716
		"""Convenience function for templates which want access
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   717
		to the raw text, without XML tags. """
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   718
		plains = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   719
		for frag in self.frags:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   720
			plains.append(frag.text)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   721
		return join(plains, '')
302
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   722
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   723
	def getActualLineWidths0(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   724
		"""Convenience function; tells you how wide each line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   725
		actually is.  For justified styles, this will be
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   726
		the same as the wrap width; for others it might be
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   727
		useful for seeing if paragraphs will fit in spaces."""
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   728
		assert hasattr(self, 'width'), "Cannot call this method before wrap()"
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   729
		w = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   730
		for frag in self.blPara.lines:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   731
			w.append(self.width - frag.extraSpace)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   732
		return w
497
63f575fc1170 Added experimental method getActualLineWidths0
andy_robinson
parents: 496
diff changeset
   733
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   734
if __name__=='__main__':	#NORUNTESTS
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   735
	def dumpParagraphLines(P):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   736
		print 'dumpParagraphLines(<Paragraph @ %d>)' % id(P)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   737
		lines = P.blPara.lines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   738
		n =len(lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   739
		for l in range(n):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   740
			line = lines[l]
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   741
			if hasattr(line,'words'):
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   742
				words = line.words
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   743
			else:
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   744
				words = line[1]
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   745
			nwords = len(words)
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   746
			print 'line%d: %d(%s)\n  ' % (l,nwords,str(getattr(line,'wordCount','Unknown'))),
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   747
			for w in range(nwords):
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   748
				print "%d:'%s'"%(w,getattr(words[w],'text',words[w])),
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   749
			print
302
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   750
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   751
	def dumpParagraphFrags(P):
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   752
		print 'dumpParagraphFrags(<Paragraph @ %d>) minWidth() = %.2f' % (id(P), P.minWidth())
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   753
		frags = P.frags
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   754
		n =len(frags)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   755
		for l in range(n):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   756
			print "frag%d: '%s'" % (l, frags[l].text)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   757
	
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   758
		l = 0
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   759
		cum = 0
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   760
		for W in _getFragWords(frags):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   761
			cum = cum + W[0]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   762
			print "fragword%d: cum=%3d size=%d" % (l, cum, W[0]),
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   763
			for w in W[1:]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   764
				print "'%s'" % w[1],
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   765
			print
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   766
			l = l + 1
434
257af3109bf4 Various brutal changes to paragraph, canvas and textobject for speed/size
rgbecker
parents: 383
diff changeset
   767
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   768
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   769
	from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   770
	import sys
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   771
	TESTS = sys.argv[1:]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   772
	if TESTS==[]: TESTS=['4']
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   773
	def flagged(i,TESTS=TESTS):
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   774
		return 'all' in TESTS or '*' in TESTS or str(i) in TESTS
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   775
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   776
	styleSheet = getSampleStyleSheet()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   777
	B = styleSheet['BodyText']
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   778
	style = ParagraphStyle("discussiontext", parent=B)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   779
	style.fontName= 'Helvetica'
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   780
	if flagged(1):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   781
		text='''The <font name=courier color=green>CMYK</font> or subtractive method follows the way a printer
302
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   782
mixes three pigments (cyan, magenta, and yellow) to form colors.
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   783
Because mixing chemicals is more difficult than combining light there
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   784
is a fourth parameter for darkness.  For example a chemical
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   785
combination of the <font name=courier color=green>CMY</font> pigments generally never makes a perfect
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   786
black -- instead producing a muddy color -- so, to get black printers
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   787
don't use the <font name=courier color=green>CMY</font> pigments but use a direct black ink.  Because
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   788
<font name=courier color=green>CMYK</font> maps more directly to the way printer hardware works it may
434
257af3109bf4 Various brutal changes to paragraph, canvas and textobject for speed/size
rgbecker
parents: 383
diff changeset
   789
be the case that &amp;| &amp; | colors specified in <font name=courier color=green>CMYK</font> will provide better fidelity
302
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   790
and better control when printed.
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   791
'''
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   792
		P=Paragraph(text,style)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   793
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   794
		aW, aH = 456.0, 42.8
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   795
		w,h = P.wrap(aW, aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   796
		dumpParagraphLines(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   797
		S = P.split(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   798
		for s in S:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   799
			s.wrap(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   800
			dumpParagraphLines(s)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   801
			aH = 500
488
a270e8b45200 Added J Alet's bug case
rgbecker
parents: 471
diff changeset
   802
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   803
	if flagged(2):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   804
		P=Paragraph("""Price<super><font color="red">*</font></super>""", styleSheet['Normal'])
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   805
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   806
		w,h = P.wrap(24, 200)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   807
		dumpParagraphLines(P)
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   808
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   809
	if flagged(3):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   810
		text = """Dieses Kapitel bietet eine schnelle <b><font color=red>Programme :: starten</font></b>
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   811
<onDraw name=myIndex label="Programme :: starten">
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   812
<b><font color=red>Eingabeaufforderung :: (&gt;&gt;&gt;)</font></b>
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   813
<onDraw name=myIndex label="Eingabeaufforderung :: (&gt;&gt;&gt;)">
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   814
<b><font color=red>&gt;&gt;&gt; (Eingabeaufforderung)</font></b>
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   815
<onDraw name=myIndex label="&gt;&gt;&gt; (Eingabeaufforderung)">
681
934a4f24ea5d Added explicit font and encoding support
andy_robinson
parents: 553
diff changeset
   816
Einf\374hrung in Python <b><font color=red>Python :: Einf\374hrung</font></b>
934a4f24ea5d Added explicit font and encoding support
andy_robinson
parents: 553
diff changeset
   817
<onDraw name=myIndex label="Python :: Einf\374hrung">.
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   818
Das Ziel ist, die grundlegenden Eigenschaften von Python darzustellen, ohne
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   819
sich zu sehr in speziellen Regeln oder Details zu verstricken. Dazu behandelt
681
934a4f24ea5d Added explicit font and encoding support
andy_robinson
parents: 553
diff changeset
   820
dieses Kapitel kurz die wesentlichen Konzepte wie Variablen, Ausdr\374cke,
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   821
Kontrollfluss, Funktionen sowie Ein- und Ausgabe. Es erhebt nicht den Anspruch,
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   822
umfassend zu sein."""
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   823
		P=Paragraph(text, styleSheet['Code'])
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   824
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   825
		w,h = P.wrap(6*72, 9.7*72)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   826
		dumpParagraphLines(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   827
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   828
	if flagged(4):
681
934a4f24ea5d Added explicit font and encoding support
andy_robinson
parents: 553
diff changeset
   829
		text='''Die eingebaute Funktion <font name=Courier>range(i, j [, stride])</font><onDraw name=myIndex label="eingebaute Funktionen::range()"><onDraw name=myIndex label="range() (Funktion)"><onDraw name=myIndex label="Funktionen::range()"> erzeugt eine Liste von Ganzzahlen und f\374llt sie mit Werten <font name=Courier>k</font>, f\374r die gilt: <font name=Courier>i &lt;= k &lt; j</font>. Man kann auch eine optionale Schrittweite angeben. Die eingebaute Funktion <font name=Courier>xrange()</font><onDraw name=myIndex label="eingebaute Funktionen::xrange()"><onDraw name=myIndex label="xrange() (Funktion)"><onDraw name=myIndex label="Funktionen::xrange()"> erf\374llt einen \344hnlichen Zweck, gibt aber eine unver\344nderliche Sequenz vom Typ <font name=Courier>XRangeType</font><onDraw name=myIndex label="XRangeType"> zur\374ck. Anstatt alle Werte in der Liste abzuspeichern, berechnet diese Liste ihre Werte, wann immer sie angefordert werden. Das ist sehr viel speicherschonender, wenn mit sehr langen Listen von Ganzzahlen gearbeitet wird. <font name=Courier>XRangeType</font> kennt eine einzige Methode, <font name=Courier>s.tolist()</font><onDraw name=myIndex label="XRangeType::tolist() (Methode)"><onDraw name=myIndex label="s.tolist() (Methode)"><onDraw name=myIndex label="Methoden::s.tolist()">, die seine Werte in eine Liste umwandelt.'''
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   830
		aW = 420
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   831
		aH = 64.4
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   832
		P=Paragraph(text, B)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   833
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   834
		w,h = P.wrap(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   835
		print 'After initial wrap',w,h
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   836
		dumpParagraphLines(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   837
		S = P.split(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   838
		dumpParagraphFrags(S[0])
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   839
		w0,h0 = S[0].wrap(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   840
		print 'After split wrap',w0,h0
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   841
		dumpParagraphLines(S[0])
683
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   842
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   843
	if flagged(5):
1001
84d63f4312a9 Remove explicit � character to stop Dinu moaning
rgbecker
parents: 987
diff changeset
   844
		text = '<para> %s <![CDATA[</font></b>& %s < >]]></para>' % (chr(163),chr(163))
683
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   845
		P=Paragraph(text, styleSheet['Code'])
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   846
		dumpParagraphFrags(P)
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   847
		w,h = P.wrap(6*72, 9.7*72)
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   848
		dumpParagraphLines(P)