Printing (Phoenix)

Keywords : Printing, Printout, Preview, Printer, PrintData, PrintDialogData, PageSetupDialogData, PageSetupDialog, PrintPreview, PreviewFrame, Canvas.


Introduction

The Printer framework for wxWindows / wxPython is quite complicated. Because of this, (wx)HtmlEasyPrinting is provided to help simplify basic printing functionality. This Recipe covers a simplified approach to using both (wx)HtmlEasyPrinting and the more complicated (wx)Printout.


What Objects are Involved

The following classes will be used in these recipes:


Demonstrating :

Tested py3.x, wx4.x and Win10.

Printing is an essential element for your programs, here we show you how print.

Do you ready to use some examples ? ;)

Test, modify, correct, improve and share your discoveries ! (!)


Direct printing

img_sample_one.PNG

   1 # sample_one.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import wx
   7 
   8 # class My_Frame
   9 # class My_App
  10 
  11 #-------------------------------------------------------------------------------
  12 
  13 if os.name == "posix":
  14     print("\nPlatform : UNIX - Linux")
  15 elif os.name in ['nt', 'dos', 'ce']:
  16     print("\nPlatform : Windows")
  17 else:
  18     print("\nPlatform : ", platform.system())
  19 
  20 #-------------------------------------------------------------------------------
  21 
  22 class My_Frame(wx.Frame):
  23     """
  24     Create a main frame for my application.
  25     """
  26     def __init__(self, parent, id, title=""):
  27         wx.Frame.__init__(self,
  28                           parent,
  29                           id,
  30                           title,
  31                           size=(600, 350),
  32                           style=wx.DEFAULT_FRAME_STYLE)
  33 
  34         #------------
  35 
  36         # Simplified init method.
  37         self.SetProperties()
  38         self.CreateMenu()
  39         self.CreateCtrls()
  40         self.BindEvents()
  41         self.DoLayout()
  42 
  43         #------------
  44 
  45         self.CenterOnScreen()
  46 
  47     #---------------------------------------------------------------------------
  48 
  49     def SetProperties(self):
  50         """
  51         Set the main frame properties (title, icon...).
  52         """
  53 
  54         self.SetTitle("Printing test...")
  55 
  56 
  57     def CreateMenu(self):
  58         """
  59         Make the frame menus.
  60         """
  61 
  62         menub = wx.MenuBar()
  63 
  64         fmenu = wx.Menu()
  65         fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
  66         fmenu.AppendSeparator()
  67         fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
  68         menub.Append(fmenu, "&File")
  69 
  70         self.SetMenuBar(menub)
  71 
  72 
  73     def CreateCtrls(self):
  74         """
  75         Make widgets for my application.
  76         """
  77 
  78         boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  79         boldFont.SetWeight(wx.BOLD)
  80         boldFont.SetPointSize(10)
  81 
  82         #------------
  83 
  84         # First create the controls.
  85         self.panel = wx.Panel(self,
  86                               id=-1,
  87                               style=wx.BORDER_THEME|
  88                               wx.TAB_TRAVERSAL)
  89 
  90         self.text = wx.StaticText(self.panel,
  91                                   id=-1,
  92                                   label="Demonstrating :")
  93         self.text.SetFont(boldFont)
  94 
  95         self.info = wx.StaticText(self.panel,
  96                                   id=-1,
  97                                   label="> Direct printing.")
  98         self.info.SetForegroundColour("red")
  99 
 100         self.tc = wx.TextCtrl(self.panel,
 101                               id=-1,
 102                               size=(200, -1),
 103                               value="Hello, World ! A sample text.")
 104 
 105         self.btnPrint = wx.Button(self.panel,
 106                                   id=wx.ID_PRINT,
 107                                   label="")
 108         self.btnPrint.SetFocus()
 109 
 110         self.btnClose = wx.Button(self.panel,
 111                                   id=wx.ID_CLOSE,
 112                                   label="E&xit")
 113 
 114 
 115     def BindEvents(self):
 116         """
 117         Bind all the events related to my application.
 118         """
 119 
 120         # Bind some menu events to an events handler.
 121         self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
 122         self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
 123 
 124         # Bind the close event to an event handler.
 125         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 126 
 127         # Bind some buttons events to an events handler.
 128         self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
 129         self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
 130 
 131 
 132     def DoLayout(self):
 133         """
 134         Manage widgets Layout.
 135         """
 136 
 137         # MainSizer is the top-level one that manages everything.
 138         mainSizer = wx.BoxSizer(wx.VERTICAL)
 139 
 140         #------------
 141 
 142         hBox1 = wx.BoxSizer(wx.HORIZONTAL)
 143         hBox1.Add(self.info, 0, wx.ALL, 15)
 144 
 145         #------------
 146 
 147         hBox2 = wx.BoxSizer(wx.HORIZONTAL)
 148         hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
 149         hBox2.Add(self.btnClose, 0, wx.ALL, 10)
 150 
 151         #------------
 152 
 153         mainSizer.Add(self.text, 0, wx.ALL, 10)
 154         mainSizer.Add(wx.StaticLine(self.panel),
 155                       0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
 156         mainSizer.Add(self.tc, 0, wx.ALL, 15)
 157         mainSizer.Add(hBox1, 0, wx.ALL, 5)
 158         mainSizer.Add(hBox2, 0, wx.ALL, 5)
 159 
 160         #------------
 161 
 162         # Finally, tell the panel to use the mainSizer for layout.
 163         self.panel.SetSizer(mainSizer)
 164 
 165 
 166     def OnBtnPrint(self, event):
 167         """
 168         Print the document.
 169         """
 170 
 171         text = self.tc.GetValue()
 172 
 173         #------------
 174 
 175         pd = wx.PrintData()
 176 
 177         pd.SetPrinterName("")
 178         pd.SetOrientation(wx.PORTRAIT)
 179         pd.SetPaperId(wx.PAPER_A4)
 180         pd.SetQuality(wx.PRINT_QUALITY_DRAFT)
 181         # Black and white printing if False.
 182         pd.SetColour(True)
 183         pd.SetNoCopies(1)
 184         pd.SetCollate(True)
 185 
 186         #------------
 187 
 188         pdd = wx.PrintDialogData()
 189 
 190         pdd.SetPrintData(pd)
 191         pdd.SetMinPage(1)
 192         pdd.SetMaxPage(1)
 193         pdd.SetFromPage(1)
 194         pdd.SetToPage(1)
 195         pdd.SetPrintToFile(False)
 196         # pdd.SetSetupDialog(False)
 197         # pdd.EnableSelection(True)
 198         # pdd.EnablePrintToFile(True)
 199         # pdd.EnablePageNumbers(True)
 200         # pdd.SetAllPages(True)
 201 
 202         #------------
 203 
 204         dlg = wx.PrintDialog(self, pdd)
 205 
 206         if dlg.ShowModal() == wx.ID_OK:
 207             dc = dlg.GetPrintDC()
 208 
 209             dc.StartDoc("My document title")
 210             dc.StartPage()
 211 
 212             # (wx.MM_METRIC) ---> Each logical unit is 1 mm.
 213             # (wx.MM_POINTS) ---> Each logical unit is a "printer point" i.e.
 214             dc.SetMapMode(wx.MM_POINTS)
 215 
 216             dc.SetTextForeground("red")
 217             dc.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.BOLD))
 218             dc.DrawText(text, 50, 100)
 219 
 220             dc.EndPage()
 221             dc.EndDoc()
 222             del dc
 223 
 224         else :
 225             dlg.Destroy()
 226 
 227 
 228     def OnBtnClose(self, event):
 229         """
 230         ...
 231         """
 232 
 233         self.Close(True)
 234 
 235 
 236     def OnCloseWindow(self, event):
 237         """
 238         ...
 239         """
 240 
 241         self.Destroy()
 242 
 243 #-------------------------------------------------------------------------------
 244 
 245 class My_App(wx.App):
 246     """
 247     ...
 248     """
 249     def OnInit(self):
 250 
 251         #------------
 252 
 253         frame = My_Frame(None, id=-1)
 254         self.SetTopWindow(frame)
 255         frame.Show(True)
 256 
 257         return True
 258 
 259 #-------------------------------------------------------------------------------
 260 
 261 def main():
 262     app = My_App(False)
 263     app.MainLoop()
 264 
 265 #-------------------------------------------------------------------------------
 266 
 267 if __name__ == "__main__" :
 268     main()


Printout class

img_sample_two.PNG

   1 # sample_two.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import wx
   7 
   8 # class My_Printout
   9 # class My_Frame
  10 # class My_App
  11 
  12 #-------------------------------------------------------------------------------
  13 
  14 if os.name == "posix":
  15     print("\nPlatform : UNIX - Linux")
  16 elif os.name in ['nt', 'dos', 'ce']:
  17     print("\nPlatform : Windows")
  18 else:
  19     print("\nPlatform : ", platform.system())
  20 
  21 #-------------------------------------------------------------------------------
  22 
  23 class My_Printout(wx.Printout):
  24     """
  25     Create a printout.
  26     """
  27     def __init__(self, text, title):
  28         wx.Printout.__init__(self, title)
  29 
  30         #------------
  31 
  32         self.lines = text
  33 
  34     #---------------------------------------------------------------------------
  35 
  36     def OnBeginDocument(self, start, end):
  37         """
  38         ...
  39         """
  40 
  41         return super(My_Printout, self).OnBeginDocument(start, end)
  42 
  43 
  44     def OnEndDocument(self):
  45         """
  46         ...
  47         """
  48 
  49         super(My_Printout, self).OnEndDocument()
  50 
  51 
  52     def OnBeginPrinting(self):
  53         """
  54         ...
  55         """
  56 
  57         super(My_Printout, self).OnBeginPrinting()
  58 
  59 
  60     def OnEndPrinting(self):
  61         """
  62         ...
  63         """
  64 
  65         super(My_Printout, self).OnEndPrinting()
  66 
  67 
  68     def OnPreparePrinting(self):
  69         """
  70         ...
  71         """
  72 
  73         super(My_Printout, self).OnPreparePrinting()
  74 
  75 
  76     def HasPage(self, page):
  77         """
  78         ...
  79         """
  80 
  81         if page <= 2:
  82             return True
  83         else:
  84             return False
  85 
  86 
  87     def GetPageInfo(self):
  88         """
  89         ...
  90         """
  91 
  92         return (1, 2, 1, 2)
  93 
  94 
  95     def OnPrintPage(self, page):
  96         """
  97         ...
  98         """
  99 
 100         dc = self.GetDC()
 101 
 102         # (wx.MM_METRIC) ---> Each logical unit is 1 mm.
 103         # (wx.MM_POINTS) ---> Each logical unit is a "printer point" i.e.
 104         dc.SetMapMode(wx.MM_POINTS)
 105 
 106         dc.SetTextForeground("red")
 107         dc.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.BOLD))
 108         dc.DrawText(self.lines, 50, 100)
 109 
 110         # R, V, B.
 111         dc.SetPen(wx.Pen(wx.Colour(255, 20, 5)))
 112         dc.SetBrush(wx.Brush(wx.Colour(30, 255, 20)))
 113         # x, y, radius.
 114         dc.DrawCircle(100, 275, 25)
 115         # x, y, width, height.
 116         dc.DrawEllipse(100, 275, 75, 50)
 117 
 118         return True
 119 
 120 #-------------------------------------------------------------------------------
 121 
 122 class My_Frame(wx.Frame):
 123     """
 124     Create a main frame for my application.
 125     """
 126     def __init__(self, parent, id, title=""):
 127         wx.Frame.__init__(self,
 128                           parent,
 129                           id,
 130                           title,
 131                           size=(600, 350),
 132                           style=wx.DEFAULT_FRAME_STYLE)
 133 
 134         #------------
 135 
 136         # Simplified init method.
 137         self.SetProperties()
 138         self.CreateMenu()
 139         self.CreateCtrls()
 140         self.CreatePrintData()
 141         self.BindEvents()
 142         self.DoLayout()
 143 
 144         #------------
 145 
 146         self.CenterOnScreen()
 147 
 148     #---------------------------------------------------------------------------
 149 
 150     def SetProperties(self):
 151         """
 152         Set the main frame properties (title, icon...).
 153         """
 154 
 155         self.SetTitle("Printing test...")
 156 
 157 
 158     def CreateMenu(self):
 159         """
 160         Make the frame menus.
 161         """
 162 
 163         menub = wx.MenuBar()
 164 
 165         fmenu = wx.Menu()
 166         fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
 167         fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
 168         fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
 169         fmenu.AppendSeparator()
 170         fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
 171         menub.Append(fmenu, "&File")
 172 
 173         self.SetMenuBar(menub)
 174 
 175 
 176     def CreateCtrls(self):
 177         """
 178         Make widgets for my app.
 179         """
 180 
 181         font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
 182         font.SetWeight(wx.BOLD)
 183         font.SetPointSize(10)
 184 
 185         #------------
 186 
 187         # First create the controls.
 188         self.panel = wx.Panel(self,
 189                               id=-1,
 190                               style=wx.BORDER_THEME|
 191                               wx.TAB_TRAVERSAL)
 192 
 193         self.text = wx.StaticText(self.panel,
 194                                   id=-1,
 195                                   label="Demonstrating :")
 196         self.text.SetFont(font)
 197 
 198         self.info = wx.StaticText(self.panel,
 199                                   id=-1,
 200                                   label="1) Direct printing,\n"
 201                                         "2) Printout class,\n"
 202                                         "3) Preview,\n"
 203                                         "4) Menu,\n"
 204                                         "5) Page setup.")
 205         self.info.SetForegroundColour("red")
 206         font.SetWeight(wx.NORMAL)
 207         self.info.SetFont(font)
 208 
 209         self.tc = wx.TextCtrl(self.panel,
 210                               id=-1,
 211                               size=(200, -1),
 212                               value="Hello, World ! A sample text.")
 213 
 214         self.btnSetup = wx.Button(self.panel,
 215                                   id=wx.ID_PAGE_SETUP,
 216                                   label="Page set&up")
 217 
 218         self.btnPreview = wx.Button(self.panel,
 219                                     id=wx.ID_PREVIEW,
 220                                     label="Print pre&view")
 221         self.btnPreview.SetFocus()
 222 
 223         self.btnPrint = wx.Button(self.panel,
 224                                   id=wx.ID_PRINT,
 225                                   label="&Print")
 226 
 227         self.btnClose = wx.Button(self.panel,
 228                                   id=wx.ID_CLOSE,
 229                                   label="E&xit")
 230 
 231 
 232     def CreatePrintData(self):
 233         """
 234         Create printing data.
 235         """
 236 
 237         self.printdata = wx.PrintData()
 238 
 239         self.printdata.SetPrinterName('')
 240         self.printdata.SetOrientation(wx.PORTRAIT)
 241         self.printdata.SetPaperId(wx.PAPER_A4)
 242         self.printdata.SetQuality(wx.PRINT_QUALITY_DRAFT)
 243         # Black and white printing if False.
 244         self.printdata.SetColour(True)
 245         self.printdata.SetNoCopies(1)
 246         self.printdata.SetCollate(True)
 247         # self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
 248 
 249 
 250     def BindEvents(self):
 251         """
 252         Bind all the events related to my application.
 253         """
 254 
 255         # Bind some menu events to an events handler.
 256         self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
 257         self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
 258         self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
 259         self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
 260 
 261         # Bind the close event to an event handler.
 262         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 263 
 264         # Bind some buttons events to an events handler.
 265         self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
 266         self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
 267         self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
 268         self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
 269 
 270 
 271     def DoLayout(self):
 272         """
 273         Manage widgets Layout.
 274         """
 275 
 276         # MainSizer is the top-level one that manages everything.
 277         mainSizer = wx.BoxSizer(wx.VERTICAL)
 278 
 279         #------------
 280 
 281         hBox1 = wx.BoxSizer(wx.HORIZONTAL)
 282         hBox1.Add(self.info, 0, wx.ALL, 15)
 283 
 284         #------------
 285 
 286         hBox2 = wx.BoxSizer(wx.HORIZONTAL)
 287         hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
 288         hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
 289         hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
 290         hBox2.Add(self.btnClose, 0, wx.ALL, 10)
 291 
 292         #------------
 293 
 294         mainSizer.Add(self.text, 0, wx.ALL, 10)
 295         mainSizer.Add(wx.StaticLine(self.panel),
 296                       0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
 297         mainSizer.Add(self.tc, 0, wx.ALL, 15)
 298         mainSizer.Add(hBox1, 0, wx.ALL, 5)
 299         mainSizer.Add(hBox2, 0, wx.ALL, 5)
 300 
 301         #------------
 302 
 303         # Finally, tell the panel to use the mainSizer for layout.
 304         self.panel.SetSizer(mainSizer)
 305 
 306 
 307     def OnBtnPageSetup(self, event):
 308         """
 309         Show the PrinterSetup dialog.
 310         """
 311 
 312         psdd = wx.PageSetupDialogData(self.printdata)
 313 
 314         psdd.EnablePrinter(True)
 315         # psdd.CalculatePaperSizeFromId()
 316 
 317         #------------
 318 
 319         dlg = wx.PageSetupDialog(self, psdd)
 320         dlg.ShowModal()
 321 
 322         #------------
 323 
 324         # This makes a copy of the wx.PrintData instead of just saving
 325         # a reference to the one inside the PrintDialogData that will
 326         # be destroyed when the dialog is destroyed
 327         self.printdata = wx.PrintData(dlg.GetPageSetupData().GetPrintData())
 328 
 329         dlg.Destroy()
 330 
 331 
 332     def OnBtnPreview(self, event):
 333         """
 334         Show the print preview.
 335         """
 336 
 337         text = self.tc.GetValue()
 338 
 339         #------------
 340 
 341         data = wx.PrintDialogData(self.printdata)
 342 
 343         printout1 = My_Printout(text, "- My printing object")
 344         printout2 = My_Printout(text, "- My printing object")
 345 
 346         printPreview = wx.PrintPreview(printout1, printout2, data)
 347 
 348         # Initial zoom value.
 349         if "__WXMAC__" in wx.PlatformInfo:
 350             printPreview.SetZoom(50)
 351         else:
 352             printPreview.SetZoom(35)
 353 
 354         if not printPreview.IsOk():
 355             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 356                            "your current printer is \nnot "\
 357                            "set correctly ?"),
 358                           ("Printing"),
 359                           wx.OK)
 360             return
 361 
 362         else:
 363             previewFrame = wx.PreviewFrame(printPreview, None, "Print preview")
 364             previewFrame.Initialize()
 365             previewFrame.SetPosition(self.GetPosition())
 366             previewFrame.SetSize(self.GetSize())
 367             # Or full screen :
 368             # previewFrame.Maximize()
 369             previewFrame.Show(True)
 370             previewFrame.Layout()
 371 
 372 
 373     def OnBtnPrint(self, event):
 374         """
 375         Prints the document.
 376         """
 377 
 378         text = self.tc.GetValue()
 379 
 380         #------------
 381 
 382         pdd = wx.PrintDialogData(self.printdata)
 383         pdd.SetPrintData(self.printdata)
 384         pdd.SetMinPage(1)
 385         pdd.SetMaxPage(1)
 386         pdd.SetFromPage(1)
 387         pdd.SetToPage(1)
 388         pdd.SetPrintToFile(False)
 389         # pdd.SetSetupDialog(False)
 390         # pdd.EnableSelection(True)
 391         # pdd.EnablePrintToFile(True)
 392         # pdd.EnablePageNumbers(True)
 393         # pdd.SetAllPages(True)
 394 
 395         #------------
 396 
 397         printer = wx.Printer(pdd)
 398 
 399         myPrintout = My_Printout(text, "- My printing object")
 400 
 401         if not printer.Print(self, myPrintout, True):
 402             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 403                            "your current printer is \nnot "\
 404                            "set correctly ?"),
 405                           ("Printing"),
 406                           wx.OK)
 407             return
 408 
 409         else:
 410             self.printData = wx.PrintData(printer.GetPrintDialogData().GetPrintData())
 411         myPrintout.Destroy()
 412 
 413 
 414     def OnBtnClose(self, event):
 415         """
 416         ...
 417         """
 418 
 419         self.Close(True)
 420 
 421 
 422     def OnCloseWindow(self, event):
 423         """
 424         ...
 425         """
 426 
 427         self.Destroy()
 428 
 429 #-------------------------------------------------------------------------------
 430 
 431 class My_App(wx.App):
 432     """
 433     ...
 434     """
 435     def OnInit(self):
 436 
 437         #------------
 438 
 439         self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
 440 
 441         #------------
 442 
 443         frame = My_Frame(None, id=-1)
 444         self.SetTopWindow(frame)
 445         frame.Show(True)
 446 
 447         return True
 448 
 449 
 450 #-------------------------------------------------------------------------------
 451 
 452 def main():
 453     app = My_App(False)
 454     app.MainLoop()
 455 
 456 #-------------------------------------------------------------------------------
 457 
 458 if __name__ == "__main__" :
 459     main()


Canvas and printout class

img_sample_three.PNG

   1 # sample_three.py
   2 
   3 import sys
   4 import os
   5 import platform
   6 import time
   7 import wx
   8 
   9 # class My_Canvas
  10 # class My_Printout
  11 # class My_Frame
  12 # class My_App
  13 
  14 # There are two different approaches to drawing, buffered or direct.
  15 # This sample shows both approaches so you can easily compare and
  16 # contrast the two by changing this value :
  17 BUFFERED = 1
  18 
  19 #-------------------------------------------------------------------------------
  20 
  21 if os.name == "posix":
  22     print("\nPlatform : UNIX - Linux")
  23 elif os.name in ['nt', 'dos', 'ce']:
  24     print("\nPlatform : Windows")
  25 else:
  26     print("\nPlatform : ", platform.system())
  27 
  28 #-------------------------------------------------------------------------------
  29 
  30 class My_Canvas(wx.ScrolledWindow):
  31     """
  32     ...
  33     """
  34     def __init__(self, parent, id=-1, size=wx.DefaultSize):
  35         wx.ScrolledWindow.__init__(self,
  36                                    parent,
  37                                    id,
  38                                    pos=(0, 0),
  39                                    size=size,
  40                                    style=wx.SUNKEN_BORDER)
  41 
  42         #------------
  43 
  44         self.maxWidth  = 1000
  45         self.maxHeight = 1000
  46         self.x = self.y = 0
  47         self.drawing = False
  48 
  49         #------------
  50 
  51         self.SetVirtualSize((self.maxWidth, self.maxHeight))
  52         self.SetScrollRate(30, 30)
  53 
  54         #------------
  55 
  56         if BUFFERED:
  57             # Initialize the buffer bitmap.  No real DC is needed at this point
  58             self.buffer = wx.Bitmap(self.maxWidth, self.maxHeight)
  59             dc = wx.BufferedDC(None, self.buffer)
  60             dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
  61             dc.Clear()
  62             self.DoDrawing(dc)
  63 
  64         #------------
  65 
  66         # Bind a paint event to an events handler
  67         self.Bind(wx.EVT_PAINT, self.OnPaint)
  68 
  69     #---------------------------------------------------------------------------
  70 
  71     def GetWidth(self):
  72         """
  73         ...
  74         """
  75 
  76         return self.maxWidth
  77 
  78 
  79     def GetHeight(self):
  80         """
  81         ...
  82         """
  83 
  84         return self.maxHeight
  85 
  86 
  87     def OnPaint(self, event):
  88         """
  89         ...
  90         """
  91 
  92         if BUFFERED:
  93             # Create a buffered paint DC.  It will create the real
  94             # wx.PaintDC and then blit the bitmap to it when dc is
  95             # deleted.  Since we don't need to draw anything else
  96             # here that's all there is to it.
  97             dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)
  98         else:
  99             dc = wx.PaintDC(self)
 100             self.PrepareDC(dc)
 101             # Since we're not buffering in this case, we have to
 102             # (re)paint the all the contents of the window, which can
 103             # be potentially time consuming and flickery depending on
 104             # what is being drawn and how much of it there is.
 105             self.DoDrawing(dc)
 106 
 107 
 108     def DoDrawing(self, dc, printing=False):
 109         """
 110         ...
 111         """
 112 
 113         # Draw.
 114         pen = wx.Pen("BLACK", 4, wx.SOLID)
 115 
 116         dc.SetPen(wx.TRANSPARENT_PEN)
 117         dc.SetBrush(wx.Brush("#e0f0f0"))
 118 
 119         for i in range(56, 784, 56):
 120             dc.DrawRectangle(0,  i, 794, 28)
 121 
 122         pen.SetCap(wx.CAP_BUTT)
 123         dc.SetPen(pen)
 124         dc.DrawLine(397, 56, 397, 756)
 125 
 126         pen.SetCap(wx.CAP_BUTT)
 127         dc.SetPen(pen)
 128         dc.DrawLine(0, 756, 794, 756)
 129 
 130         pen.SetCap(wx.CAP_BUTT)
 131         dc.SetPen(pen)
 132         dc.DrawLine(0, 56, 794, 56)
 133 
 134         dc.SetTextForeground("BLACK")
 135         dc.SetFont(wx.Font(24, wx.DEFAULT, wx.NORMAL, wx.BOLD))
 136         dc.DrawText("Python", 15, 8)
 137 
 138         pen.SetJoin(wx.JOIN_MITER)
 139         dc.SetPen(pen)
 140         dc.SetBrush(wx.TRANSPARENT_BRUSH)
 141         dc.DrawRectangle(0, 0, 794, 794)
 142 
 143         dc.SetPen(wx.Pen("RED", 1))
 144         dc.DrawRectangle(0, 0, 1000, 1000)
 145 
 146 #-------------------------------------------------------------------------------
 147 
 148 class My_Printout(wx.Printout):
 149     """
 150     Create a printout.
 151     """
 152     def __init__(self, canvas, text, title):
 153         wx.Printout.__init__(self, title)
 154 
 155         #------------
 156 
 157         self.canvas = canvas
 158         self.lines = text
 159 
 160     #---------------------------------------------------------------------------
 161 
 162     def OnBeginDocument(self, start, end):
 163         """
 164         ...
 165         """
 166 
 167         return super(My_Printout, self).OnBeginDocument(start, end)
 168 
 169 
 170     def OnEndDocument(self):
 171         """
 172         ...
 173         """
 174 
 175         super(My_Printout, self).OnEndDocument()
 176 
 177 
 178     def OnBeginPrinting(self):
 179         """
 180         ...
 181         """
 182 
 183         super(My_Printout, self).OnBeginPrinting()
 184 
 185 
 186     def OnEndPrinting(self):
 187         """
 188         ...
 189         """
 190 
 191         super(My_Printout, self).OnEndPrinting()
 192 
 193 
 194     def OnPreparePrinting(self):
 195         """
 196         ...
 197         """
 198 
 199         super(My_Printout, self).OnPreparePrinting()
 200 
 201 
 202     def HasPage(self, page):
 203         """
 204         ...
 205         """
 206 
 207         if page <= 2:
 208             return True
 209         else:
 210             return False
 211 
 212 
 213     def GetPageInfo(self):
 214         """
 215         ...
 216         """
 217 
 218         return (1, 2, 1, 2)
 219 
 220 
 221     def OnPrintPage(self, page):
 222         """
 223         ...
 224         """
 225 
 226         dc = self.GetDC()
 227 
 228         # (wx.MM_METRIC) ---> Each logical unit is 1 mm.
 229         # (wx.MM_POINTS) ---> Each logical unit is a "printer point" i.e.
 230         # dc.SetMapMode(wx.MM_POINTS)
 231 
 232         #------------
 233 
 234         # One possible method of setting scaling factors...
 235         maxX = self.canvas.GetWidth()
 236         maxY = self.canvas.GetHeight()
 237 
 238         #------------
 239 
 240         # Let's have at least 50 device units margin.
 241         marginX = 180
 242         marginY = 180
 243 
 244         #------------
 245 
 246         # Add the margin to the graphic size.
 247         maxX = maxX + (2 * marginX)
 248         maxY = maxY + (2 * marginY)
 249 
 250         #------------
 251 
 252         # Get the size of the DC in pixels.
 253         # (w, h) = dc.GetSizeTuple()
 254         (w, h) = dc.GetSize()
 255 
 256         # Calculate a suitable scaling factor.
 257         scaleX = float(w) / maxX
 258         scaleY = float(h) / maxY
 259 
 260         # Use x or y scaling factor, whichever fits on the DC.
 261         actualScale = min(scaleX, scaleY)
 262 
 263         # Calculate the position on the DC for centering the graphic.
 264         posX = (w - (self.canvas.GetWidth() * actualScale)) / 2.0
 265         posY = (h - (self.canvas.GetHeight() * actualScale)) / 2.0
 266 
 267         # Set the scale and origin.
 268         dc.SetUserScale(actualScale, actualScale)
 269         dc.SetDeviceOrigin(int(posX), int(posY))
 270 
 271         #------------
 272 
 273         self.canvas.DoDrawing(dc, True)
 274 
 275         #------------
 276 
 277         # Draw.
 278         dc.SetTextForeground("RED")
 279         dc.SetFont(wx.Font(17, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
 280         dc.DrawText(self.lines, 6, 57)
 281         dc.DrawText(self.lines, 6, 85)
 282         dc.DrawText(self.lines, 6, 113)
 283         dc.DrawText(self.lines, 6, 141)
 284         dc.DrawText(self.lines, 6, 169)
 285         dc.DrawText(self.lines, 6, 197)
 286 
 287         dc.SetTextForeground("GRAY")
 288         dc.SetFont(wx.Font(32, wx.DEFAULT, wx.NORMAL, wx.BOLD))
 289         dc.DrawText(("wxPython sample :"), 0, -150)
 290 
 291         dc.SetTextForeground("BLACK")
 292         dc.SetFont(wx.Font(18, wx.DEFAULT, wx.NORMAL, wx.BOLD))
 293         dc.DrawText(("Page : %d") % page, marginX/2, maxY-marginY)
 294 
 295         tm = time.strftime(("Printing %a, %d %b %Y - %Hh%M"))
 296 
 297         dc.SetTextForeground("GRAY")
 298         dc.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
 299         dc.DrawText(tm, 10, 764)
 300 
 301         return True
 302 
 303 #-------------------------------------------------------------------------------
 304 
 305 class My_Frame(wx.Frame):
 306     """
 307     Create a main frame for my application.
 308     """
 309     def __init__(self, parent, id, title=""):
 310         wx.Frame.__init__(self,
 311                           parent,
 312                           id,
 313                           title,
 314                           size=(600, 367),
 315                           style=wx.DEFAULT_FRAME_STYLE)
 316 
 317         #------------
 318 
 319         # Simplified init method.
 320         self.SetProperties()
 321         self.CreateMenu()
 322         self.CreateCtrls()
 323         self.CreatePrintData()
 324         self.BindEvents()
 325         self.DoLayout()
 326 
 327         #------------
 328 
 329         self.CenterOnScreen()
 330 
 331     #---------------------------------------------------------------------------
 332 
 333     def SetProperties(self):
 334         """
 335         Set the main frame properties (title, icon...).
 336         """
 337 
 338         self.SetTitle("Printing test...")
 339 
 340 
 341     def CreateMenu(self):
 342         """
 343         Make the frame menus.
 344         """
 345 
 346         menub = wx.MenuBar()
 347 
 348         fmenu = wx.Menu()
 349         fmenu.Append(wx.ID_PAGE_SETUP, "Page set&up\tCtrl+U")
 350         fmenu.Append(wx.ID_PREVIEW, "Print pre&view\tCtrl+V")
 351         fmenu.Append(wx.ID_PRINT, "&Print\tCtrl+P")
 352         fmenu.AppendSeparator()
 353         fmenu.Append(wx.ID_EXIT, "E&xit\tCtrl+X")
 354         menub.Append(fmenu, "&File")
 355 
 356         self.SetMenuBar(menub)
 357 
 358 
 359     def CreateCtrls(self):
 360         """
 361         Make widgets for my app.
 362         """
 363 
 364         font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
 365         font.SetWeight(wx.BOLD)
 366         font.SetPointSize(10)
 367 
 368         #------------
 369 
 370         # First create the controls.
 371         self.panel = wx.Panel(self,
 372                               id=-1,
 373                               style=wx.BORDER_THEME|
 374                               wx.TAB_TRAVERSAL)
 375 
 376         self.text = wx.StaticText(self.panel,
 377                                   id=-1,
 378                                   label="Demonstrating :")
 379         self.text.SetFont(font)
 380 
 381         self.info = wx.StaticText(self.panel,
 382                                   id=-1,
 383                                   label="1) Direct printing,\n"
 384                                         "2) Printout class,\n"
 385                                         "3) Canvas class,\n"
 386                                         "4) Preview,\n"
 387                                         "5) Menu,\n"
 388                                         "6) Page setup.")
 389         self.info.SetForegroundColour("red")
 390         font.SetWeight(wx.NORMAL)
 391         self.info.SetFont(font)
 392 
 393         self.tc = wx.TextCtrl(self.panel,
 394                               id=-1,
 395                               size=(200, -1),
 396                               value="Hello, World ! A sample text.")
 397 
 398         self.canvas = My_Canvas(self.panel, size=(0, 0))
 399 
 400         self.btnSetup = wx.Button(self.panel,
 401                                   id=wx.ID_PAGE_SETUP,
 402                                   label="Page set&up")
 403 
 404         self.btnPreview = wx.Button(self.panel,
 405                                     id=wx.ID_PREVIEW,
 406                                     label="Print pre&view")
 407         self.btnPreview.SetFocus()
 408 
 409         self.btnPrint = wx.Button(self.panel,
 410                                   id=wx.ID_PRINT,
 411                                   label="&Print")
 412 
 413         self.btnClose = wx.Button(self.panel,
 414                                   id=wx.ID_CLOSE,
 415                                   label="E&xit")
 416 
 417 
 418     def CreatePrintData(self):
 419         """
 420         Create printing data.
 421         """
 422 
 423         self.printdata = wx.PrintData()
 424 
 425         self.printdata.SetPrinterName('')
 426         self.printdata.SetOrientation(wx.PORTRAIT)
 427         self.printdata.SetPaperId(wx.PAPER_A4)
 428         self.printdata.SetQuality(wx.PRINT_QUALITY_DRAFT)
 429         # Black and white printing if False.
 430         self.printdata.SetColour(True)
 431         self.printdata.SetNoCopies(1)
 432         self.printdata.SetCollate(True)
 433         # self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
 434 
 435 
 436     def BindEvents(self):
 437         """
 438         Bind all the events related to my application.
 439         """
 440 
 441         # Bind some menu events to an events handler.
 442         self.Bind(wx.EVT_MENU, self.OnBtnPageSetup, id=wx.ID_PAGE_SETUP)
 443         self.Bind(wx.EVT_MENU, self.OnBtnPreview, id=wx.ID_PREVIEW)
 444         self.Bind(wx.EVT_MENU, self.OnBtnPrint, id=wx.ID_PRINT)
 445         self.Bind(wx.EVT_MENU, self.OnBtnClose, id=wx.ID_EXIT)
 446 
 447         # Bind the close event to an event handler.
 448         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 449 
 450         # Bind some buttons events to an events handler.
 451         self.Bind(wx.EVT_BUTTON, self.OnBtnPageSetup, self.btnSetup)
 452         self.Bind(wx.EVT_BUTTON, self.OnBtnPreview, self.btnPreview)
 453         self.Bind(wx.EVT_BUTTON, self.OnBtnPrint, self.btnPrint)
 454         self.Bind(wx.EVT_BUTTON, self.OnBtnClose, self.btnClose)
 455 
 456 
 457     def DoLayout(self):
 458         """
 459         Manage widgets Layout.
 460         """
 461 
 462         # MainSizer is the top-level one that manages everything.
 463         mainSizer = wx.BoxSizer(wx.VERTICAL)
 464 
 465         #------------
 466 
 467         hBox1 = wx.BoxSizer(wx.HORIZONTAL)
 468         hBox1.Add(self.info, 0, wx.ALL, 15)
 469 
 470         #------------
 471 
 472         hBox2 = wx.BoxSizer(wx.HORIZONTAL)
 473         hBox2.Add(self.btnSetup, 0, wx.ALL, 10)
 474         hBox2.Add(self.btnPreview, 0, wx.ALL, 10)
 475         hBox2.Add(self.btnPrint, 0, wx.ALL, 10)
 476         hBox2.Add(self.btnClose, 0, wx.ALL, 10)
 477 
 478         #------------
 479 
 480         mainSizer.Add(self.text, 0, wx.ALL, 10)
 481         mainSizer.Add(wx.StaticLine(self.panel),
 482                       0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
 483         mainSizer.Add(self.tc, 0, wx.ALL, 15)
 484         mainSizer.Add(hBox1, 0, wx.ALL, 5)
 485         mainSizer.Add(hBox2, 0, wx.ALL, 5)
 486 
 487         #------------
 488 
 489         # Finally, tell the panel to use the mainSizer for layout.
 490         self.panel.SetSizer(mainSizer)
 491 
 492 
 493     def OnBtnPageSetup(self, event):
 494         """
 495         Show the PrinterSetup dialog.
 496         """
 497 
 498         psdd = wx.PageSetupDialogData(self.printdata)
 499 
 500         psdd.EnablePrinter(True)
 501         # psdd.CalculatePaperSizeFromId()
 502 
 503         #------------
 504 
 505         dlg = wx.PageSetupDialog(self, psdd)
 506         dlg.ShowModal()
 507 
 508         #------------
 509 
 510         # This makes a copy of the wx.PrintData instead of just saving
 511         # a reference to the one inside the PrintDialogData that will
 512         # be destroyed when the dialog is destroyed
 513         self.printdata = wx.PrintData(dlg.GetPageSetupData().GetPrintData())
 514 
 515         dlg.Destroy()
 516 
 517 
 518     def OnBtnPreview(self, event):
 519         """
 520         Show the print preview.
 521         """
 522 
 523         text = self.tc.GetValue()
 524 
 525         #------------
 526 
 527         data = wx.PrintDialogData(self.printdata)
 528 
 529         printout1 = My_Printout(self.canvas, text, "- My printing object")
 530         printout2 = My_Printout(self.canvas, text, "- My printing object")
 531 
 532         printPreview = wx.PrintPreview(printout1, printout2, data)
 533 
 534         # Initial zoom value.
 535         if "__WXMAC__" in wx.PlatformInfo:
 536             printPreview.SetZoom(50)
 537         else:
 538             printPreview.SetZoom(35)
 539 
 540         if not printPreview.IsOk():
 541             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 542                            "your current printer is \nnot "\
 543                            "set correctly ?"),
 544                           ("Printing"),
 545                           wx.OK)
 546             return
 547 
 548         else:
 549             previewFrame = wx.PreviewFrame(printPreview, None, "Print preview")
 550             previewFrame.Initialize()
 551             previewFrame.SetPosition(self.GetPosition())
 552             previewFrame.SetSize(self.GetSize())
 553             # Or full screen :
 554             # previewFrame.Maximize()
 555             previewFrame.Show(True)
 556             previewFrame.Layout()
 557 
 558 
 559     def OnBtnPrint(self, event):
 560         """
 561         Prints the document.
 562         """
 563 
 564         text = self.tc.GetValue()
 565 
 566         #------------
 567 
 568         pdd = wx.PrintDialogData(self.printdata)
 569         pdd.SetPrintData(self.printdata)
 570         pdd.SetMinPage(1)
 571         pdd.SetMaxPage(1)
 572         pdd.SetFromPage(1)
 573         pdd.SetToPage(1)
 574         pdd.SetPrintToFile(False)
 575         # pdd.SetSetupDialog(False)
 576         # pdd.EnableSelection(True)
 577         # pdd.EnablePrintToFile(True)
 578         # pdd.EnablePageNumbers(True)
 579         # pdd.SetAllPages(True)
 580 
 581         #------------
 582 
 583         printer = wx.Printer(pdd)
 584 
 585         myPrintout = My_Printout(self.canvas, text, "- My printing object")
 586 
 587         if not printer.Print(self, myPrintout, True):
 588             wx.MessageBox(("There was a problem printing.\nPerhaps "\
 589                            "your current printer is \nnot "\
 590                            "set correctly ?"),
 591                           ("Printing"),
 592                           wx.OK)
 593             return
 594 
 595         else:
 596             self.printData = wx.PrintData(printer.GetPrintDialogData().GetPrintData())
 597         myPrintout.Destroy()
 598 
 599 
 600     def OnBtnClose(self, event):
 601         """
 602         ...
 603         """
 604 
 605         self.Close(True)
 606 
 607 
 608     def OnCloseWindow(self, event):
 609         """
 610         ...
 611         """
 612 
 613         self.Destroy()
 614 
 615 #-------------------------------------------------------------------------------
 616 
 617 class My_App(wx.App):
 618     """
 619     ...
 620     """
 621     def OnInit(self):
 622 
 623         #------------
 624 
 625         self.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
 626 
 627         #------------
 628 
 629         frame = My_Frame(None, id=-1)
 630         self.SetTopWindow(frame)
 631         frame.Show(True)
 632 
 633         return True
 634 
 635 #-------------------------------------------------------------------------------
 636 
 637 def main():
 638     app = My_App(False)
 639     app.MainLoop()
 640 
 641 #-------------------------------------------------------------------------------
 642 
 643 if __name__ == "__main__" :
 644     main()


Multiline printing

img_sample_four.PNG

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