1 #---------------------------------------------------------------------------- 
   3 # Purpose:      preview and printing class -> table/grid printing 
   5 # Author:       Lorne White (email: lorne.white@telusplanet.net) 
  10 # Licence:      wxWindows license 
  11 #---------------------------------------------------------------------------- 
  14 # fixed bug for string wider than print region 
  15 # add index to data list after parsing total pages for paging 
  16 #---------------------------------------------------------------------------- 
  17 # 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net) 
  18 # o 2.5 compatability update. 
  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 
  30     def SetPrintFont(self
, font
):      # set the DC font parameters 
  43         fcolour 
= self
.GetFontColour(font
) 
  44         self
.DC
.SetTextForeground(fcolour
) 
  46         setfont 
= wx
.Font(font
["Size"], wx
.SWISS
, set_style
, weight
, underline
) 
  47         setfont
.SetFaceName(font
["Name"]) 
  48         self
.DC
.SetFont(setfont
) 
  50     def GetFontColour(self
, font
): 
  51         fcolour 
= font
["Colour"] 
  52         return wx
.Colour(fcolour
[0], fcolour
[1], fcolour
[2]) 
  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
: 
  60                 vout
, remain 
= self
.SetFlow(text
, self
.region
) 
  61                 if self
.draw 
== True and txtdraw 
== True: 
  62                     test_out 
= self
.TestFull(vout
) 
  63                     if self
.align 
== wx
.ALIGN_LEFT
: 
  64                         self
.DC
.DrawText(test_out
, self
.indent
+self
.pcell_left_margin
, y
) 
  66                     elif self
.align 
== wx
.ALIGN_CENTRE
: 
  67                         diff 
= self
.GetCellDiff(test_out
, self
.region
) 
  68                         self
.DC
.DrawText(test_out
, self
.indent
+diff
/2, y
) 
  70                     elif self
.align 
== wx
.ALIGN_RIGHT
: 
  71                         diff 
= self
.GetCellDiff(test_out
, self
.region
) 
  72                         self
.DC
.DrawText(test_out
, self
.indent
+diff
, y
) 
  75                         self
.DC
.DrawText(test_out
, self
.indent
+self
.pcell_left_margin
, y
) 
  78         return y 
- self
.space 
+ self
.pt_space_after
 
  80     def GetCellDiff(self
, text
, width
):      # get the remaining cell size for adjustment 
  81         w
, h 
= self
.DC
.GetTextExtent(text
) 
  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 
  94     def SetFlow(self
, ln_text
, width
): 
  95         width 
= width 
- self
.pcell_right_margin
 
  97         split 
= ln_text
.split() 
 102             w
, h 
= self
.DC
.GetTextExtent(" " + split
[0]) 
 110             bword 
= " " + word  
# blank + word 
 113             w
, h 
= self
.DC
.GetTextExtent(text 
+ bword
) 
 118                 remain 
= ' '.join(split
[cnt
:]) 
 122         remain 
= ' '.join(split
[cnt
:]) 
 126     def SetChar(self
, ln_text
, width
):  # truncate string to fit into width 
 127         width 
= width 
- self
.pcell_right_margin 
- self
.pcell_left_margin
 
 130             w
, h 
= self
.DC
.GetTextExtent(text 
+ val
) 
 133                 return text     
# fitted text value 
 137     def OutTextPageWidth(self
, textout
, y_out
, align
, indent
, txtdraw 
= True): 
 138         textlines 
= textout
.split('\n') 
 141         pagew 
= self
.parent
.page_width 
* self
.pwidth        
# full page width 
 142         w
, h 
= self
.DC
.GetTextExtent(textout
) 
 145         for text 
in textlines
: 
 148                 vout
, remain 
= self
.SetFlow(text
, pagew
) 
 149                 if self
.draw 
== True and txtdraw 
== True: 
 151                     if align 
== wx
.ALIGN_LEFT
: 
 152                         self
.DC
.DrawText(test_out
, indent
, y
) 
 154                     elif align 
== wx
.ALIGN_CENTRE
: 
 155                         diff 
= self
.GetCellDiff(test_out
, pagew
) 
 156                         self
.DC
.DrawText(test_out
, indent
+diff
/2, y
) 
 158                     elif align 
== wx
.ALIGN_RIGHT
: 
 159                         diff 
= self
.GetCellDiff(test_out
, pagew
) 
 160                         self
.DC
.DrawText(test_out
, indent
+diff
, y
) 
 163                         self
.DC
.DrawText(test_out
, indent
, y_out
) 
 169         date
, time 
= self
.GetNow() 
 172     def GetDateTime(self
): 
 173         date
, time 
= self
.GetNow() 
 174         return date 
+ ' ' + time
 
 177         now 
= wx
.DateTime
.Now() 
 178         date 
= now
.FormatDate() 
 179         time 
= now
.FormatTime() 
 182     def SetPreview(self
, preview
): 
 183         self
.preview 
= preview
 
 185     def SetPSize(self
, width
, height
): 
 186         self
.pwidth 
= width
/self
.scale
 
 187         self
.pheight 
= height
/self
.scale
 
 189     def SetScale(self
, scale
): 
 192     def SetPTSize(self
, width
, height
): 
 194         self
.ptheight 
= height
 
 203 class PrintTableDraw(wx
.ScrolledWindow
, PrintBase
): 
 204     def __init__(self
, parent
, DC
, size
): 
 207         self
.scale 
= parent
.scale
 
 209         self
.height 
= size
[1] 
 212     def SetDefaults(self
): 
 214         self
.total_pages 
= None 
 216         self
.page_width 
= self
.parent
.page_width
 
 217         self
.page_height 
= self
.parent
.page_height
 
 219         self
.left_margin 
= self
.parent
.left_margin
 
 220         self
.right_margin 
= self
.parent
.right_margin
 
 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
 
 227         self
.label_colour 
= self
.parent
.label_colour
 
 229         self
.row_line_colour 
= self
.parent
.row_line_colour
 
 230         self
.row_line_size 
= self
.parent
.row_line_size
 
 232         self
.row_def_line_colour 
= self
.parent
.row_def_line_colour
 
 233         self
.row_def_line_size 
= self
.parent
.row_def_line_size
 
 235         self
.column_line_colour 
= self
.parent
.column_line_colour
 
 236         self
.column_line_size 
= self
.parent
.column_line_size
 
 238         self
.column_def_line_size 
= self
.parent
.column_def_line_size
 
 239         self
.column_def_line_colour 
= self
.parent
.column_def_line_colour
 
 241         self
.text_font 
= self
.parent
.text_font
 
 243         self
.label_font 
= self
.parent
.label_font
 
 245     def AdjustValues(self
): 
 246         self
.vertical_offset 
= self
.pheight 
* self
.parent
.vertical_offset
 
 247         self
.horizontal_offset 
= self
.pheight 
* self
.parent
.horizontal_offset
 
 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
 
 254         self
.pheader_margin 
= self
.pheight 
* self
.parent
.header_margin
 
 255         self
.pfooter_margin 
= self
.pheight 
* self
.parent
.footer_margin
 
 257         self
.cell_colour 
= self
.parent
.set_cell_colour
 
 258         self
.cell_text 
= self
.parent
.set_cell_text
 
 261         self
.column_align 
= [] 
 262         self
.column_bgcolour 
= [] 
 263         self
.column_txtcolour 
= [] 
 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
 
 269         pos_x 
= self
.left_margin 
* self
.pwidth 
+ self
.horizontal_offset     
# left margin 
 270         self
.column
.append(pos_x
) 
 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 
 276             rows 
= len(self
.data
) 
 278             self
.data 
= [[str(self
.data
)]] # a non-iterable becomes a single cell 
 280         first_value 
= self
.data
[0] 
 282         if isinstance(first_value
, types
.StringTypes
): # a sequence of strings 
 283             if self
.label 
== [] and self
.set_column 
== []: 
 285                 for x 
in self
.data
:     #becomes one column 
 288                 data 
= [self
.data
]      #becames one row 
 290             first_value 
= data
[0] 
 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 
 297                     data
.append([str(x
)]) 
 300                 data 
= [self
.data
] #becomes one row 
 301                 column_total 
= len(self
.data
) 
 303             first_value 
= data
[0] 
 305         if self
.set_column 
== []: 
 306             table_width 
= self
.page_width 
- self
.left_margin 
- self
.right_margin
 
 311             width 
= table_width
/(len(temp
)) 
 313                 column_width 
= width 
* self
.pwidth
 
 314                 pos_x 
= pos_x 
+ column_width
 
 315                 self
.column
.append(pos_x
)   # position of each column 
 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 
 322         if pos_x 
> self
.page_width 
* self
.pwidth
:    # check if it fits in page 
 323             print "Warning, Too Wide for Page" 
 327             if len(self
.column
) -1 != len(self
.label
): 
 328                 print "Column Settings Incorrect", "\nColumn Value: " + str(self
.column
), "\nLabel Value: " + str(self
.label
) 
 331         if column_total 
!= len(self
.column
) -1: 
 332             print "Cannot fit", first_value
, 'in', len(self
.column
)-1, 'columns.' 
 335         for col 
in range(column_total
): 
 337                 align 
= set_column_align
[col
]       # check if custom column alignment 
 339                 align 
= wx
.ALIGN_LEFT
 
 340             self
.column_align
.append(align
) 
 343                 colour 
= set_column_bgcolour
[col
]     # check if custom column background colour 
 345                 colour 
= self
.parent
.column_colour
 
 346             self
.column_bgcolour
.append(colour
) 
 349                 colour 
= set_column_txtcolour
[col
]     # check if custom column text colour 
 351                 colour 
= self
.GetFontColour(self
.parent
.text_font
) 
 352             self
.column_txtcolour
.append(colour
) 
 355     def SetPointAdjust(self
): 
 356         f 
= wx
.Font(10, wx
.SWISS
, wx
.NORMAL
, wx
.NORMAL
)     # setup using 10 point 
 358         f
.SetFaceName(self
.text_font
["Name"]) 
 359         x
, y 
= self
.DC
.GetTextExtent("W") 
 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 
 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 
 367     def SetPage(self
, page
): 
 370     def SetColumns(self
, col
): 
 375         self
.SetPointAdjust() 
 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
 
 380         self
.SetPrintFont(self
.label_font
) 
 382         x
, y 
= self
.DC
.GetTextExtent("W") 
 385         self
.SetPrintFont(self
.text_font
) 
 387         x
, y 
= self
.DC
.GetTextExtent("W") 
 390         if self
.total_pages 
is None: 
 391             self
.GetTotalPages()    # total pages for display/printing 
 393         self
.data_cnt 
= self
.page_index
[self
.page
-1] 
 400     def GetTotalPages(self
): 
 403         self
.page_index 
= [0] 
 407             test 
= self
.OutPage() 
 408             self
.page_index
.append(self
.data_cnt
) 
 413         self
.total_pages 
= cnt 
+ 1 
 416         self
.y 
= self
.y_start
 
 417         self
.end_x 
= self
.column
[-1] 
 419         if self
.data_cnt 
< len(self
.data
):  # if there data for display on the page 
 420             if self
.label 
!= []:        # check if header defined 
 425         for val 
in self
.data
: 
 427                 row_val 
= self
.data
[self
.data_cnt
] 
 432             max_y 
= self
.PrintRow(row_val
, False)       # test to see if row will fit in remaining space 
 433             test 
= max_y 
+ self
.space
 
 435             if test 
> self
.y_end
: 
 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
 
 443             if self
.y 
> self
.y_end
: 
 446             self
.data_cnt 
= self
.data_cnt 
+ 1 
 450         if self
.data_cnt 
== len(self
.data
):    # last value in list 
 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
 
 460         self
.LabelColorRow(self
.label_colour
) 
 461         self
.SetPrintFont(self
.label_font
) 
 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
] 
 469             self
.align 
= wx
.ALIGN_LEFT
 
 471             max_out 
= self
.OutTextRegion(vtxt
, True) 
 474             self
.col 
= self
.col 
+ 1 
 476         self
.DrawGridLine()     # top line of label 
 477         self
.y 
= max_y 
+ self
.label_space
 
 479     def PrintHeader(self
):      # print the header array 
 480         if self
.draw 
== False: 
 483         for val 
in self
.parent
.header
: 
 484             self
.SetPrintFont(val
["Font"]) 
 486             header_indent 
= val
["Indent"] * self
.pwidth
 
 491                 addtext 
= self
.GetDate() 
 492             elif htype 
== "Date & Time": 
 493                 addtext 
= self
.GetDateTime() 
 497             self
.OutTextPageWidth(text
+addtext
, self
.pheader_margin
, val
["Align"], header_indent
, True) 
 499     def PrintFooter(self
):      # print the header array 
 500         if self
.draw 
== False: 
 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"]) 
 507             footer_indent 
= val
["Indent"] * self
.pwidth
 
 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
) 
 516                 addtext 
= str(self
.page
) 
 517             elif ftype 
== "Date": 
 518                 addtext 
= self
.GetDate() 
 519             elif ftype 
== "Date & Time": 
 520                 addtext 
= self
.GetDateTime() 
 524             self
.OutTextPageWidth(text
+addtext
, footer_pos
, val
["Align"], footer_indent
, True) 
 527     def LabelColorRow(self
, colour
): 
 528         brush 
= wx
.Brush(colour
, wx
.SOLID
) 
 529         self
.DC
.SetBrush(brush
) 
 530         height 
= self
.label_space 
+ self
.label_pt_space_before 
+ self
.label_pt_space_after
 
 531         self
.DC
.DrawRectangle(self
.column
[0], self
.y
, 
 532                               self
.end_x
-self
.column
[0]+1, height
) 
 534     def ColourRowCells(self
, height
): 
 535         if self
.draw 
== False: 
 539         for colour 
in self
.column_bgcolour
: 
 540             cellcolour 
= self
.GetCellColour(self
.data_cnt
, col
) 
 541             if cellcolour 
is not None: 
 544             brush 
= wx
.Brush(colour
, wx
.SOLID
) 
 545             self
.DC
.SetBrush(brush
) 
 546             self
.DC
.SetPen(wx
.Pen(wx
.NamedColour('WHITE'), 0)) 
 548             start_x 
= self
.column
[col
] 
 549             width 
= self
.column
[col
+1] - start_x 
+ 2 
 550             self
.DC
.DrawRectangle(start_x
, self
.y
, width
, height
) 
 553     def PrintRow(self
, row_val
, draw 
= True, align 
= wx
.ALIGN_LEFT
): 
 554         self
.SetPrintFont(self
.text_font
) 
 556         self
.pt_space_before 
= self
.text_pt_space_before   
# set the point spacing 
 557         self
.pt_space_after 
= self
.text_pt_space_after
 
 562             if not isinstance(vtxt
,types
.StringTypes
): 
 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
] 
 568             fcolour 
= self
.column_txtcolour
[self
.col
]       # set font colour 
 569             celltext 
= self
.GetCellTextColour(self
.data_cnt
, self
.col
) 
 570             if celltext 
is not None: 
 571                 fcolour 
= celltext      
# override the column colour 
 573             self
.DC
.SetTextForeground(fcolour
) 
 575             max_out 
= self
.OutTextRegion(vtxt
, draw
) 
 578             self
.col 
= self
.col 
+ 1 
 581     def GetCellColour(self
, row
, col
):      # check if custom colour defined for the cell background 
 583             set = self
.cell_colour
[row
] 
 592     def GetCellTextColour(self
, row
, col
):      # check if custom colour defined for the cell text 
 594             set = self
.cell_text
[row
] 
 603     def FinishDraw(self
): 
 604         self
.DrawGridLine()     # draw last row line 
 605         self
.DrawColumns()      # draw all vertical lines 
 607     def DrawGridLine(self
): 
 608         if self
.draw 
== True \
 
 609         and len(self
.column
) > 2:    #supress grid lines if only one column 
 611                 size 
= self
.row_line_size
[self
.data_cnt
] 
 613                 size 
= self
.row_def_line_size
 
 618                 colour 
= self
.row_line_colour
[self
.data_cnt
] 
 620                 colour 
= self
.row_def_line_colour
 
 622             self
.DC
.SetPen(wx
.Pen(colour
, size
)) 
 625 #            y_out = self.y + self.pt_space_before + self.pt_space_after     # adjust for extra spacing 
 626             self
.DC
.DrawLine(self
.column
[0], y_out
, self
.end_x
, y_out
) 
 628     def DrawColumns(self
): 
 629         if self
.draw 
== True \
 
 630         and len(self
.column
) > 2:   #surpress grid line if only one column 
 632             for val 
in self
.column
: 
 634                     size 
= self
.column_line_size
[col
] 
 636                     size 
= self
.column_def_line_size
 
 638                 if size 
< 1: continue 
 641                     colour 
= self
.column_line_colour
[col
] 
 643                     colour 
= self
.column_def_line_colour
 
 647                 self
.DC
.SetPen(wx
.Pen(colour
, size
)) 
 648                 self
.DC
.DrawLine(indent
, self
.y_start
, indent
, self
.y
) 
 654     def DoDrawing(self
, DC
): 
 662         self
.sizew 
= DC
.MaxY() 
 663         self
.sizeh 
= DC
.MaxX() 
 667     def __init__(self
, parentFrame
=None): 
 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 
= {} 
 684         self
.parentFrame 
= parentFrame
 
 685         self
.SetPreviewSize() 
 687         self
.printData 
= wx
.PrintData() 
 695         self
.SetPrinterOffset() 
 696         self
.SetHeaderValue() 
 697         self
.SetFooterValue() 
 701     def SetPreviewSize(self
, position 
= wx
.Point(0, 0), size
="Full"): 
 703             r 
= wx
.GetClientDisplayRect() 
 704             self
.preview_frame_size 
= r
.GetSize() 
 705             self
.preview_frame_pos 
= r
.GetPosition() 
 707             self
.preview_frame_size 
= size
 
 708             self
.preview_frame_pos 
= position
 
 710     def SetPaperId(self
, paper
): 
 711         self
.printData
.SetPaperId(paper
) 
 713     def SetOrientation(self
, orient
): 
 714         self
.printData
.SetOrientation(orient
) 
 717         self
.row_def_line_colour 
= wx
.NamedColour('BLACK') 
 718         self
.row_def_line_size 
= 1 
 720         self
.column_def_line_colour 
= wx
.NamedColour('BLACK') 
 721         self
.column_def_line_size 
= 1 
 722         self
.column_colour 
= wx
.NamedColour('WHITE') 
 724         self
.label_colour 
= wx
.NamedColour('LIGHT GREY') 
 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] }
 
 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 
 734         self
.text_pt_adj_before 
= 0     # point adjustment before and after the row text 
 735         self
.text_pt_adj_after 
= 0 
 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
 
 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
 
 745     def SetPrinterOffset(self
):        # offset to adjust for printer 
 746         self
.vertical_offset 
= -0.1 
 747         self
.horizontal_offset 
= -0.1 
 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] }
 
 752         self
.header_align 
= wx
.ALIGN_CENTRE
 
 753         self
.header_indent 
= 0 
 754         self
.header_type 
= "Text" 
 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] }
 
 759         self
.footer_align 
= wx
.ALIGN_CENTRE
 
 760         self
.footer_indent 
= 0 
 761         self
.footer_type 
= "Pageof" 
 763     def SetMargins(self
): 
 764         self
.left_margin 
= 0.5 
 765         self
.right_margin 
= 0.5    # only used if no column sizes 
 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 
 772     def SetPortrait(self
): 
 773         self
.printData
.SetPaperId(wx
.PAPER_LETTER
) 
 774         self
.printData
.SetOrientation(wx
.PORTRAIT
) 
 775         self
.page_width 
= 8.5 
 776         self
.page_height 
= 11.0 
 778     def SetLandscape(self
): 
 779         self
.printData
.SetOrientation(wx
.LANDSCAPE
) 
 780         self
.page_width 
= 11.0 
 781         self
.page_height 
= 8.5 
 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] }
 
 795     def SetColAlignment(self
, col
, align
=wx
.ALIGN_LEFT
): 
 796         self
.set_column_align
[col
] = align
 
 798     def SetColBackgroundColour(self
, col
, colour
): 
 799         self
.set_column_bgcolour
[col
] = colour
 
 801     def SetColTextColour(self
, col
, colour
): 
 802         self
.set_column_txtcolour
[col
] = colour
 
 804     def SetCellColour(self
, row
, col
, colour
):      # cell background colour 
 806             set = self
.set_cell_colour
[row
]     # test if row already exists 
 808                 set[col
] = colour       
# test if column already exists 
 810                 set = { col: colour }       
# create the column value 
 812             set = { col: colour }           
# create the column value 
 814         self
.set_cell_colour
[row
] = set    # create dictionary item for colour settings 
 816     def SetCellText(self
, row
, col
, colour
):        # font colour for custom cells 
 818             set = self
.set_cell_text
[row
]     # test if row already exists 
 820                 set[col
] = colour       
# test if column already exists 
 822                 set = { col: colour }       
# create the column value 
 824             set = { col: colour }           
# create the column value 
 826         self
.set_cell_text
[row
] = set    # create dictionary item for colour settings 
 828     def SetColumnLineSize(self
, col
, size
):      # column line size 
 829         self
.column_line_size
[col
] = size    
# create dictionary item for column line settings 
 831     def SetColumnLineColour(self
, col
, colour
): 
 832         self
.column_line_colour
[col
] = colour
 
 834     def SetRowLineSize(self
, row
, size
): 
 835         self
.row_line_size
[row
] = size
 
 837     def SetRowLineColour(self
, row
, colour
): 
 838         self
.row_line_colour
[row
] = colour
 
 840     def GetColour(self
, colour
):        # returns colours based from wxColour value 
 843         green 
= colour
.Green() 
 844         return [red
, green
, blue 
] 
 846     def SetHeader(self
, text 
= "", type = "Text", font
=None, align 
= None, indent 
= None, colour 
= None, size 
= None): 
 847         set = { "Text": text }
 
 850             set["Font"] = copy
.copy(self
.default_font
) 
 854         if colour 
is not None: 
 855             setfont 
= set["Font"] 
 856             setfont
["Colour"] = self
.GetColour(colour
) 
 859             setfont 
= set["Font"] 
 860             setfont
["Size"] = size
 
 863             set["Align"] = self
.header_align
 
 868             set["Indent"] = self
.header_indent
 
 870             set["Indent"] = indent
 
 873             set["Type"] = self
.header_type
 
 877         self
.header
.append(set) 
 879     def SetFooter(self
, text 
= "", type = None, font
=None, align 
= None, indent 
= None, colour 
= None, size 
= None): 
 880         set = { "Text": text }
 
 883             set["Font"] = copy
.copy(self
.default_font
) 
 887         if colour 
is not None: 
 888             setfont 
= set["Font"] 
 889             setfont
["Colour"] = self
.GetColour(colour
) 
 892             setfont 
= set["Font"] 
 893             setfont
["Size"] = size
 
 896             set["Align"] = self
.footer_align
 
 901             set["Indent"] = self
.footer_indent
 
 903             set["Indent"] = indent
 
 906             set["Type"] = self
.footer_type
 
 910         self
.footer
.append(set) 
 913         data 
= wx
.PrintDialogData(self
.printData
) 
 914         printout 
= SetPrintout(self
) 
 915         printout2 
= SetPrintout(self
) 
 916         self
.preview 
= wx
.PrintPreview(printout
, printout2
, data
) 
 917         if not self
.preview
.Ok(): 
 918             wx
.MessageBox("There was a problem printing!", "Printing", wx
.OK
) 
 921         self
.preview
.SetZoom(60)        # initial zoom value 
 922         frame 
= wx
.PreviewFrame(self
.preview
, self
.parentFrame
, "Print preview") 
 926             frame
.SetPosition(self
.preview_frame_pos
) 
 927             frame
.SetSize(self
.preview_frame_size
) 
 931         pdd 
= wx
.PrintDialogData(self
.printData
) 
 932         printer 
= wx
.Printer(pdd
) 
 933         printout 
= SetPrintout(self
) 
 934         if not printer
.Print(self
.parentFrame
, printout
): 
 935             wx
.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx
.OK
) 
 937             self
.printData 
= wx
.PrintData( printer
.GetPrintDialogData().GetPrintData() ) 
 940     def DoDrawing(self
, DC
): 
 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
) 
 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) 
 955             if self
.preview 
== 1: 
 956                 table
.scale 
= self
.scale
 
 957                 table
.SetPSize(size
[0]/self
.page_width
, size
[1]/self
.page_height
) 
 959                 table
.SetPSize(self
.pwidth
, self
.pheight
) 
 961             table
.SetPTSize(self
.ptwidth
, self
.ptheight
) 
 962             table
.SetPreview(self
.preview
) 
 965         self
.page_total 
= table
.total_pages     
# total display pages 
 969         self
.ymax 
= DC
.MaxY() 
 970         self
.xmax 
= DC
.MaxX() 
 975     def GetTotalPages(self
): 
 976         self
.page_total 
= 100 
 977         return self
.page_total
 
 979     def HasPage(self
, page
): 
 980         if page 
<= self
.page_total
: 
 985     def SetPage(self
, page
): 
 988     def SetPageSize(self
, width
, height
): 
 989         self
.pwidth
, self
.pheight 
= width
, height
 
 991     def SetTotalSize(self
, width
, height
): 
 992         self
.ptwidth
, self
.ptheight 
= width
, height
 
 994     def SetPreview(self
, preview
, scale
): 
 995         self
.preview 
= preview
 
 998     def SetTotalSize(self
, width
, height
): 
1000         self
.ptheight 
= height
 
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() 
1009         self
.total_row 
= total_row
 
1010         self
.total_col 
= total_col
 
1014         for row 
in range(total_row
): 
1016             value 
= grid
.GetRowLabelValue(row
) 
1017             row_val
.append(value
) 
1019             for col 
in range(total_col
): 
1020                 value 
= grid
.GetCellValue(row
, col
) 
1021                 row_val
.append(value
) 
1022             data
.append(row_val
) 
1025         for col 
in range(total_col
): 
1026             value 
= grid
.GetColLabelValue(col
) 
1029         self
.table 
= PrintTable(parent
) 
1030         self
.table
.cell_left_margin 
= 0.0 
1031         self
.table
.cell_right_margin 
= 0.0 
1033         self
.table
.label 
= label
 
1034         self
.table
.set_column 
= format
 
1035         self
.table
.data 
= data
 
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
) 
1046                 colour 
= self
.grid
.GetCellBackgroundColour(row
, col
-1) 
1047                 self
.table
.SetCellColour(row
, col
, colour
) 
1050         self
.table
.Preview() 
1056 class SetPrintout(wx
.Printout
): 
1057     def __init__(self
, canvas
): 
1058         wx
.Printout
.__init
__(self
) 
1059         self
.canvas 
= canvas
 
1062     def OnBeginDocument(self
, start
, end
): 
1063         return super(SetPrintout
, self
).OnBeginDocument(start
, end
) 
1065     def OnEndDocument(self
): 
1066         super(SetPrintout
, self
).OnEndDocument() 
1068     def HasPage(self
, page
): 
1070             end 
= self
.canvas
.HasPage(page
) 
1075     def GetPageInfo(self
): 
1077             self
.end_pg 
= self
.canvas
.GetTotalPages() 
1081         end_pg 
= self
.end_pg
 
1083         return (str_pg
, end_pg
, str_pg
, end_pg
) 
1085     def OnPreparePrinting(self
): 
1086         super(SetPrintout
, self
).OnPreparePrinting() 
1088     def OnBeginPrinting(self
): 
1091         self
.preview 
= self
.IsPreview() 
1093             self
.pixelsPerInch 
= self
.GetPPIScreen() 
1095             self
.pixelsPerInch 
= self
.GetPPIPrinter() 
1097         (w
, h
) = dc
.GetSize() 
1098         scaleX 
= float(w
) / 1000 
1099         scaleY 
= float(h
) / 1000 
1100         self
.printUserScale 
= min(scaleX
, scaleY
) 
1102         super(SetPrintout
, self
).OnBeginPrinting() 
1105         self
.psizew
, self
.psizeh 
= self
.GetPPIPrinter() 
1106         return self
.psizew
, self
.psizeh
 
1108     def GetTotalSize(self
): 
1109         self
.ptsizew
, self
.ptsizeh 
= self
.GetPageSizePixels() 
1110         return self
.ptsizew
, self
.ptsizeh
 
1112     def OnPrintPage(self
, page
): 
1114         (w
, h
) = dc
.GetSize() 
1115         scaleX 
= float(w
) / 1000 
1116         scaleY 
= float(h
) / 1000 
1117         self
.printUserScale 
= min(scaleX
, scaleY
) 
1118         dc
.SetUserScale(self
.printUserScale
, self
.printUserScale
) 
1120         self
.preview 
= self
.IsPreview() 
1122         self
.canvas
.SetPreview(self
.preview
, self
.printUserScale
) 
1123         self
.canvas
.SetPage(page
) 
1125         self
.ptsizew
, self
.ptsizeh 
= self
.GetPageSizePixels() 
1126         self
.canvas
.SetTotalSize(self
.ptsizew
, self
.ptsizeh
) 
1128         self
.psizew
, self
.psizeh 
= self
.GetPPIPrinter() 
1129         self
.canvas
.SetPageSize(self
.psizew
, self
.psizeh
) 
1131         self
.canvas
.DoDrawing(dc
) 
1134 if __name__ 
== '__main__': 
1135     app 
= wx
.PySimpleApp() 
1136     frame 
= wx
.Frame(None, -1, "Dummy wx frame for testing printout.py") 
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 ... 
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".', 
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.' 
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')