]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/printout.py
updates from Andrea, plus some fixes
[wxWidgets.git] / wxPython / wx / lib / printout.py
CommitLineData
d14a1e28
RD
1#----------------------------------------------------------------------------
2# Name: printout.py
3# Purpose: preview and printing class -> table/grid printing
4#
5# Author: Lorne White (email: lorne.white@telusplanet.net)
6#
7# Created:
8# Version 0.75
9# Date: May 15, 2002
10# Licence: wxWindows license
11#----------------------------------------------------------------------------
12# Release Notes
13
14# fixed bug for string wider than print region
15# add index to data list after parsing total pages for paging
16#----------------------------------------------------------------------------
b881fc78 17# 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
b881fc78 18# o 2.5 compatability update.
02b800ce
RD
19#----------------------------------------------------------------------------
20# 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com)
21# o Generalize for non-2-dimensional sequences and non-text data
22# (can use as a simple text printer by supplying a list of strings.)
23# o Add a small _main_ for self test
24
b881fc78 25import copy
02b800ce 26import types
b881fc78 27import wx
d14a1e28
RD
28
29class PrintBase:
30 def SetPrintFont(self, font): # set the DC font parameters
31 fattr = font["Attr"]
32 if fattr[0] == 1:
b881fc78 33 weight = wx.BOLD
d14a1e28 34 else:
b881fc78 35 weight = wx.NORMAL
d14a1e28
RD
36
37 if fattr[1] == 1:
b881fc78 38 set_style = wx.ITALIC
d14a1e28 39 else:
b881fc78 40 set_style = wx.NORMAL
d14a1e28
RD
41
42 underline = fattr[2]
43 fcolour = self.GetFontColour(font)
44 self.DC.SetTextForeground(fcolour)
45
b881fc78 46 setfont = wx.Font(font["Size"], wx.SWISS, set_style, weight, underline)
d14a1e28
RD
47 setfont.SetFaceName(font["Name"])
48 self.DC.SetFont(setfont)
49
50 def GetFontColour(self, font):
51 fcolour = font["Colour"]
b881fc78 52 return wx.Colour(fcolour[0], fcolour[1], fcolour[2])
d14a1e28
RD
53
54 def OutTextRegion(self, textout, txtdraw = True):
55 textlines = textout.split('\n')
56 y = copy.copy(self.y) + self.pt_space_before
57 for text in textlines:
58 remain = 'X'
59 while remain != "":
60 vout, remain = self.SetFlow(text, self.region)
61 if self.draw == True and txtdraw == True:
62 test_out = self.TestFull(vout)
b881fc78 63 if self.align == wx.ALIGN_LEFT:
d7403ad2 64 self.DC.DrawText(test_out, self.indent+self.pcell_left_margin, y)
d14a1e28 65
b881fc78 66 elif self.align == wx.ALIGN_CENTRE:
d14a1e28 67 diff = self.GetCellDiff(test_out, self.region)
d7403ad2 68 self.DC.DrawText(test_out, self.indent+diff/2, y)
d14a1e28 69
b881fc78 70 elif self.align == wx.ALIGN_RIGHT:
d14a1e28 71 diff = self.GetCellDiff(test_out, self.region)
d7403ad2 72 self.DC.DrawText(test_out, self.indent+diff, y)
d14a1e28
RD
73
74 else:
d7403ad2 75 self.DC.DrawText(test_out, self.indent+self.pcell_left_margin, y)
d14a1e28
RD
76 text = remain
77 y = y + self.space
78 return y - self.space + self.pt_space_after
79
80 def GetCellDiff(self, text, width): # get the remaining cell size for adjustment
81 w, h = self.DC.GetTextExtent(text)
82 diff = width - w
83 if diff < 0:
84 diff = 0
85 return diff
86
87 def TestFull(self, text_test):
88 w, h = self.DC.GetTextExtent(text_test)
89 if w > self.region: # trouble fitting into cell
90 return self.SetChar(text_test, self.region) # fit the text to the cell size
91 else:
92 return text_test
93
94 def SetFlow(self, ln_text, width):
95 width = width - self.pcell_right_margin
96 text = ""
97 split = ln_text.split()
98 if len(split) == 1:
99 return ln_text, ""
100
101 try:
102 w, h = self.DC.GetTextExtent(" " + split[0])
103 if w >= width:
104 return ln_text, ""
105 except:
106 pass
107
108 cnt = 0
109 for word in split:
110 bword = " " + word # blank + word
111 length = len(bword)
112
113 w, h = self.DC.GetTextExtent(text + bword)
114 if w < width:
115 text = text + bword
116 cnt = cnt + 1
117 else:
118 remain = ' '.join(split[cnt:])
119 text = text.strip()
120 return text, remain
121
122 remain = ' '.join(split[cnt:])
123 vout = text.strip()
124 return vout, remain
125
126 def SetChar(self, ln_text, width): # truncate string to fit into width
127 width = width - self.pcell_right_margin - self.pcell_left_margin
128 text = ""
129 for val in ln_text:
130 w, h = self.DC.GetTextExtent(text + val)
131 if w > width:
132 text = text + ".."
133 return text # fitted text value
134 text = text + val
135 return text
136
137 def OutTextPageWidth(self, textout, y_out, align, indent, txtdraw = True):
138 textlines = textout.split('\n')
139 y = copy.copy(y_out)
140
141 pagew = self.parent.page_width * self.pwidth # full page width
142 w, h = self.DC.GetTextExtent(textout)
143 y_line = h
144
145 for text in textlines:
146 remain = 'X'
147 while remain != "":
148 vout, remain = self.SetFlow(text, pagew)
149 if self.draw == True and txtdraw == True:
150 test_out = vout
b881fc78 151 if align == wx.ALIGN_LEFT:
d7403ad2 152 self.DC.DrawText(test_out, indent, y)
d14a1e28 153
b881fc78 154 elif align == wx.ALIGN_CENTRE:
d14a1e28 155 diff = self.GetCellDiff(test_out, pagew)
d7403ad2 156 self.DC.DrawText(test_out, indent+diff/2, y)
d14a1e28 157
b881fc78 158 elif align == wx.ALIGN_RIGHT:
d14a1e28 159 diff = self.GetCellDiff(test_out, pagew)
d7403ad2 160 self.DC.DrawText(test_out, indent+diff, y)
d14a1e28
RD
161
162 else:
d7403ad2 163 self.DC.DrawText(test_out, indent, y_out)
d14a1e28
RD
164 text = remain
165 y = y + y_line
166 return y - y_line
167
168 def GetDate(self):
169 date, time = self.GetNow()
170 return date
171
172 def GetDateTime(self):
173 date, time = self.GetNow()
174 return date + ' ' + time
175
176 def GetNow(self):
c5d11c71
RD
177 now = wx.DateTime.Now()
178 date = now.FormatDate()
179 time = now.FormatTime()
d14a1e28
RD
180 return date, time
181
182 def SetPreview(self, preview):
183 self.preview = preview
184
185 def SetPSize(self, width, height):
186 self.pwidth = width/self.scale
187 self.pheight = height/self.scale
188
189 def SetScale(self, scale):
190 self.scale = scale
191
192 def SetPTSize(self, width, height):
193 self.ptwidth = width
194 self.ptheight = height
195
196 def getWidth(self):
197 return self.sizew
198
199 def getHeight(self):
200 return self.sizeh
201
202
b881fc78 203class PrintTableDraw(wx.ScrolledWindow, PrintBase):
d14a1e28
RD
204 def __init__(self, parent, DC, size):
205 self.parent = parent
206 self.DC = DC
207 self.scale = parent.scale
208 self.width = size[0]
209 self.height = size[1]
210 self.SetDefaults()
211
212 def SetDefaults(self):
213 self.page = 1
214 self.total_pages = None
215
216 self.page_width = self.parent.page_width
217 self.page_height = self.parent.page_height
218
219 self.left_margin = self.parent.left_margin
220 self.right_margin = self.parent.right_margin
221
222 self.top_margin = self.parent.top_margin
223 self.bottom_margin = self.parent.bottom_margin
224 self.cell_left_margin = self.parent.cell_left_margin
225 self.cell_right_margin = self.parent.cell_right_margin
226
227 self.label_colour = self.parent.label_colour
228
229 self.row_line_colour = self.parent.row_line_colour
230 self.row_line_size = self.parent.row_line_size
231
232 self.row_def_line_colour = self.parent.row_def_line_colour
233 self.row_def_line_size = self.parent.row_def_line_size
234
235 self.column_line_colour = self.parent.column_line_colour
236 self.column_line_size = self.parent.column_line_size
237
238 self.column_def_line_size = self.parent.column_def_line_size
239 self.column_def_line_colour = self.parent.column_def_line_colour
240
241 self.text_font = self.parent.text_font
242
243 self.label_font = self.parent.label_font
244
245 def AdjustValues(self):
246 self.vertical_offset = self.pheight * self.parent.vertical_offset
247 self.horizontal_offset = self.pheight * self.parent.horizontal_offset
248
249 self.pcell_left_margin = self.pwidth * self.cell_left_margin
250 self.pcell_right_margin = self.pwidth * self.cell_right_margin
251 self.ptop_margin = self.pheight * self.top_margin
252 self.pbottom_margin = self.pheight * self.bottom_margin
253
254 self.pheader_margin = self.pheight * self.parent.header_margin
255 self.pfooter_margin = self.pheight * self.parent.footer_margin
256
257 self.cell_colour = self.parent.set_cell_colour
258 self.cell_text = self.parent.set_cell_text
259
260 self.column = []
261 self.column_align = []
262 self.column_bgcolour = []
263 self.column_txtcolour = []
264
265 set_column_align = self.parent.set_column_align
266 set_column_bgcolour = self.parent.set_column_bgcolour
267 set_column_txtcolour = self.parent.set_column_txtcolour
268
269 pos_x = self.left_margin * self.pwidth + self.horizontal_offset # left margin
270 self.column.append(pos_x)
271
02b800ce
RD
272 #module logic expects two dimensional data -- fix input if needed
273 if isinstance(self.data,types.StringTypes):
274 self.data = [[copy.copy(self.data)]] # a string becomes a single cell
275 try:
276 rows = len(self.data)
277 except TypeError:
278 self.data = [[str(self.data)]] # a non-iterable becomes a single cell
279 rows = 1
280 first_value = self.data[0]
281
282 if isinstance(first_value, types.StringTypes): # a sequence of strings
283 if self.label == [] and self.set_column == []:
284 data = []
285 for x in self.data: #becomes one column
286 data.append([x])
287 else:
288 data = [self.data] #becames one row
289 self.data = data
290 first_value = data[0]
291 try:
292 column_total = len(first_value)
293 except TypeError: # a sequence of non-iterables
294 if self.label == [] and self.set_column == []:
295 data = [] #becomes one column
296 for x in self.data:
297 data.append([str(x)])
298 column_total = 1
299 else:
300 data = [self.data] #becomes one row
301 column_total = len(self.data)
302 self.data = data
303 first_value = data[0]
304
d14a1e28
RD
305 if self.set_column == []:
306 table_width = self.page_width - self.left_margin - self.right_margin
02b800ce
RD
307 if self.label == []:
308 temp = first_value
309 else:
310 temp = self.label
311 width = table_width/(len(temp))
312 for val in temp:
d14a1e28
RD
313 column_width = width * self.pwidth
314 pos_x = pos_x + column_width
315 self.column.append(pos_x) # position of each column
316 else:
317 for val in self.set_column:
318 column_width = val * self.pwidth
319 pos_x = pos_x + column_width
320 self.column.append(pos_x) # position of each column
321
322 if pos_x > self.page_width * self.pwidth: # check if it fits in page
323 print "Warning, Too Wide for Page"
324 return
325
326 if self.label != []:
327 if len(self.column) -1 != len(self.label):
328 print "Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label)
329 return
330
d14a1e28 331 if column_total != len(self.column) -1:
02b800ce 332 print "Cannot fit", first_value, 'in', len(self.column)-1, 'columns.'
d14a1e28
RD
333 return
334
d14a1e28
RD
335 for col in range(column_total):
336 try:
337 align = set_column_align[col] # check if custom column alignment
338 except:
b881fc78 339 align = wx.ALIGN_LEFT
d14a1e28
RD
340 self.column_align.append(align)
341
342 try:
343 colour = set_column_bgcolour[col] # check if custom column background colour
344 except:
345 colour = self.parent.column_colour
346 self.column_bgcolour.append(colour)
347
348 try:
349 colour = set_column_txtcolour[col] # check if custom column text colour
350 except:
351 colour = self.GetFontColour(self.parent.text_font)
d14a1e28
RD
352 self.column_txtcolour.append(colour)
353
d14a1e28
RD
354
355 def SetPointAdjust(self):
b881fc78 356 f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # setup using 10 point
d14a1e28
RD
357 self.DC.SetFont(f)
358 f.SetFaceName(self.text_font["Name"])
359 x, y = self.DC.GetTextExtent("W")
360
361 self.label_pt_space_before = self.parent.label_pt_adj_before * y/10 # extra spacing for label per point value
362 self.label_pt_space_after = self.parent.label_pt_adj_after * y/10
363
364 self.text_pt_space_before = self.parent.text_pt_adj_before * y/10 # extra spacing for row text per point value
365 self.text_pt_space_after = self.parent.text_pt_adj_after * y/10
366
367 def SetPage(self, page):
368 self.page = page
369
370 def SetColumns(self, col):
371 self.column = col
372
373 def OutCanvas(self):
374 self.AdjustValues()
375 self.SetPointAdjust()
376
377 self.y_start = self.ptop_margin + self.vertical_offset
378 self.y_end = self.parent.page_height * self.pheight - self.pbottom_margin + self.vertical_offset
379
380 self.SetPrintFont(self.label_font)
381
382 x, y = self.DC.GetTextExtent("W")
383 self.label_space = y
384
385 self.SetPrintFont(self.text_font)
386
387 x, y = self.DC.GetTextExtent("W")
388 self.space = y
389
390 if self.total_pages is None:
391 self.GetTotalPages() # total pages for display/printing
392
393 self.data_cnt = self.page_index[self.page-1]
394
395 self.draw = True
396 self.PrintHeader()
397 self.PrintFooter()
398 self.OutPage()
399
400 def GetTotalPages(self):
401 self.data_cnt = 0
402 self.draw = False
403 self.page_index = [0]
404
405 cnt = 0
406 while 1:
407 test = self.OutPage()
408 self.page_index.append(self.data_cnt)
409 if test == False:
410 break
411 cnt = cnt + 1
412
413 self.total_pages = cnt + 1
414
415 def OutPage(self):
416 self.y = self.y_start
417 self.end_x = self.column[-1]
418
419 if self.data_cnt < len(self.data): # if there data for display on the page
420 if self.label != []: # check if header defined
421 self.PrintLabel()
422 else:
423 return False
424
425 for val in self.data:
426 try:
427 row_val = self.data[self.data_cnt]
428 except:
429 self.FinishDraw()
430 return False
431
432 max_y = self.PrintRow(row_val, False) # test to see if row will fit in remaining space
433 test = max_y + self.space
434
435 if test > self.y_end:
436 break
437
438 self.ColourRowCells(max_y-self.y+self.space) # colour the row/column
439 max_y = self.PrintRow(row_val, True) # row fits - print text
440 self.DrawGridLine() # top line of cell
441 self.y = max_y + self.space
442
443 if self.y > self.y_end:
444 break
445
446 self.data_cnt = self.data_cnt + 1
447
448 self.FinishDraw()
449
450 if self.data_cnt == len(self.data): # last value in list
451 return False
452
453 return True
454
455
456 def PrintLabel(self):
457 self.pt_space_before = self.label_pt_space_before # set the point spacing
458 self.pt_space_after = self.label_pt_space_after
459
460 self.LabelColorRow(self.label_colour)
461 self.SetPrintFont(self.label_font)
462
463 self.col = 0
464 max_y = 0
465 for vtxt in self.label:
466 self.region = self.column[self.col+1] - self.column[self.col]
467 self.indent = self.column[self.col]
468
b881fc78 469 self.align = wx.ALIGN_LEFT
d14a1e28
RD
470
471 max_out = self.OutTextRegion(vtxt, True)
472 if max_out > max_y:
473 max_y = max_out
474 self.col = self.col + 1
475
476 self.DrawGridLine() # top line of label
477 self.y = max_y + self.label_space
478
479 def PrintHeader(self): # print the header array
480 if self.draw == False:
481 return
482
483 for val in self.parent.header:
484 self.SetPrintFont(val["Font"])
485
486 header_indent = val["Indent"] * self.pwidth
487 text = val["Text"]
488
489 htype = val["Type"]
490 if htype == "Date":
491 addtext = self.GetDate()
492 elif htype == "Date & Time":
493 addtext = self.GetDateTime()
494 else:
495 addtext = ""
496
497 self.OutTextPageWidth(text+addtext, self.pheader_margin, val["Align"], header_indent, True)
498
499 def PrintFooter(self): # print the header array
500 if self.draw == False:
501 return
502
503 footer_pos = self.parent.page_height * self.pheight - self.pfooter_margin + self.vertical_offset
504 for val in self.parent.footer:
505 self.SetPrintFont(val["Font"])
506
507 footer_indent = val["Indent"] * self.pwidth
508 text = val["Text"]
509
510 ftype = val["Type"]
511 if ftype == "Pageof":
512 addtext = "Page " + str(self.page) + " of " + str(self.total_pages)
513 elif ftype == "Page":
514 addtext = "Page " + str(self.page)
515 elif ftype == "Num":
516 addtext = str(self.page)
517 elif ftype == "Date":
518 addtext = self.GetDate()
519 elif ftype == "Date & Time":
520 addtext = self.GetDateTime()
521 else:
522 addtext = ""
523
524 self.OutTextPageWidth(text+addtext, footer_pos, val["Align"], footer_indent, True)
525
526
527 def LabelColorRow(self, colour):
b881fc78 528 brush = wx.Brush(colour, wx.SOLID)
d14a1e28
RD
529 self.DC.SetBrush(brush)
530 height = self.label_space + self.label_pt_space_before + self.label_pt_space_after
d7403ad2
RD
531 self.DC.DrawRectangle(self.column[0], self.y,
532 self.end_x-self.column[0]+1, height)
d14a1e28
RD
533
534 def ColourRowCells(self, height):
535 if self.draw == False:
536 return
537
538 col = 0
539 for colour in self.column_bgcolour:
540 cellcolour = self.GetCellColour(self.data_cnt, col)
541 if cellcolour is not None:
542 colour = cellcolour
543
b881fc78 544 brush = wx.Brush(colour, wx.SOLID)
d14a1e28 545 self.DC.SetBrush(brush)
b881fc78 546 self.DC.SetPen(wx.Pen(wx.NamedColour('WHITE'), 0))
d14a1e28
RD
547
548 start_x = self.column[col]
549 width = self.column[col+1] - start_x + 2
d7403ad2 550 self.DC.DrawRectangle(start_x, self.y, width, height)
d14a1e28
RD
551 col = col + 1
552
b881fc78 553 def PrintRow(self, row_val, draw = True, align = wx.ALIGN_LEFT):
d14a1e28
RD
554 self.SetPrintFont(self.text_font)
555
556 self.pt_space_before = self.text_pt_space_before # set the point spacing
557 self.pt_space_after = self.text_pt_space_after
558
559 self.col = 0
560 max_y = 0
561 for vtxt in row_val:
02b800ce
RD
562 if not isinstance(vtxt,types.StringTypes):
563 vtxt = str(vtxt)
d14a1e28
RD
564 self.region = self.column[self.col+1] - self.column[self.col]
565 self.indent = self.column[self.col]
566 self.align = self.column_align[self.col]
567
568 fcolour = self.column_txtcolour[self.col] # set font colour
02b800ce 569 celltext = self.GetCellTextColour(self.data_cnt, self.col)
d14a1e28
RD
570 if celltext is not None:
571 fcolour = celltext # override the column colour
572
573 self.DC.SetTextForeground(fcolour)
574
575 max_out = self.OutTextRegion(vtxt, draw)
576 if max_out > max_y:
577 max_y = max_out
578 self.col = self.col + 1
579 return max_y
580
581 def GetCellColour(self, row, col): # check if custom colour defined for the cell background
582 try:
583 set = self.cell_colour[row]
584 except:
585 return None
586 try:
587 colour = set[col]
588 return colour
589 except:
590 return None
591
02b800ce 592 def GetCellTextColour(self, row, col): # check if custom colour defined for the cell text
d14a1e28
RD
593 try:
594 set = self.cell_text[row]
595 except:
596 return None
597 try:
598 colour = set[col]
599 return colour
600 except:
601 return None
602
603 def FinishDraw(self):
604 self.DrawGridLine() # draw last row line
605 self.DrawColumns() # draw all vertical lines
606
607 def DrawGridLine(self):
02b800ce
RD
608 if self.draw == True \
609 and len(self.column) > 2: #supress grid lines if only one column
d14a1e28
RD
610 try:
611 size = self.row_line_size[self.data_cnt]
612 except:
613 size = self.row_def_line_size
614
9f54c187
RD
615 if size < 1: return
616
d14a1e28
RD
617 try:
618 colour = self.row_line_colour[self.data_cnt]
619 except:
620 colour = self.row_def_line_colour
621
b881fc78 622 self.DC.SetPen(wx.Pen(colour, size))
d14a1e28
RD
623
624 y_out = self.y
625# y_out = self.y + self.pt_space_before + self.pt_space_after # adjust for extra spacing
d7403ad2 626 self.DC.DrawLine(self.column[0], y_out, self.end_x, y_out)
d14a1e28
RD
627
628 def DrawColumns(self):
02b800ce
RD
629 if self.draw == True \
630 and len(self.column) > 2: #surpress grid line if only one column
d14a1e28
RD
631 col = 0
632 for val in self.column:
633 try:
634 size = self.column_line_size[col]
635 except:
636 size = self.column_def_line_size
637
9f54c187
RD
638 if size < 1: continue
639
d14a1e28
RD
640 try:
641 colour = self.column_line_colour[col]
642 except:
643 colour = self.column_def_line_colour
644
645 indent = val
646
b881fc78 647 self.DC.SetPen(wx.Pen(colour, size))
d7403ad2 648 self.DC.DrawLine(indent, self.y_start, indent, self.y)
d14a1e28
RD
649 col = col + 1
650
651 def DrawText(self):
652 self.DoRefresh()
653
654 def DoDrawing(self, DC):
b881fc78 655 size = DC.GetSize()
d14a1e28
RD
656 self.DC = DC
657
658 DC.BeginDrawing()
659 self.DrawText()
660 DC.EndDrawing()
661
662 self.sizew = DC.MaxY()
663 self.sizeh = DC.MaxX()
664
665
666class PrintTable:
667 def __init__(self, parentFrame=None):
668 self.data = []
669 self.set_column = []
670 self.label = []
671 self.header = []
672 self.footer = []
673
674 self.set_column_align = {}
675 self.set_column_bgcolour = {}
676 self.set_column_txtcolour = {}
677 self.set_cell_colour = {}
678 self.set_cell_text = {}
679 self.column_line_size = {}
680 self.column_line_colour = {}
681 self.row_line_size = {}
682 self.row_line_colour = {}
683
684 self.parentFrame = parentFrame
685 self.SetPreviewSize()
686
b881fc78 687 self.printData = wx.PrintData()
d14a1e28
RD
688 self.scale = 1.0
689
690 self.SetParms()
691 self.SetColors()
692 self.SetFonts()
693 self.TextSpacing()
694
695 self.SetPrinterOffset()
696 self.SetHeaderValue()
697 self.SetFooterValue()
698 self.SetMargins()
699 self.SetPortrait()
700
b881fc78 701 def SetPreviewSize(self, position = wx.Point(0, 0), size="Full"):
d14a1e28 702 if size == "Full":
b881fc78
RD
703 r = wx.GetClientDisplayRect()
704 self.preview_frame_size = r.GetSize()
705 self.preview_frame_pos = r.GetPosition()
d14a1e28
RD
706 else:
707 self.preview_frame_size = size
708 self.preview_frame_pos = position
709
710 def SetPaperId(self, paper):
711 self.printData.SetPaperId(paper)
712
713 def SetOrientation(self, orient):
714 self.printData.SetOrientation(orient)
715
716 def SetColors(self):
b881fc78 717 self.row_def_line_colour = wx.NamedColour('BLACK')
d14a1e28
RD
718 self.row_def_line_size = 1
719
b881fc78 720 self.column_def_line_colour = wx.NamedColour('BLACK')
d14a1e28 721 self.column_def_line_size = 1
b881fc78 722 self.column_colour = wx.NamedColour('WHITE')
d14a1e28 723
b881fc78 724 self.label_colour = wx.NamedColour('LIGHT GREY')
d14a1e28
RD
725
726 def SetFonts(self):
727 self.label_font = { "Name": self.default_font_name, "Size": 12, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
728 self.text_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
729
730 def TextSpacing(self):
731 self.label_pt_adj_before = 0 # point adjustment before and after the label text
732 self.label_pt_adj_after = 0
733
734 self.text_pt_adj_before = 0 # point adjustment before and after the row text
735 self.text_pt_adj_after = 0
736
737 def SetLabelSpacing(self, before, after): # method to set the label space adjustment
738 self.label_pt_adj_before = before
739 self.label_pt_adj_after = after
740
741 def SetRowSpacing(self, before, after): # method to set the row space adjustment
742 self.text_pt_adj_before = before
743 self.text_pt_adj_after = after
744
745 def SetPrinterOffset(self): # offset to adjust for printer
746 self.vertical_offset = -0.1
747 self.horizontal_offset = -0.1
748
749 def SetHeaderValue(self):
750 self.header_margin = 0.25
751 self.header_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
b881fc78 752 self.header_align = wx.ALIGN_CENTRE
d14a1e28
RD
753 self.header_indent = 0
754 self.header_type = "Text"
755
756 def SetFooterValue(self):
757 self.footer_margin = 0.7
758 self.footer_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
b881fc78 759 self.footer_align = wx.ALIGN_CENTRE
d14a1e28
RD
760 self.footer_indent = 0
761 self.footer_type = "Pageof"
762
763 def SetMargins(self):
02b800ce
RD
764 self.left_margin = 0.5
765 self.right_margin = 0.5 # only used if no column sizes
d14a1e28
RD
766
767 self.top_margin = 0.8
768 self.bottom_margin = 1.0
769 self.cell_left_margin = 0.1
770 self.cell_right_margin = 0.1
771
772 def SetPortrait(self):
b881fc78
RD
773 self.printData.SetPaperId(wx.PAPER_LETTER)
774 self.printData.SetOrientation(wx.PORTRAIT)
d14a1e28
RD
775 self.page_width = 8.5
776 self.page_height = 11.0
777
778 def SetLandscape(self):
b881fc78 779 self.printData.SetOrientation(wx.LANDSCAPE)
d14a1e28
RD
780 self.page_width = 11.0
781 self.page_height = 8.5
782
783 def SetParms(self):
784 self.ymax = 1
785 self.xmax = 1
786 self.page = 1
787 self.total_pg = 100
788
789 self.preview = None
790 self.page = 0
791
792 self.default_font_name = "Arial"
793 self.default_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
794
b881fc78 795 def SetColAlignment(self, col, align=wx.ALIGN_LEFT):
d14a1e28
RD
796 self.set_column_align[col] = align
797
798 def SetColBackgroundColour(self, col, colour):
799 self.set_column_bgcolour[col] = colour
800
801 def SetColTextColour(self, col, colour):
802 self.set_column_txtcolour[col] = colour
803
804 def SetCellColour(self, row, col, colour): # cell background colour
805 try:
806 set = self.set_cell_colour[row] # test if row already exists
807 try:
808 set[col] = colour # test if column already exists
809 except:
810 set = { col: colour } # create the column value
811 except:
812 set = { col: colour } # create the column value
813
814 self.set_cell_colour[row] = set # create dictionary item for colour settings
815
816 def SetCellText(self, row, col, colour): # font colour for custom cells
817 try:
818 set = self.set_cell_text[row] # test if row already exists
819 try:
820 set[col] = colour # test if column already exists
821 except:
822 set = { col: colour } # create the column value
823 except:
824 set = { col: colour } # create the column value
825
826 self.set_cell_text[row] = set # create dictionary item for colour settings
827
828 def SetColumnLineSize(self, col, size): # column line size
829 self.column_line_size[col] = size # create dictionary item for column line settings
830
831 def SetColumnLineColour(self, col, colour):
832 self.column_line_colour[col] = colour
833
834 def SetRowLineSize(self, row, size):
835 self.row_line_size[row] = size
836
837 def SetRowLineColour(self, row, colour):
838 self.row_line_colour[row] = colour
839
840 def GetColour(self, colour): # returns colours based from wxColour value
841 red = colour.Red()
842 blue = colour.Blue()
843 green = colour.Green()
844 return [red, green, blue ]
845
846 def SetHeader(self, text = "", type = "Text", font=None, align = None, indent = None, colour = None, size = None):
847 set = { "Text": text }
848
849 if font is None:
850 set["Font"] = copy.copy(self.default_font)
851 else:
852 set["Font"] = font
853
854 if colour is not None:
855 setfont = set["Font"]
856 setfont["Colour"] = self.GetColour(colour)
857
858 if size is not None:
859 setfont = set["Font"]
860 setfont["Size"] = size
861
862 if align is None:
863 set["Align"] = self.header_align
864 else:
865 set["Align"] = align
866
867 if indent is None:
868 set["Indent"] = self.header_indent
869 else:
870 set["Indent"] = indent
871
872 if type is None:
873 set["Type"] = self.header_type
874 else:
875 set["Type"] = type
876
877 self.header.append(set)
878
879 def SetFooter(self, text = "", type = None, font=None, align = None, indent = None, colour = None, size = None):
880 set = { "Text": text }
881
882 if font is None:
883 set["Font"] = copy.copy(self.default_font)
884 else:
885 set["Font"] = font
886
887 if colour is not None:
888 setfont = set["Font"]
889 setfont["Colour"] = self.GetColour(colour)
890
891 if size is not None:
892 setfont = set["Font"]
893 setfont["Size"] = size
894
895 if align is None:
896 set["Align"] = self.footer_align
897 else:
898 set["Align"] = align
899
900 if indent is None:
901 set["Indent"] = self.footer_indent
902 else:
903 set["Indent"] = indent
904
905 if type is None:
906 set["Type"] = self.footer_type
907 else:
908 set["Type"] = type
909
910 self.footer.append(set)
911
912 def Preview(self):
02b800ce 913 data = wx.PrintDialogData(self.printData)
d14a1e28
RD
914 printout = SetPrintout(self)
915 printout2 = SetPrintout(self)
02b800ce 916 self.preview = wx.PrintPreview(printout, printout2, data)
d14a1e28 917 if not self.preview.Ok():
4dca6329 918 wx.MessageBox("There was a problem printing!", "Printing", wx.OK)
d14a1e28
RD
919 return
920
921 self.preview.SetZoom(60) # initial zoom value
b881fc78 922 frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
d14a1e28
RD
923
924 frame.Initialize()
925 if self.parentFrame:
926 frame.SetPosition(self.preview_frame_pos)
927 frame.SetSize(self.preview_frame_size)
928 frame.Show(True)
929
930 def Print(self):
02b800ce 931 pdd = wx.PrintDialogData(self.printData)
b881fc78 932 printer = wx.Printer(pdd)
d14a1e28
RD
933 printout = SetPrintout(self)
934 if not printer.Print(self.parentFrame, printout):
b881fc78 935 wx.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx.OK)
d14a1e28 936 else:
02b800ce 937 self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
d14a1e28
RD
938 printout.Destroy()
939
940 def DoDrawing(self, DC):
b881fc78 941 size = DC.GetSize()
d14a1e28
RD
942 DC.BeginDrawing()
943
944 table = PrintTableDraw(self, DC, size)
945 table.data = self.data
946 table.set_column = self.set_column
947 table.label = self.label
948 table.SetPage(self.page)
949
950 if self.preview is None:
951 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
952 table.SetPTSize(size[0], size[1])
953 table.SetPreview(False)
954 else:
955 if self.preview == 1:
956 table.scale = self.scale
957 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
958 else:
959 table.SetPSize(self.pwidth, self.pheight)
960
961 table.SetPTSize(self.ptwidth, self.ptheight)
962 table.SetPreview(self.preview)
963
964 table.OutCanvas()
965 self.page_total = table.total_pages # total display pages
966
967 DC.EndDrawing()
968
969 self.ymax = DC.MaxY()
970 self.xmax = DC.MaxX()
971
972 self.sizeh = size[0]
973 self.sizew = size[1]
974
975 def GetTotalPages(self):
976 self.page_total = 100
977 return self.page_total
978
979 def HasPage(self, page):
980 if page <= self.page_total:
981 return True
982 else:
983 return False
984
985 def SetPage(self, page):
986 self.page = page
987
988 def SetPageSize(self, width, height):
989 self.pwidth, self.pheight = width, height
990
991 def SetTotalSize(self, width, height):
992 self.ptwidth, self.ptheight = width, height
993
994 def SetPreview(self, preview, scale):
995 self.preview = preview
996 self.scale = scale
997
998 def SetTotalSize(self, width, height):
999 self.ptwidth = width
1000 self.ptheight = height
1001
1002class PrintGrid:
1003 def __init__(self, parent, grid, format = [], total_col = None, total_row = None):
1004 if total_row is None:
1005 total_row = grid.GetNumberRows()
1006 if total_col is None:
1007 total_col = grid.GetNumberCols()
1008
1009 self.total_row = total_row
1010 self.total_col = total_col
1011 self.grid = grid
1012
1013 data = []
1014 for row in range(total_row):
1015 row_val = []
1016 value = grid.GetRowLabelValue(row)
1017 row_val.append(value)
1018
1019 for col in range(total_col):
1020 value = grid.GetCellValue(row, col)
1021 row_val.append(value)
1022 data.append(row_val)
1023
1024 label = [""]
1025 for col in range(total_col):
1026 value = grid.GetColLabelValue(col)
1027 label.append(value)
1028
1029 self.table = PrintTable(parent)
1030 self.table.cell_left_margin = 0.0
1031 self.table.cell_right_margin = 0.0
1032
1033 self.table.label = label
1034 self.table.set_column = format
1035 self.table.data = data
1036
1037 def GetTable(self):
1038 return self.table
1039
1040 def SetAttributes(self):
1041 for row in range(self.total_row):
1042 for col in range(self.total_col):
1043 colour = self.grid.GetCellTextColour(row, col-1)
1044 self.table.SetCellText(row, col, colour)
1045
1046 colour = self.grid.GetCellBackgroundColour(row, col-1)
1047 self.table.SetCellColour(row, col, colour)
1048
1049 def Preview(self):
1050 self.table.Preview()
1051
1052 def Print(self):
1053 self.table.Print()
1054
1055
b881fc78 1056class SetPrintout(wx.Printout):
d14a1e28 1057 def __init__(self, canvas):
b881fc78 1058 wx.Printout.__init__(self)
d14a1e28
RD
1059 self.canvas = canvas
1060 self.end_pg = 1000
1061
1062 def OnBeginDocument(self, start, end):
a7a01418 1063 return super(SetPrintout, self).OnBeginDocument(start, end)
d14a1e28
RD
1064
1065 def OnEndDocument(self):
a7a01418 1066 super(SetPrintout, self).OnEndDocument()
d14a1e28
RD
1067
1068 def HasPage(self, page):
1069 try:
1070 end = self.canvas.HasPage(page)
1071 return end
1072 except:
1073 return True
1074
1075 def GetPageInfo(self):
1076 try:
1077 self.end_pg = self.canvas.GetTotalPages()
1078 except:
1079 pass
1080
1081 end_pg = self.end_pg
1082 str_pg = 1
1083 return (str_pg, end_pg, str_pg, end_pg)
1084
1085 def OnPreparePrinting(self):
a7a01418 1086 super(SetPrintout, self).OnPreparePrinting()
d14a1e28
RD
1087
1088 def OnBeginPrinting(self):
1089 dc = self.GetDC()
1090
1091 self.preview = self.IsPreview()
1092 if (self.preview):
1093 self.pixelsPerInch = self.GetPPIScreen()
1094 else:
1095 self.pixelsPerInch = self.GetPPIPrinter()
1096
b881fc78 1097 (w, h) = dc.GetSize()
d14a1e28
RD
1098 scaleX = float(w) / 1000
1099 scaleY = float(h) / 1000
1100 self.printUserScale = min(scaleX, scaleY)
1101
a7a01418 1102 super(SetPrintout, self).OnBeginPrinting()
d14a1e28
RD
1103
1104 def GetSize(self):
1105 self.psizew, self.psizeh = self.GetPPIPrinter()
1106 return self.psizew, self.psizeh
1107
1108 def GetTotalSize(self):
1109 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1110 return self.ptsizew, self.ptsizeh
1111
1112 def OnPrintPage(self, page):
1113 dc = self.GetDC()
b881fc78 1114 (w, h) = dc.GetSize()
d14a1e28
RD
1115 scaleX = float(w) / 1000
1116 scaleY = float(h) / 1000
1117 self.printUserScale = min(scaleX, scaleY)
1118 dc.SetUserScale(self.printUserScale, self.printUserScale)
1119
1120 self.preview = self.IsPreview()
1121
1122 self.canvas.SetPreview(self.preview, self.printUserScale)
1123 self.canvas.SetPage(page)
1124
1125 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1126 self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
1127
1128 self.psizew, self.psizeh = self.GetPPIPrinter()
1129 self.canvas.SetPageSize(self.psizew, self.psizeh)
1130
1131 self.canvas.DoDrawing(dc)
1132 return True
1133
02b800ce
RD
1134if __name__ == '__main__':
1135 app = wx.PySimpleApp()
1136 frame = wx.Frame(None, -1, "Dummy wx frame for testing printout.py")
1137 frame.Show(True)
1138 ptbl = PrintTable(frame)
1139 ptbl.SetHeader('This is the test HEADER')
1140 # a single sequence will print out as a single column with no borders ...
1141 ptbl.data = (
1142 'This is the first line of text.',
1143 'This is the second line\nand the third. The fourth will be the number "4.0".',
1144 04.00,
1145 'This is the fifth line, but by design it is too long to fit in the width of a standard'\
1146 ' page, so it will be forced to wrap around in order to fit without having '\
1147 'some of its verbose verbage truncated.',
1148 'Here we have the final line.'
1149 )
1150 #... but, if labels or columns are defined, a single sequence will print out as a single row
1151 ##ptbl.label = ('One','Two','Three','Four','5')
1152 ptbl.Preview()
1153 app.MainLoop()