]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/printout.py
Use MustHaveApp for wx.RendererNative.Get and others
[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
615 try:
616 colour = self.row_line_colour[self.data_cnt]
617 except:
618 colour = self.row_def_line_colour
619
b881fc78 620 self.DC.SetPen(wx.Pen(colour, size))
d14a1e28
RD
621
622 y_out = self.y
623# y_out = self.y + self.pt_space_before + self.pt_space_after # adjust for extra spacing
d7403ad2 624 self.DC.DrawLine(self.column[0], y_out, self.end_x, y_out)
d14a1e28
RD
625
626 def DrawColumns(self):
02b800ce
RD
627 if self.draw == True \
628 and len(self.column) > 2: #surpress grid line if only one column
d14a1e28
RD
629 col = 0
630 for val in self.column:
631 try:
632 size = self.column_line_size[col]
633 except:
634 size = self.column_def_line_size
635
636 try:
637 colour = self.column_line_colour[col]
638 except:
639 colour = self.column_def_line_colour
640
641 indent = val
642
b881fc78 643 self.DC.SetPen(wx.Pen(colour, size))
d7403ad2 644 self.DC.DrawLine(indent, self.y_start, indent, self.y)
d14a1e28
RD
645 col = col + 1
646
647 def DrawText(self):
648 self.DoRefresh()
649
650 def DoDrawing(self, DC):
b881fc78 651 size = DC.GetSize()
d14a1e28
RD
652 self.DC = DC
653
654 DC.BeginDrawing()
655 self.DrawText()
656 DC.EndDrawing()
657
658 self.sizew = DC.MaxY()
659 self.sizeh = DC.MaxX()
660
661
662class PrintTable:
663 def __init__(self, parentFrame=None):
664 self.data = []
665 self.set_column = []
666 self.label = []
667 self.header = []
668 self.footer = []
669
670 self.set_column_align = {}
671 self.set_column_bgcolour = {}
672 self.set_column_txtcolour = {}
673 self.set_cell_colour = {}
674 self.set_cell_text = {}
675 self.column_line_size = {}
676 self.column_line_colour = {}
677 self.row_line_size = {}
678 self.row_line_colour = {}
679
680 self.parentFrame = parentFrame
681 self.SetPreviewSize()
682
b881fc78 683 self.printData = wx.PrintData()
d14a1e28
RD
684 self.scale = 1.0
685
686 self.SetParms()
687 self.SetColors()
688 self.SetFonts()
689 self.TextSpacing()
690
691 self.SetPrinterOffset()
692 self.SetHeaderValue()
693 self.SetFooterValue()
694 self.SetMargins()
695 self.SetPortrait()
696
b881fc78 697 def SetPreviewSize(self, position = wx.Point(0, 0), size="Full"):
d14a1e28 698 if size == "Full":
b881fc78
RD
699 r = wx.GetClientDisplayRect()
700 self.preview_frame_size = r.GetSize()
701 self.preview_frame_pos = r.GetPosition()
d14a1e28
RD
702 else:
703 self.preview_frame_size = size
704 self.preview_frame_pos = position
705
706 def SetPaperId(self, paper):
707 self.printData.SetPaperId(paper)
708
709 def SetOrientation(self, orient):
710 self.printData.SetOrientation(orient)
711
712 def SetColors(self):
b881fc78 713 self.row_def_line_colour = wx.NamedColour('BLACK')
d14a1e28
RD
714 self.row_def_line_size = 1
715
b881fc78 716 self.column_def_line_colour = wx.NamedColour('BLACK')
d14a1e28 717 self.column_def_line_size = 1
b881fc78 718 self.column_colour = wx.NamedColour('WHITE')
d14a1e28 719
b881fc78 720 self.label_colour = wx.NamedColour('LIGHT GREY')
d14a1e28
RD
721
722 def SetFonts(self):
723 self.label_font = { "Name": self.default_font_name, "Size": 12, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
724 self.text_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
725
726 def TextSpacing(self):
727 self.label_pt_adj_before = 0 # point adjustment before and after the label text
728 self.label_pt_adj_after = 0
729
730 self.text_pt_adj_before = 0 # point adjustment before and after the row text
731 self.text_pt_adj_after = 0
732
733 def SetLabelSpacing(self, before, after): # method to set the label space adjustment
734 self.label_pt_adj_before = before
735 self.label_pt_adj_after = after
736
737 def SetRowSpacing(self, before, after): # method to set the row space adjustment
738 self.text_pt_adj_before = before
739 self.text_pt_adj_after = after
740
741 def SetPrinterOffset(self): # offset to adjust for printer
742 self.vertical_offset = -0.1
743 self.horizontal_offset = -0.1
744
745 def SetHeaderValue(self):
746 self.header_margin = 0.25
747 self.header_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
b881fc78 748 self.header_align = wx.ALIGN_CENTRE
d14a1e28
RD
749 self.header_indent = 0
750 self.header_type = "Text"
751
752 def SetFooterValue(self):
753 self.footer_margin = 0.7
754 self.footer_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
b881fc78 755 self.footer_align = wx.ALIGN_CENTRE
d14a1e28
RD
756 self.footer_indent = 0
757 self.footer_type = "Pageof"
758
759 def SetMargins(self):
02b800ce
RD
760 self.left_margin = 0.5
761 self.right_margin = 0.5 # only used if no column sizes
d14a1e28
RD
762
763 self.top_margin = 0.8
764 self.bottom_margin = 1.0
765 self.cell_left_margin = 0.1
766 self.cell_right_margin = 0.1
767
768 def SetPortrait(self):
b881fc78
RD
769 self.printData.SetPaperId(wx.PAPER_LETTER)
770 self.printData.SetOrientation(wx.PORTRAIT)
d14a1e28
RD
771 self.page_width = 8.5
772 self.page_height = 11.0
773
774 def SetLandscape(self):
b881fc78 775 self.printData.SetOrientation(wx.LANDSCAPE)
d14a1e28
RD
776 self.page_width = 11.0
777 self.page_height = 8.5
778
779 def SetParms(self):
780 self.ymax = 1
781 self.xmax = 1
782 self.page = 1
783 self.total_pg = 100
784
785 self.preview = None
786 self.page = 0
787
788 self.default_font_name = "Arial"
789 self.default_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
790
b881fc78 791 def SetColAlignment(self, col, align=wx.ALIGN_LEFT):
d14a1e28
RD
792 self.set_column_align[col] = align
793
794 def SetColBackgroundColour(self, col, colour):
795 self.set_column_bgcolour[col] = colour
796
797 def SetColTextColour(self, col, colour):
798 self.set_column_txtcolour[col] = colour
799
800 def SetCellColour(self, row, col, colour): # cell background colour
801 try:
802 set = self.set_cell_colour[row] # test if row already exists
803 try:
804 set[col] = colour # test if column already exists
805 except:
806 set = { col: colour } # create the column value
807 except:
808 set = { col: colour } # create the column value
809
810 self.set_cell_colour[row] = set # create dictionary item for colour settings
811
812 def SetCellText(self, row, col, colour): # font colour for custom cells
813 try:
814 set = self.set_cell_text[row] # test if row already exists
815 try:
816 set[col] = colour # test if column already exists
817 except:
818 set = { col: colour } # create the column value
819 except:
820 set = { col: colour } # create the column value
821
822 self.set_cell_text[row] = set # create dictionary item for colour settings
823
824 def SetColumnLineSize(self, col, size): # column line size
825 self.column_line_size[col] = size # create dictionary item for column line settings
826
827 def SetColumnLineColour(self, col, colour):
828 self.column_line_colour[col] = colour
829
830 def SetRowLineSize(self, row, size):
831 self.row_line_size[row] = size
832
833 def SetRowLineColour(self, row, colour):
834 self.row_line_colour[row] = colour
835
836 def GetColour(self, colour): # returns colours based from wxColour value
837 red = colour.Red()
838 blue = colour.Blue()
839 green = colour.Green()
840 return [red, green, blue ]
841
842 def SetHeader(self, text = "", type = "Text", font=None, align = None, indent = None, colour = None, size = None):
843 set = { "Text": text }
844
845 if font is None:
846 set["Font"] = copy.copy(self.default_font)
847 else:
848 set["Font"] = font
849
850 if colour is not None:
851 setfont = set["Font"]
852 setfont["Colour"] = self.GetColour(colour)
853
854 if size is not None:
855 setfont = set["Font"]
856 setfont["Size"] = size
857
858 if align is None:
859 set["Align"] = self.header_align
860 else:
861 set["Align"] = align
862
863 if indent is None:
864 set["Indent"] = self.header_indent
865 else:
866 set["Indent"] = indent
867
868 if type is None:
869 set["Type"] = self.header_type
870 else:
871 set["Type"] = type
872
873 self.header.append(set)
874
875 def SetFooter(self, text = "", type = None, font=None, align = None, indent = None, colour = None, size = None):
876 set = { "Text": text }
877
878 if font is None:
879 set["Font"] = copy.copy(self.default_font)
880 else:
881 set["Font"] = font
882
883 if colour is not None:
884 setfont = set["Font"]
885 setfont["Colour"] = self.GetColour(colour)
886
887 if size is not None:
888 setfont = set["Font"]
889 setfont["Size"] = size
890
891 if align is None:
892 set["Align"] = self.footer_align
893 else:
894 set["Align"] = align
895
896 if indent is None:
897 set["Indent"] = self.footer_indent
898 else:
899 set["Indent"] = indent
900
901 if type is None:
902 set["Type"] = self.footer_type
903 else:
904 set["Type"] = type
905
906 self.footer.append(set)
907
908 def Preview(self):
02b800ce 909 data = wx.PrintDialogData(self.printData)
d14a1e28
RD
910 printout = SetPrintout(self)
911 printout2 = SetPrintout(self)
02b800ce 912 self.preview = wx.PrintPreview(printout, printout2, data)
d14a1e28 913 if not self.preview.Ok():
4dca6329 914 wx.MessageBox("There was a problem printing!", "Printing", wx.OK)
d14a1e28
RD
915 return
916
917 self.preview.SetZoom(60) # initial zoom value
b881fc78 918 frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
d14a1e28
RD
919
920 frame.Initialize()
921 if self.parentFrame:
922 frame.SetPosition(self.preview_frame_pos)
923 frame.SetSize(self.preview_frame_size)
924 frame.Show(True)
925
926 def Print(self):
02b800ce 927 pdd = wx.PrintDialogData(self.printData)
b881fc78 928 printer = wx.Printer(pdd)
d14a1e28
RD
929 printout = SetPrintout(self)
930 if not printer.Print(self.parentFrame, printout):
b881fc78 931 wx.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx.OK)
d14a1e28 932 else:
02b800ce 933 self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
d14a1e28
RD
934 printout.Destroy()
935
936 def DoDrawing(self, DC):
b881fc78 937 size = DC.GetSize()
d14a1e28
RD
938 DC.BeginDrawing()
939
940 table = PrintTableDraw(self, DC, size)
941 table.data = self.data
942 table.set_column = self.set_column
943 table.label = self.label
944 table.SetPage(self.page)
945
946 if self.preview is None:
947 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
948 table.SetPTSize(size[0], size[1])
949 table.SetPreview(False)
950 else:
951 if self.preview == 1:
952 table.scale = self.scale
953 table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
954 else:
955 table.SetPSize(self.pwidth, self.pheight)
956
957 table.SetPTSize(self.ptwidth, self.ptheight)
958 table.SetPreview(self.preview)
959
960 table.OutCanvas()
961 self.page_total = table.total_pages # total display pages
962
963 DC.EndDrawing()
964
965 self.ymax = DC.MaxY()
966 self.xmax = DC.MaxX()
967
968 self.sizeh = size[0]
969 self.sizew = size[1]
970
971 def GetTotalPages(self):
972 self.page_total = 100
973 return self.page_total
974
975 def HasPage(self, page):
976 if page <= self.page_total:
977 return True
978 else:
979 return False
980
981 def SetPage(self, page):
982 self.page = page
983
984 def SetPageSize(self, width, height):
985 self.pwidth, self.pheight = width, height
986
987 def SetTotalSize(self, width, height):
988 self.ptwidth, self.ptheight = width, height
989
990 def SetPreview(self, preview, scale):
991 self.preview = preview
992 self.scale = scale
993
994 def SetTotalSize(self, width, height):
995 self.ptwidth = width
996 self.ptheight = height
997
998class PrintGrid:
999 def __init__(self, parent, grid, format = [], total_col = None, total_row = None):
1000 if total_row is None:
1001 total_row = grid.GetNumberRows()
1002 if total_col is None:
1003 total_col = grid.GetNumberCols()
1004
1005 self.total_row = total_row
1006 self.total_col = total_col
1007 self.grid = grid
1008
1009 data = []
1010 for row in range(total_row):
1011 row_val = []
1012 value = grid.GetRowLabelValue(row)
1013 row_val.append(value)
1014
1015 for col in range(total_col):
1016 value = grid.GetCellValue(row, col)
1017 row_val.append(value)
1018 data.append(row_val)
1019
1020 label = [""]
1021 for col in range(total_col):
1022 value = grid.GetColLabelValue(col)
1023 label.append(value)
1024
1025 self.table = PrintTable(parent)
1026 self.table.cell_left_margin = 0.0
1027 self.table.cell_right_margin = 0.0
1028
1029 self.table.label = label
1030 self.table.set_column = format
1031 self.table.data = data
1032
1033 def GetTable(self):
1034 return self.table
1035
1036 def SetAttributes(self):
1037 for row in range(self.total_row):
1038 for col in range(self.total_col):
1039 colour = self.grid.GetCellTextColour(row, col-1)
1040 self.table.SetCellText(row, col, colour)
1041
1042 colour = self.grid.GetCellBackgroundColour(row, col-1)
1043 self.table.SetCellColour(row, col, colour)
1044
1045 def Preview(self):
1046 self.table.Preview()
1047
1048 def Print(self):
1049 self.table.Print()
1050
1051
b881fc78 1052class SetPrintout(wx.Printout):
d14a1e28 1053 def __init__(self, canvas):
b881fc78 1054 wx.Printout.__init__(self)
d14a1e28
RD
1055 self.canvas = canvas
1056 self.end_pg = 1000
1057
1058 def OnBeginDocument(self, start, end):
a7a01418 1059 return super(SetPrintout, self).OnBeginDocument(start, end)
d14a1e28
RD
1060
1061 def OnEndDocument(self):
a7a01418 1062 super(SetPrintout, self).OnEndDocument()
d14a1e28
RD
1063
1064 def HasPage(self, page):
1065 try:
1066 end = self.canvas.HasPage(page)
1067 return end
1068 except:
1069 return True
1070
1071 def GetPageInfo(self):
1072 try:
1073 self.end_pg = self.canvas.GetTotalPages()
1074 except:
1075 pass
1076
1077 end_pg = self.end_pg
1078 str_pg = 1
1079 return (str_pg, end_pg, str_pg, end_pg)
1080
1081 def OnPreparePrinting(self):
a7a01418 1082 super(SetPrintout, self).OnPreparePrinting()
d14a1e28
RD
1083
1084 def OnBeginPrinting(self):
1085 dc = self.GetDC()
1086
1087 self.preview = self.IsPreview()
1088 if (self.preview):
1089 self.pixelsPerInch = self.GetPPIScreen()
1090 else:
1091 self.pixelsPerInch = self.GetPPIPrinter()
1092
b881fc78 1093 (w, h) = dc.GetSize()
d14a1e28
RD
1094 scaleX = float(w) / 1000
1095 scaleY = float(h) / 1000
1096 self.printUserScale = min(scaleX, scaleY)
1097
a7a01418 1098 super(SetPrintout, self).OnBeginPrinting()
d14a1e28
RD
1099
1100 def GetSize(self):
1101 self.psizew, self.psizeh = self.GetPPIPrinter()
1102 return self.psizew, self.psizeh
1103
1104 def GetTotalSize(self):
1105 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1106 return self.ptsizew, self.ptsizeh
1107
1108 def OnPrintPage(self, page):
1109 dc = self.GetDC()
b881fc78 1110 (w, h) = dc.GetSize()
d14a1e28
RD
1111 scaleX = float(w) / 1000
1112 scaleY = float(h) / 1000
1113 self.printUserScale = min(scaleX, scaleY)
1114 dc.SetUserScale(self.printUserScale, self.printUserScale)
1115
1116 self.preview = self.IsPreview()
1117
1118 self.canvas.SetPreview(self.preview, self.printUserScale)
1119 self.canvas.SetPage(page)
1120
1121 self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
1122 self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
1123
1124 self.psizew, self.psizeh = self.GetPPIPrinter()
1125 self.canvas.SetPageSize(self.psizew, self.psizeh)
1126
1127 self.canvas.DoDrawing(dc)
1128 return True
1129
02b800ce
RD
1130if __name__ == '__main__':
1131 app = wx.PySimpleApp()
1132 frame = wx.Frame(None, -1, "Dummy wx frame for testing printout.py")
1133 frame.Show(True)
1134 ptbl = PrintTable(frame)
1135 ptbl.SetHeader('This is the test HEADER')
1136 # a single sequence will print out as a single column with no borders ...
1137 ptbl.data = (
1138 'This is the first line of text.',
1139 'This is the second line\nand the third. The fourth will be the number "4.0".',
1140 04.00,
1141 'This is the fifth line, but by design it is too long to fit in the width of a standard'\
1142 ' page, so it will be forced to wrap around in order to fit without having '\
1143 'some of its verbose verbage truncated.',
1144 'Here we have the final line.'
1145 )
1146 #... but, if labels or columns are defined, a single sequence will print out as a single row
1147 ##ptbl.label = ('One','Two','Three','Four','5')
1148 ptbl.Preview()
1149 app.MainLoop()