reportlab/platypus/paragraph.py
author andy_robinson
Mon, 26 Nov 2001 21:49:01 +0000
changeset 1440 243d35446390
parent 1398 4bb93ead7e52
child 1677 1450177dd19e
permissions -rw-r--r--
Removed 0 from multiBuild stuff prior to further changes; ensured test suite really does run silently when making manuals.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 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
1398
4bb93ead7e52 Tidied up bullets further
andy_robinson
parents: 1397
diff changeset
     4
#$Header: /tmp/reportlab/reportlab/platypus/paragraph.py,v 1.60 2001/11/05 07:57:16 andy_robinson Exp $
4bb93ead7e52 Tidied up bullets further
andy_robinson
parents: 1397
diff changeset
     5
__version__=''' $Id: paragraph.py,v 1.60 2001/11/05 07:57:16 andy_robinson 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
1373
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   142
try:
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   143
	from _rl_accel import _sameFrag
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   144
except:
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   145
	def _sameFrag(f,g):
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   146
		'returns 1 if two ParaFrags map out the same'
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   147
		if hasattr(f,'cbDefn') or hasattr(g,'cbDefn'): return 0
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   148
		for a in ('fontName', 'fontSize', 'textColor', 'rise'):
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   149
			if getattr(f,a)!=getattr(g,a): return 0
df3383c5f8bc Added accelerated _sameFrag
rgbecker
parents: 1160
diff changeset
   150
		return 1
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   151
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   152
def _getFragWords(frags):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   153
	''' given a Parafrag list return a list of fragwords
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   154
		[[size, (f00,w00), ..., (f0n,w0n)],....,[size, (fm0,wm0), ..., (f0n,wmn)]]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   155
		each pair f,w represents a style and some string
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   156
		each sublist represents a word
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   157
	'''
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   158
	R = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   159
	W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   160
	n = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   161
	for f in frags:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   162
		text = f.text
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   163
		#del f.text # we can't do this until we sort out splitting
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   164
					# of paragraphs
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   165
		if text!='':
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   166
			S = split(text)
543
7cdeef1a500a Delete fix
rgbecker
parents: 542
diff changeset
   167
			if S==[]: S = ['']
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   168
			if W!=[] and text[0] in whitespace:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   169
				W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   170
				R.append(W)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   171
				W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   172
				n = 0
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   173
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   174
			for w in S[:-1]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   175
				W.append((f,w))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   176
				n = n + stringWidth(w, f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   177
				W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   178
				R.append(W)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   179
				W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   180
				n = 0
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   181
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   182
			w = S[-1]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   183
			W.append((f,w))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   184
			n = n + stringWidth(w, f.fontName, f.fontSize)
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   185
			if text[-1] in whitespace:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   186
				W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   187
				R.append(W)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   188
				W = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   189
				n = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   190
		elif hasattr(f,'cbDefn'):
542
4b770e4f149d Fixed Dinu's tagmadness4 problem
rgbecker
parents: 541
diff changeset
   191
			W.append((f,''))
508
37dc6fc3fa65 More <onDraw> hacks
rgbecker
parents: 506
diff changeset
   192
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   193
	if W!=[]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   194
		W.insert(0,n)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   195
		R.append(W)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   196
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   197
	return R
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   198
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   199
def _split_blParaSimple(blPara,start,stop):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   200
	f = blPara.clone()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   201
	for a in ('lines', 'kind', 'text'):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   202
		if hasattr(f,a): delattr(f,a)
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   203
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   204
	f.words = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   205
	for l in blPara.lines[start:stop]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   206
		for w in l[1]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   207
			f.words.append(w)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   208
	return [f]
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   209
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   210
def _split_blParaHard(blPara,start,stop):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   211
	f = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   212
	lines = blPara.lines[start:stop]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   213
	for l in lines:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   214
		for w in l.words:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   215
			f.append(w)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   216
		if l is not lines[-1]:
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   217
			i = len(f)-1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   218
			while hasattr(f[i],'cbDefn'): i = i-1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   219
			g = f[i]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   220
			if g.text[-1]!=' ': g.text = g.text+' '
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   221
	return f
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   222
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   223
def _drawBullet(canvas, offset, cur_y, bulletText, style):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   224
	'''draw a bullet text could be a simple string or a frag list'''
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   225
	tx2 = canvas.beginText(style.bulletIndent, cur_y)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   226
	tx2.setFont(style.bulletFontName, style.bulletFontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   227
	tx2.setFillColor(hasattr(style,'bulletColor') and style.bulletColor or style.textColor)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   228
	if type(bulletText) is StringType:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   229
		tx2.textOut(bulletText)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   230
	else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   231
		for f in bulletText:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   232
			tx2.setFont(f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   233
			tx2.setFillColor(f.textColor)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   234
			tx2.textOut(f.text)
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   235
1397
afa7a0e510e0 Bullet text spacing and figure caption size made more flexible
andy_robinson
parents: 1373
diff changeset
   236
	#AR making definition lists a bit less ugly
afa7a0e510e0 Bullet text spacing and figure caption size made more flexible
andy_robinson
parents: 1373
diff changeset
   237
	#bulletEnd = tx2.getX()
afa7a0e510e0 Bullet text spacing and figure caption size made more flexible
andy_robinson
parents: 1373
diff changeset
   238
	bulletEnd = tx2.getX() + style.bulletFontSize * 0.6
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   239
	offset = max(offset, bulletEnd - style.leftIndent)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   240
	canvas.drawText(tx2)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   241
	return offset
250
a1bcf9c6c21e <bullet> xml tag added
rgbecker
parents: 221
diff changeset
   242
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   243
def _handleBulletWidth(bulletText,style,maxWidths):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   244
	'''work out bullet width and adjust maxWidths[0] if neccessary
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   245
	'''
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   246
	if bulletText <> None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   247
		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
   248
			bulletWidth = stringWidth( bulletText, style.bulletFontName, style.bulletFontSize)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   249
		else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   250
			#it's a list of fragments
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   251
			bulletWidth = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   252
			for f in bulletText:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   253
				bulletWidth = bulletWidth + stringWidth(f.text, f.fontName, f.fontSize)
1398
4bb93ead7e52 Tidied up bullets further
andy_robinson
parents: 1397
diff changeset
   254
		bulletRight = style.bulletIndent + bulletWidth + 0.6 * style.bulletFontSize
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   255
		indent = style.leftIndent+style.firstLineIndent
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   256
		if bulletRight > indent:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   257
			#..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
   258
			maxWidths[0] = maxWidths[0] - (bulletRight - indent)
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   259
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   260
def	splitLines0(frags,widths):
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   261
	'''
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   262
	given a list of ParaFrags we return a list of ParaLines
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   263
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   264
	each ParaLine has
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   265
	1)	ExtraSpace
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   266
	2)	blankCount
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   267
	3)	[textDefns....]
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   268
		each text definition is a (ParaFrag, start, limit) triplet
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   269
	'''
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   270
	#initialise the algorithm
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   271
	lines	= []
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   272
	lineNum	= 0
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   273
	maxW	= widths[lineNum]
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   274
	i		= -1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   275
	l		= len(frags)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   276
	lim		= start = 0
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   277
	while 1:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   278
		#find a non whitespace character
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   279
		while i<l:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   280
			while start<lim and text[start]==' ': start=start+1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   281
			if start==lim:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   282
				i = i + 1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   283
				if i==l: break
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   284
				start = 0
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   285
				f = frags[i]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   286
				text = f.text
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   287
				lim	= len(text)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   288
			else:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   289
				break	# we found one
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   290
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   291
		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
   292
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   293
		#start of a line
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   294
		g		= (None,None,None)
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   295
		line	= []
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   296
		cLen	= 0
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   297
		nSpaces	= 0
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   298
		while cLen<maxW:
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   299
			j = find(text,' ',start)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   300
			if j<0: j==lim
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   301
			w = stringWidth(text[start:j],f.fontName,f.fontSize)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   302
			cLen = cLen + w
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   303
			if cLen>maxW and line!=[]:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   304
				cLen = cLen-w
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   305
				#this is the end of the line
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   306
				while g.text[lim]==' ':
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   307
					lim = lim - 1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   308
					nSpaces = nSpaces-1
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   309
				break
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   310
			if j<0: j = lim
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   311
			if g[0] is f: g[2] = j	#extend
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   312
			else:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   313
				g = (f,start,j)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   314
				line.append(g)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   315
			if j==lim:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   316
				i=i+1
549
f9e66c978f3a Start on new simpler line splitter
rgbecker
parents: 547
diff changeset
   317
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   318
class Paragraph(Flowable):
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   319
	""" Paragraph(text, style, bulletText=None)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   320
		text a string of stuff to go into the paragraph.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   321
		style is a style definition as in reportlab.lib.styles.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   322
		bulletText is an optional bullet defintion.
316
e15cf6a28eb8 Documentation fixes
rgbecker
parents: 302
diff changeset
   323
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   324
		This class is a flowable that can format a block of text
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   325
		into a paragraph with a given style.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   326
	
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   327
		The paragraph Text can contain XML-like markup including the tags:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   328
		<b> ... </b> - bold
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   329
		<i> ... </i> - italics
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   330
		<u> ... </u> - underline
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   331
		<super> ... </super> - superscript
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   332
		<sub> ... </sub> - subscript
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   333
		<font name=fontfamily/fontname color=colorname size=float>
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   334
		<onDraw name=callable label="a label">
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
   335
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   336
		The whole may be surrounded by <para> </para> tags
268
8414113fa500 more documentation changes
aaron_watters
parents: 253
diff changeset
   337
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   338
		It will also be able to handle any MathML specified Greek characters.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   339
	"""
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   340
	def __init__(self, text, style, bulletText = None, frags=None):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   341
		self._setup(text, style, bulletText, frags, cleanBlockQuotedText)
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   342
541
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   343
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   344
	def __repr__(self):
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   345
		import string
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   346
		n = self.__class__.__name__
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   347
		L = [n+"("]
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   348
		keys = self.__dict__.keys()
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   349
		for k in keys:
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   350
			v = getattr(self, k)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   351
			rk = repr(k)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   352
			rv = repr(v)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   353
			rk = "  "+string.replace(rk, "\n", "\n  ")
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   354
			rv = "    "+string.replace(rv, "\n", "\n    ")
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   355
			L.append(rk)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   356
			L.append(rv)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   357
		L.append(") #"+n)
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   358
		return string.join(L, "\n")		
33de80b3655c added __repr__s and enhanced exception messages for debugging
aaron_watters
parents: 540
diff changeset
   359
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   360
	def _setup(self, text, style, bulletText, frags, cleaner):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   361
		if frags is None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   362
			text = cleaner(text)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   363
			style, frags, bulletTextFrags = _parser.parse(text,style)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   364
			if frags is None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   365
				raise "xml parser error (%s) in paragraph beginning\n'%s'"\
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   366
					% (_parser.errors[0],text[:min(30,len(text))])
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   367
			if bulletTextFrags: bulletText = bulletTextFrags
279
e7d8b3631d5c Global sequencer put in the 'story builder'.
andy_robinson
parents: 268
diff changeset
   368
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   369
		#AR hack
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   370
		self.text = text
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   371
		self.frags = frags
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   372
		self.style = style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   373
		self.bulletText = bulletText
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   374
		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
   375
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   376
	def wrap(self, availWidth, availHeight):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   377
		# work out widths array for breaking
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   378
		self.width = availWidth
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   379
		leftIndent = self.style.leftIndent
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   380
		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
   381
		later_widths = availWidth - leftIndent - self.style.rightIndent
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   382
		self.blPara = self.breakLines([first_line_width, later_widths])
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   383
		self.height = len(self.blPara.lines) * self.style.leading
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   384
		return (self.width, self.height)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   385
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   386
	def minWidth(self):
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   387
		'Attempt to determine a minimum sensible width'
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   388
		frags = self.frags
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   389
		nFrags= len(frags)
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   390
		if nFrags==1:
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   391
			f = frags[0]
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   392
			fS = f.fontSize
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   393
			fN = f.fontName
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   394
			words = hasattr(f,'text') and split(f.text, ' ') or f.words
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   395
			func = lambda w, fS=fS, fN=fN: stringWidth(w,fN,fS)
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   396
		else:
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   397
			words = _getFragWords(frags)
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   398
			func  = lambda x: x[0]
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   399
		return max(map(func,words))
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   400
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   401
	def _get_split_blParaFunc(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   402
		return self.blPara.kind==0 and _split_blParaSimple or _split_blParaHard
438
fa5d480207bc Preparing for cleanup
rgbecker
parents: 434
diff changeset
   403
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   404
	def split(self,availWidth, availHeight):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   405
		if len(self.frags)<=0: return []
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   406
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   407
		#the split information is all inside self.blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   408
		if not hasattr(self,'blPara'):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   409
			self.wrap(availWidth,availHeight)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   410
		blPara = self.blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   411
		style = self.style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   412
		leading = style.leading
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   413
		lines = blPara.lines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   414
		n = len(lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   415
		s = int(availHeight/leading)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   416
		if s<=1: return []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   417
		if n<=s: return [self]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   418
		func = self._get_split_blParaFunc()
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   419
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   420
		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
   421
		#this is a major hack
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   422
		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
   423
		P1._JustifyLast = 1
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   424
		if style.firstLineIndent != 0:
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   425
			style = deepcopy(style)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   426
			style.firstLineIndent = 0
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   427
		P2=self.__class__(None,style,bulletText=None,frags=func(blPara,s,n))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   428
		return [P1,P2]
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   429
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   430
	def draw(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   431
		#call another method for historical reasons.  Besides, I
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   432
		#suspect I will be playing with alternate drawing routines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   433
		#so not doing it here makes it easier to switch.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   434
		self.drawPara(self.debug)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   435
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   436
	def breakLines(self, width):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   437
		"""
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   438
		Returns a broken line structure. There are two cases
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   439
		
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   440
		A) For the simple case of a single formatting input fragment the output is
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   441
			A fragment specifier with
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   442
				kind = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   443
				fontName, fontSize, leading, textColor
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   444
				lines=	A list of lines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   445
						Each line has two items.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   446
						1) unused width in points
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   447
						2) word list
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   448
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   449
		B) When there is more than one input formatting fragment the out put is
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   450
			A fragment specifier with
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   451
				kind = 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   452
				lines=	A list of fragments each having fields
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   453
							extraspace (needed for justified)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   454
							fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   455
							words=word list
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   456
								each word is itself a fragment with
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   457
								various settings
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   458
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   459
		This structure can be used to easily draw paragraphs with the various alignments.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   460
		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
   461
		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
   462
		different first line indent; a longer list could be created to facilitate custom wraps
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   463
		around irregular objects."""
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   464
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   465
		if type(width) <> ListType: maxWidths = [width]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   466
		else: maxWidths = width
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   467
		lines = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   468
		lineno = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   469
		style = self.style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   470
		fFontSize = float(style.fontSize)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   471
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   472
		#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
   473
		_handleBulletWidth(self.bulletText,style,maxWidths)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   474
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   475
		maxWidth = maxWidths[lineno]
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   476
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   477
		self.height = 0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   478
		frags = self.frags
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   479
		nFrags= len(frags)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   480
		if nFrags==1:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   481
			f = frags[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   482
			fontSize = f.fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   483
			fontName = f.fontName
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   484
			words = hasattr(f,'text') and split(f.text, ' ') or f.words
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   485
			spaceWidth = stringWidth(' ', fontName, fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   486
			cLine = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   487
			currentWidth = - spaceWidth   # hack to get around extra space for word 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   488
			for word in words:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   489
				wordWidth = stringWidth(word, fontName, fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   490
				newWidth = currentWidth + spaceWidth + wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   491
				if newWidth<=maxWidth or len(cLine)==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   492
					# fit one more on this line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   493
					cLine.append(word)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   494
					currentWidth = newWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   495
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   496
					if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   497
					#end of line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   498
					lines.append((maxWidth - currentWidth, cLine))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   499
					cLine = [word]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   500
					currentWidth = wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   501
					lineno = lineno + 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   502
					try:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   503
						maxWidth = maxWidths[lineno]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   504
					except IndexError:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   505
						maxWidth = maxWidths[-1]  # use the last one
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   506
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   507
			#deal with any leftovers on the final line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   508
			if cLine!=[]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   509
				if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   510
				lines.append((maxWidth - currentWidth, cLine))
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   511
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   512
			return f.clone(kind=0, lines=lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   513
		elif nFrags<=0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   514
			return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   515
							textColor=style.textColor, lines=[])
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   516
		else:
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   517
			if hasattr(self,'blPara'):
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   518
				#NB this is an utter hack that awaits the proper information
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   519
				#preserving splitting algorithm
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   520
				return self.blPara
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   521
			n = 0
553
7a1834c1f32b More Dinu related fixes/edits
rgbecker
parents: 551
diff changeset
   522
			nSp = 0
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   523
			for w in _getFragWords(frags):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   524
				spaceWidth = stringWidth(' ',w[-1][0].fontName, w[-1][0].fontSize)
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   525
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   526
				if n==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   527
					currentWidth = -spaceWidth	 # hack to get around extra space for word 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   528
					words = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   529
					maxSize = 0
496
bb47cf5c2739 Layout error fixes
rgbecker
parents: 494
diff changeset
   530
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   531
				wordWidth = w[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   532
				f = w[1][0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   533
				if wordWidth>0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   534
					newWidth = currentWidth + spaceWidth + wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   535
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   536
					newWidth = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   537
				if newWidth<=maxWidth or n==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   538
					# fit one more on this line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   539
					n = n + 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   540
					maxSize = max(maxSize,f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   541
					nText = w[1][1]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   542
					if words==[]:
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   543
						g = f.clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   544
						words = [g]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   545
						g.text = nText
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   546
					elif not _sameFrag(g,f):
553
7a1834c1f32b More Dinu related fixes/edits
rgbecker
parents: 551
diff changeset
   547
						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
   548
							if hasattr(g,'cbDefn'):
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   549
								i = len(words)-1
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   550
								while hasattr(words[i],'cbDefn'): i = i-1
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   551
								words[i].text = words[i].text + ' '
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   552
							else:
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   553
								g.text = g.text + ' '
553
7a1834c1f32b More Dinu related fixes/edits
rgbecker
parents: 551
diff changeset
   554
							nSp = nSp + 1
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   555
						g = f.clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   556
						words.append(g)
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   557
						g.text = nText
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   558
					else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   559
						if nText!='' and nText[0]!=' ':
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   560
							g.text = g.text + ' ' + nText
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   561
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   562
					for i in w[2:]:
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   563
						g = i[0].clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   564
						g.text=i[1]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   565
						words.append(g)
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   566
						maxSize = max(maxSize,g.fontSize)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   567
						
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   568
					currentWidth = newWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   569
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   570
					if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   571
					#end of line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   572
					lines.append(FragLine(extraSpace=(maxWidth - currentWidth),wordCount=n,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   573
										words=words, fontSize=maxSize))
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   574
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   575
					#start new line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   576
					lineno = lineno + 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   577
					try:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   578
						maxWidth = maxWidths[lineno]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   579
					except IndexError:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   580
						maxWidth = maxWidths[-1]  # use the last one
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   581
					currentWidth = wordWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   582
					n = 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   583
					maxSize = f.fontSize
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   584
					g = f.clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   585
					words = [g]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   586
					g.text = w[1][1]
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   587
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   588
					for i in w[2:]:
547
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   589
						g = i[0].clone()
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   590
						g.text=i[1]
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   591
						words.append(g)
f24a33fb2384 Further Dinuistic fixes for rare cbDefn bugs
rgbecker
parents: 543
diff changeset
   592
						maxSize = max(maxSize,g.fontSize)
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   593
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   594
			#deal with any leftovers on the final line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   595
			if words<>[]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   596
				if currentWidth>self.width: self.width = currentWidth
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   597
				lines.append(ParaLines(extraSpace=(maxWidth - currentWidth),wordCount=n,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   598
									words=words, fontSize=maxSize))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   599
			return ParaLines(kind=1, lines=lines)
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   600
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   601
		return lines
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   602
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   603
	def drawPara(self,debug=0):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   604
		"""Draws a paragraph according to the given style.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   605
		Returns the final y position at the bottom. Not safe for
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   606
		paragraphs without spaces e.g. Japanese; wrapping
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   607
		algorithm will go infinite."""
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   608
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   609
		#stash the key facts locally for speed
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   610
		canvas = self.canv
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   611
		style = self.style
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   612
		blPara = self.blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   613
		lines = blPara.lines
532
fa0a46295460 Added a text background color attribute
andy_robinson
parents: 529
diff changeset
   614
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   615
		#work out the origin for line 1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   616
		cur_x = style.leftIndent
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   617
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   618
		#if has a background, draw it
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   619
		if style.backColor:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   620
			canvas.saveState()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   621
			canvas.setFillColor(style.backColor)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   622
			canvas.rect(style.leftIndent, 
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   623
						0,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   624
						self.width - style.rightIndent,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   625
						self.height,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   626
						fill=1,
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   627
						stroke=0)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   628
			canvas.restoreState()
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   629
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   630
		if debug:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   631
			# This boxes and shades stuff to show how the paragraph
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   632
			# uses its space.  Useful for self-documentation so
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   633
			# the debug code stays!
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   634
			# box the lot
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   635
			canvas.rect(0, 0, self.width, self.height)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   636
			#left and right margins
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   637
			canvas.saveState()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   638
			canvas.setFillColor(Color(0.9,0.9,0.9))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   639
			canvas.rect(0, 0, style.leftIndent, self.height)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   640
			canvas.rect(self.width - style.rightIndent, 0, style.rightIndent, self.height)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   641
			# shade above and below
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   642
			canvas.setFillColor(Color(1.0,1.0,0.0))
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   643
			canvas.restoreState()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   644
			#self.drawLine(x + style.leftIndent, y, x + style.leftIndent, cur_y)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   645
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   646
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   647
		nLines = len(lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   648
		bulletText = self.bulletText
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   649
		if nLines > 0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   650
			canvas.saveState()
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   651
			#canvas.addLiteral('%% %s.drawPara' % _className(self))
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   652
			alignment = style.alignment
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   653
			offset = style.firstLineIndent
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   654
			lim = nLines-1
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   655
			noJustifyLast = not (hasattr(self,'_JustifyLast') and self._JustifyLast)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   656
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   657
			if blPara.kind==0:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   658
				if alignment == TA_LEFT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   659
					dpl = _leftDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   660
				elif alignment == TA_CENTER:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   661
					dpl = _centerDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   662
				elif self.style.alignment == TA_RIGHT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   663
					dpl = _rightDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   664
				elif self.style.alignment == TA_JUSTIFY:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   665
					dpl = _justifyDrawParaLine
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   666
				f = blPara
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   667
				cur_y = self.height - f.fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   668
				if bulletText <> None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   669
					offset = _drawBullet(canvas,offset,cur_y,bulletText,style)
212
b04e22acb4fa Splitting changes
rgbecker
parents: 208
diff changeset
   670
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   671
				#set up the font etc.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   672
				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
   673
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   674
				tx = canvas.beginText(cur_x, cur_y)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   675
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   676
				#now the font for the rest of the paragraph
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   677
				tx.setFont(f.fontName, f.fontSize, style.leading)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   678
				dpl( tx, offset, lines[0][0], lines[0][1], noJustifyLast and nLines==1)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   679
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   680
				#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
   681
				for i in range(1, nLines):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   682
					dpl( tx, 0, lines[i][0], lines[i][1], noJustifyLast and i==lim)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   683
			else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   684
				f = lines[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   685
				cur_y = self.height - f.fontSize
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   686
				# default?
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   687
				dpl = _leftDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   688
				if bulletText <> None:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   689
					offset = _drawBullet(canvas,offset,cur_y,bulletText,style)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   690
				if alignment == TA_LEFT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   691
					dpl = _leftDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   692
				elif alignment == TA_CENTER:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   693
					dpl = _centerDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   694
				elif self.style.alignment == TA_RIGHT:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   695
					dpl = _rightDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   696
				elif self.style.alignment == TA_JUSTIFY:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   697
					dpl = _justifyDrawParaLineX
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   698
				else:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   699
					raise ValueError, "bad align %s" % repr(alignment)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   700
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   701
				#set up the font etc.
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   702
				tx = canvas.beginText(cur_x, cur_y)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   703
				tx.XtraState=ABag()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   704
				tx.XtraState.textColor=None
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   705
				tx.XtraState.rise=0
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   706
				tx.setLeading(style.leading)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   707
				#f = lines[0].words[0]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   708
				#tx._setFont(f.fontName, f.fontSize)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   709
				tx._fontname,tx._fontsize = None, None
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   710
				dpl( tx, offset, lines[0], noJustifyLast and nLines==1)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   711
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   712
				#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
   713
				for i in range(1, nLines):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   714
					f = lines[i]
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   715
					dpl( tx, 0, f, noJustifyLast and i==lim)
131
72cb089e6fda Removed from layout.py
rgbecker
parents:
diff changeset
   716
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   717
			canvas.drawText(tx)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   718
			canvas.restoreState()
284
eabeb5f4e851 Added UserDocTemplate class, and paragraph.getPlainText()
andy_robinson
parents: 279
diff changeset
   719
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   720
	def getPlainText(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   721
		"""Convenience function for templates which want access
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   722
		to the raw text, without XML tags. """
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   723
		plains = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   724
		for frag in self.frags:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   725
			plains.append(frag.text)
539
14dd200244e2 Layout fixes; the text objects needed moves before & after and the bullet width
rgbecker
parents: 534
diff changeset
   726
		return join(plains, '')
302
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   727
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   728
	def getActualLineWidths0(self):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   729
		"""Convenience function; tells you how wide each line
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   730
		actually is.  For justified styles, this will be
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   731
		the same as the wrap width; for others it might be
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   732
		useful for seeing if paragraphs will fit in spaces."""
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   733
		assert hasattr(self, 'width'), "Cannot call this method before wrap()"
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   734
		w = []
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   735
		for frag in self.blPara.lines:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   736
			w.append(self.width - frag.extraSpace)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   737
		return w
497
63f575fc1170 Added experimental method getActualLineWidths0
andy_robinson
parents: 496
diff changeset
   738
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   739
if __name__=='__main__':	#NORUNTESTS
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   740
	def dumpParagraphLines(P):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   741
		print 'dumpParagraphLines(<Paragraph @ %d>)' % id(P)
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   742
		lines = P.blPara.lines
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   743
		n =len(lines)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   744
		for l in range(n):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   745
			line = lines[l]
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   746
			if hasattr(line,'words'):
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   747
				words = line.words
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   748
			else:
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   749
				words = line[1]
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   750
			nwords = len(words)
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   751
			print 'line%d: %d(%s)\n  ' % (l,nwords,str(getattr(line,'wordCount','Unknown'))),
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   752
			for w in range(nwords):
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   753
				print "%d:'%s'"%(w,getattr(words[w],'text',words[w])),
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   754
			print
302
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   755
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   756
	def dumpParagraphFrags(P):
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   757
		print 'dumpParagraphFrags(<Paragraph @ %d>) minWidth() = %.2f' % (id(P), P.minWidth())
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   758
		frags = P.frags
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   759
		n =len(frags)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   760
		for l in range(n):
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   761
			print "frag%d: '%s'" % (l, frags[l].text)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   762
	
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   763
		l = 0
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   764
		cum = 0
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   765
		for W in _getFragWords(frags):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   766
			cum = cum + W[0]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   767
			print "fragword%d: cum=%3d size=%d" % (l, cum, W[0]),
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   768
			for w in W[1:]:
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   769
				print "'%s'" % w[1],
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   770
			print
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   771
			l = l + 1
434
257af3109bf4 Various brutal changes to paragraph, canvas and textobject for speed/size
rgbecker
parents: 383
diff changeset
   772
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   773
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   774
	from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   775
	import sys
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   776
	TESTS = sys.argv[1:]
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   777
	if TESTS==[]: TESTS=['4']
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   778
	def flagged(i,TESTS=TESTS):
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   779
		return 'all' in TESTS or '*' in TESTS or str(i) in TESTS
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   780
534
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   781
	styleSheet = getSampleStyleSheet()
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   782
	B = styleSheet['BodyText']
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   783
	style = ParagraphStyle("discussiontext", parent=B)
5dead09d5d08 Comments and cosmetic changes
rgbecker
parents: 532
diff changeset
   784
	style.fontName= 'Helvetica'
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   785
	if flagged(1):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   786
		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
   787
mixes three pigments (cyan, magenta, and yellow) to form colors.
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   788
Because mixing chemicals is more difficult than combining light there
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   789
is a fourth parameter for darkness.  For example a chemical
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   790
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
   791
black -- instead producing a muddy color -- so, to get black printers
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   792
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
   793
<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
   794
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
   795
and better control when printed.
960659f9cb5c Fixes to splitting code
rgbecker
parents: 284
diff changeset
   796
'''
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   797
		P=Paragraph(text,style)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   798
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   799
		aW, aH = 456.0, 42.8
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   800
		w,h = P.wrap(aW, aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   801
		dumpParagraphLines(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   802
		S = P.split(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   803
		for s in S:
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   804
			s.wrap(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   805
			dumpParagraphLines(s)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   806
			aH = 500
488
a270e8b45200 Added J Alet's bug case
rgbecker
parents: 471
diff changeset
   807
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   808
	if flagged(2):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   809
		P=Paragraph("""Price<super><font color="red">*</font></super>""", styleSheet['Normal'])
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   810
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   811
		w,h = P.wrap(24, 200)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   812
		dumpParagraphLines(P)
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   813
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   814
	if flagged(3):
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   815
		text = """Dieses Kapitel bietet eine schnelle <b><font color=red>Programme :: starten</font></b>
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   816
<onDraw name=myIndex label="Programme :: starten">
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   817
<b><font color=red>Eingabeaufforderung :: (&gt;&gt;&gt;)</font></b>
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   818
<onDraw name=myIndex label="Eingabeaufforderung :: (&gt;&gt;&gt;)">
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   819
<b><font color=red>&gt;&gt;&gt; (Eingabeaufforderung)</font></b>
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   820
<onDraw name=myIndex label="&gt;&gt;&gt; (Eingabeaufforderung)">
681
934a4f24ea5d Added explicit font and encoding support
andy_robinson
parents: 553
diff changeset
   821
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
   822
<onDraw name=myIndex label="Python :: Einf\374hrung">.
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   823
Das Ziel ist, die grundlegenden Eigenschaften von Python darzustellen, ohne
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   824
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
   825
dieses Kapitel kurz die wesentlichen Konzepte wie Variablen, Ausdr\374cke,
521
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   826
Kontrollfluss, Funktionen sowie Ein- und Ausgabe. Es erhebt nicht den Anspruch,
e09fc89a6bb3 Cosmetic changes
rgbecker
parents: 519
diff changeset
   827
umfassend zu sein."""
551
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   828
		P=Paragraph(text, styleSheet['Code'])
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   829
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   830
		w,h = P.wrap(6*72, 9.7*72)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   831
		dumpParagraphLines(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   832
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   833
	if flagged(4):
681
934a4f24ea5d Added explicit font and encoding support
andy_robinson
parents: 553
diff changeset
   834
		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
   835
		aW = 420
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   836
		aH = 64.4
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   837
		P=Paragraph(text, B)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   838
		dumpParagraphFrags(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   839
		w,h = P.wrap(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   840
		print 'After initial wrap',w,h
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   841
		dumpParagraphLines(P)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   842
		S = P.split(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   843
		dumpParagraphFrags(S[0])
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   844
		w0,h0 = S[0].wrap(aW,aH)
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   845
		print 'After split wrap',w0,h0
21b8a2cb8c8b Hack to fix Dinu's problem
rgbecker
parents: 549
diff changeset
   846
		dumpParagraphLines(S[0])
683
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   847
954
bf9f434cb08a added minWidth method to Flowable, Paragraph
rgbecker
parents: 938
diff changeset
   848
	if flagged(5):
1001
84d63f4312a9 Remove explicit � character to stop Dinu moaning
rgbecker
parents: 987
diff changeset
   849
		text = '<para> %s <![CDATA[</font></b>& %s < >]]></para>' % (chr(163),chr(163))
683
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   850
		P=Paragraph(text, styleSheet['Code'])
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   851
		dumpParagraphFrags(P)
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   852
		w,h = P.wrap(6*72, 9.7*72)
fbd2b18742a5 Added test 5
rgbecker
parents: 681
diff changeset
   853
		dumpParagraphLines(P)