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