1 #copyright ReportLab Inc. 2000 |
1 #copyright ReportLab Inc. 2000 |
2 #see license.txt for license details |
2 #see license.txt for license details |
3 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/tables.py?cvsroot=reportlab |
3 #history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/reportlab/platypus/tables.py?cvsroot=reportlab |
4 #$Header: /tmp/reportlab/reportlab/platypus/tables.py,v 1.56 2002/03/18 14:00:45 rgbecker Exp $ |
4 #$Header: /tmp/reportlab/reportlab/platypus/tables.py,v 1.57 2002/04/25 19:52:40 andy_robinson Exp $ |
5 __version__=''' $Id: tables.py,v 1.56 2002/03/18 14:00:45 rgbecker Exp $ ''' |
5 __version__=''' $Id: tables.py,v 1.57 2002/04/25 19:52:40 andy_robinson Exp $ ''' |
6 __doc__=""" |
6 __doc__=""" |
7 Tables are created by passing the constructor a tuple of column widths, a tuple of row heights and the data in |
7 Tables are created by passing the constructor a tuple of column widths, a tuple of row heights and the data in |
8 row order. Drawing of the table can be controlled by using a TableStyle instance. This allows control of the |
8 row order. Drawing of the table can be controlled by using a TableStyle instance. This allows control of the |
9 color and weight of the lines (if any), and the font, alignment and padding of the text. |
9 color and weight of the lines (if any), and the font, alignment and padding of the text. |
10 |
10 |
225 if H is not None: H.append(vh) |
225 if H is not None: H.append(vh) |
226 w = max(w,vw) |
226 w = max(w,vw) |
227 t = t + vh + v.getSpaceBefore()+v.getSpaceAfter() |
227 t = t + vh + v.getSpaceBefore()+v.getSpaceAfter() |
228 return w, t - V[0].getSpaceBefore()-V[-1].getSpaceAfter() |
228 return w, t - V[0].getSpaceBefore()-V[-1].getSpaceAfter() |
229 |
229 |
230 def _calc(self): |
230 def _calc_width(self): |
231 if hasattr(self,'_width'): return |
231 |
|
232 W = self._argW |
|
233 |
|
234 canv = getattr(self,'canv',None) |
|
235 saved = None |
|
236 |
|
237 if None in W: |
|
238 W = W[:] |
|
239 self._colWidths = W |
|
240 while None in W: |
|
241 j = W.index(None) |
|
242 f = lambda x,j=j: operator.getitem(x,j) |
|
243 V = map(f,self._cellvalues) |
|
244 S = map(f,self._cellStyles) |
|
245 w = 0 |
|
246 i = 0 |
|
247 for v, s in map(None, V, S): |
|
248 i = i + 1 |
|
249 t = type(v) |
|
250 if t in _SeqTypes or isinstance(v,Flowable): |
|
251 raise ValueError, "Flowable %s in cell(%d,%d) can't have auto width\n%s" % (v.identity(30),i,j,self.identity(30)) |
|
252 elif t is not StringType: v = v is None and '' or str(v) |
|
253 v = string.split(v, "\n") |
|
254 t = s.leftPadding+s.rightPadding + max(map(lambda a, b=s.fontname, |
|
255 c=s.fontsize,d=pdfmetrics.stringWidth: d(a,b,c), v)) |
|
256 if t>w: w = t #record a new maximum |
|
257 W[j] = w |
|
258 |
|
259 width = 0 |
|
260 self._colpositions = [0] #index -1 is right side boundary; we skip when processing cells |
|
261 for w in W: |
|
262 #print w, width |
|
263 width = width + w |
|
264 self._colpositions.append(width) |
|
265 #print "final width", width |
|
266 |
|
267 self._width = width |
|
268 |
|
269 def _calc_height(self): |
232 |
270 |
233 H = self._argH |
271 H = self._argH |
234 W = self._argW |
272 W = self._argW |
235 #print "W is", W |
|
236 |
273 |
237 canv = getattr(self,'canv',None) |
274 canv = getattr(self,'canv',None) |
238 saved = None |
275 saved = None |
|
276 |
239 if None in H: |
277 if None in H: |
240 if canv: saved = canv._fontname, canv._fontsize, canv._leading |
278 if canv: saved = canv._fontname, canv._fontsize, canv._leading |
241 H = H[:] #make a copy as we'll change it |
279 H = H[:] #make a copy as we'll change it |
242 self._rowHeights = H |
280 self._rowHeights = H |
243 while None in H: |
281 while None in H: |
267 t = s.leading*len(v) |
305 t = s.leading*len(v) |
268 t = t+s.bottomPadding+s.topPadding |
306 t = t+s.bottomPadding+s.topPadding |
269 if t>h: h = t #record a new maximum |
307 if t>h: h = t #record a new maximum |
270 H[i] = h |
308 H[i] = h |
271 |
309 |
272 if None in W: |
|
273 W = W[:] |
|
274 self._colWidths = W |
|
275 while None in W: |
|
276 j = W.index(None) |
|
277 f = lambda x,j=j: operator.getitem(x,j) |
|
278 V = map(f,self._cellvalues) |
|
279 S = map(f,self._cellStyles) |
|
280 w = 0 |
|
281 i = 0 |
|
282 for v, s in map(None, V, S): |
|
283 i = i + 1 |
|
284 t = type(v) |
|
285 if t in _SeqTypes or isinstance(v,Flowable): |
|
286 raise ValueError, "Flowable %s in cell(%d,%d) can't have auto width\n%s" % (v.identity(30),i,j,self.identity(30)) |
|
287 elif t is not StringType: v = v is None and '' or str(v) |
|
288 v = string.split(v, "\n") |
|
289 t = s.leftPadding+s.rightPadding + max(map(lambda a, b=s.fontname, |
|
290 c=s.fontsize,d=pdfmetrics.stringWidth: d(a,b,c), v)) |
|
291 if t>w: w = t #record a new maximum |
|
292 W[j] = w |
|
293 |
|
294 height = self._height = reduce(operator.add, H, 0) |
310 height = self._height = reduce(operator.add, H, 0) |
295 #print "height, H", height, H |
311 #print "height, H", height, H |
296 self._rowpositions = [height] # index 0 is actually topline; we skip when processing cells |
312 self._rowpositions = [height] # index 0 is actually topline; we skip when processing cells |
297 for h in H: |
313 for h in H: |
298 height = height - h |
314 height = height - h |
299 self._rowpositions.append(height) |
315 self._rowpositions.append(height) |
300 assert abs(height)<1e-8, 'Internal height error' |
316 assert abs(height)<1e-8, 'Internal height error' |
301 width = 0 |
317 |
302 self._colpositions = [0] #index -1 is right side boundary; we skip when processing cells |
318 def _calc(self): |
303 for w in W: |
319 if hasattr(self,'_width'): return |
304 #print w, width |
320 |
305 width = width + w |
321 # calculate the full table height |
306 self._colpositions.append(width) |
322 self._calc_height() |
307 #print "final width", width |
323 |
308 |
324 # if the width has already been calculated, don't calculate again |
309 self._width = width |
325 # there's surely a better, more pythonic way to short circuit this FIXME FIXME |
|
326 if hasattr(self,'_width_calculated_once'): return |
|
327 self._width_calculated_once = 1 |
|
328 |
|
329 # calculate the full table width |
|
330 self._calc_width() |
310 |
331 |
311 def setStyle(self, tblstyle): |
332 def setStyle(self, tblstyle): |
312 if type(tblstyle) is not TableStyleType: |
333 if type(tblstyle) is not TableStyleType: |
313 tblstyle = TableStyle(tblstyle) |
334 tblstyle = TableStyle(tblstyle) |
314 for cmd in tblstyle.getCommands(): |
335 for cmd in tblstyle.getCommands(): |
454 repeatCols = self.repeatCols |
475 repeatCols = self.repeatCols |
455 splitByRow = self.splitByRow |
476 splitByRow = self.splitByRow |
456 data = self._cellvalues |
477 data = self._cellvalues |
457 |
478 |
458 #we're going to split into two superRows |
479 #we're going to split into two superRows |
459 R0 = Table( data[:n], self._argW, self._argH[:n], |
480 #R0 = Table( data[:n], self._argW, self._argH[:n], |
|
481 R0 = Table( data[:n], self._colWidths, self._argH[:n], |
460 repeatRows=repeatRows, repeatCols=repeatCols, |
482 repeatRows=repeatRows, repeatCols=repeatCols, |
461 splitByRow=splitByRow) |
483 splitByRow=splitByRow) |
462 |
484 |
463 #copy the styles and commands |
485 #copy the styles and commands |
464 R0._cellStyles = self._cellStyles[:n] |
486 R0._cellStyles = self._cellStyles[:n] |
502 |
524 |
503 R0._cr_0(n,A) |
525 R0._cr_0(n,A) |
504 R0._cr_0(n,self._bkgrndcmds) |
526 R0._cr_0(n,self._bkgrndcmds) |
505 |
527 |
506 if repeatRows: |
528 if repeatRows: |
507 R1 = Table(data[:repeatRows]+data[n:], |
529 #R1 = Table(data[:repeatRows]+data[n:],self._argW, |
508 self._argW, self._argH[:repeatRows]+self._argH[n:], |
530 R1 = Table(data[:repeatRows]+data[n:],self._colWidths, |
|
531 self._argH[:repeatRows]+self._argH[n:], |
509 repeatRows=repeatRows, repeatCols=repeatCols, |
532 repeatRows=repeatRows, repeatCols=repeatCols, |
510 splitByRow=splitByRow) |
533 splitByRow=splitByRow) |
511 R1._cellStyles = self._cellStyles[:repeatRows]+self._cellStyles[n:] |
534 R1._cellStyles = self._cellStyles[:repeatRows]+self._cellStyles[n:] |
512 R1._cr_1_1(n,repeatRows,A) |
535 R1._cr_1_1(n,repeatRows,A) |
513 R1._cr_1_1(n,repeatRows,self._bkgrndcmds) |
536 R1._cr_1_1(n,repeatRows,self._bkgrndcmds) |
514 else: |
537 else: |
515 R1 = Table(data[n:], self._argW, self._argH[n:], |
538 #R1 = Table(data[n:], self._argW, self._argH[n:], |
|
539 R1 = Table(data[n:], self._colWidths, self._argH[n:], |
516 repeatRows=repeatRows, repeatCols=repeatCols, |
540 repeatRows=repeatRows, repeatCols=repeatCols, |
517 splitByRow=splitByRow) |
541 splitByRow=splitByRow) |
518 R1._cellStyles = self._cellStyles[n:] |
542 R1._cellStyles = self._cellStyles[n:] |
519 R1._cr_1_0(n,A) |
543 R1._cr_1_0(n,A) |
520 R1._cr_1_0(n,self._bkgrndcmds) |
544 R1._cr_1_0(n,self._bkgrndcmds) |