]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wx/lib/printout.py
compilation fix after removing wxImage(wxImage *) ctor
[wxWidgets.git] / wxPython / wx / lib / printout.py
index c927f0659de1ed4fc700f9878412e007372f8ecf..0ced233037385ad4de6ba694291ce0503ad66c81 100644 (file)
+#----------------------------------------------------------------------------
+# Name:         printout.py
+# Purpose:      preview and printing class -> table/grid printing
+#
+# Author:       Lorne White (email: lorne.white@telusplanet.net)
+#
+# Created:
+# Version       0.75
+# Date:         May 15, 2002
+# Licence:      wxWindows license
+#----------------------------------------------------------------------------
+# Release Notes
 
-"""Renamer stub: provides a way to drop the wx prefix from wxPython objects."""
+# fixed bug for string wider than print region
+# add index to data list after parsing total pages for paging
+#----------------------------------------------------------------------------
+# 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net)
+# o 2.5 compatability update.
+#----------------------------------------------------------------------------
+# 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com)
+# o Generalize for non-2-dimensional sequences and non-text data
+#   (can use as a simple text printer by supplying a list of strings.)
+# o Add a small _main_ for self test
+import  copy
+import  types
+import  wx
 
-__cvsid__ = "$Id$"
-__revision__ = "$Revision$"[11:-2]
+class PrintBase:
+    def SetPrintFont(self, font):      # set the DC font parameters
+        fattr = font["Attr"]
+        if fattr[0] == 1:
+            weight = wx.BOLD
+        else:
+            weight = wx.NORMAL
 
-from wx import _rename
-from wxPython.lib import printout
-_rename(globals(), printout.__dict__, modulename='lib.printout')
-del printout
-del _rename
+        if fattr[1] == 1:
+            set_style = wx.ITALIC
+        else:
+            set_style = wx.NORMAL
+
+        underline = fattr[2]
+        fcolour = self.GetFontColour(font)
+        self.DC.SetTextForeground(fcolour)
+
+        setfont = wx.Font(font["Size"], wx.SWISS, set_style, weight, underline)
+        setfont.SetFaceName(font["Name"])
+        self.DC.SetFont(setfont)
+
+    def GetFontColour(self, font):
+        fcolour = font["Colour"]
+        return wx.Colour(fcolour[0], fcolour[1], fcolour[2])
+
+    def OutTextRegion(self, textout, txtdraw = True):
+        textlines = textout.split('\n')
+        y = copy.copy(self.y) + self.pt_space_before
+        for text in textlines:
+            remain = 'X'
+            while remain != "":
+                vout, remain = self.SetFlow(text, self.region)
+                if self.draw == True and txtdraw == True:
+                    test_out = self.TestFull(vout)
+                    if self.align == wx.ALIGN_LEFT:
+                        self.DC.DrawText(test_out, self.indent+self.pcell_left_margin, y)
+
+                    elif self.align == wx.ALIGN_CENTRE:
+                        diff = self.GetCellDiff(test_out, self.region)
+                        self.DC.DrawText(test_out, self.indent+diff/2, y)
+
+                    elif self.align == wx.ALIGN_RIGHT:
+                        diff = self.GetCellDiff(test_out, self.region)
+                        self.DC.DrawText(test_out, self.indent+diff, y)
+
+                    else:
+                        self.DC.DrawText(test_out, self.indent+self.pcell_left_margin, y)
+                text = remain
+                y = y + self.space
+        return y - self.space + self.pt_space_after
+
+    def GetCellDiff(self, text, width):      # get the remaining cell size for adjustment
+        w, h = self.DC.GetTextExtent(text)
+        diff = width - w
+        if diff < 0:
+            diff = 0
+        return diff
+
+    def TestFull(self, text_test):
+        w, h = self.DC.GetTextExtent(text_test)
+        if w > self.region:     # trouble fitting into cell
+            return self.SetChar(text_test, self.region)     # fit the text to the cell size
+        else:
+            return text_test
+
+    def SetFlow(self, ln_text, width):
+        width = width - self.pcell_right_margin
+        text = ""
+        split = ln_text.split()
+        if len(split) == 1:
+            return ln_text, ""
+
+        try:
+            w, h = self.DC.GetTextExtent(" " + split[0])
+            if w >= width:
+                return ln_text, ""
+        except:
+            pass
+
+        cnt = 0
+        for word in split:
+            bword = " " + word  # blank + word
+            length = len(bword)
+
+            w, h = self.DC.GetTextExtent(text + bword)
+            if w < width:
+                text = text + bword
+                cnt = cnt + 1
+            else:
+                remain = ' '.join(split[cnt:])
+                text = text.strip()
+                return text, remain
+
+        remain = ' '.join(split[cnt:])
+        vout = text.strip()
+        return vout, remain
+
+    def SetChar(self, ln_text, width):  # truncate string to fit into width
+        width = width - self.pcell_right_margin - self.pcell_left_margin
+        text = ""
+        for val in ln_text:
+            w, h = self.DC.GetTextExtent(text + val)
+            if w > width:
+                text = text + ".."
+                return text     # fitted text value
+            text = text + val
+        return text
+
+    def OutTextPageWidth(self, textout, y_out, align, indent, txtdraw = True):
+        textlines = textout.split('\n')
+        y = copy.copy(y_out)
+
+        pagew = self.parent.page_width * self.pwidth        # full page width
+        w, h = self.DC.GetTextExtent(textout)
+        y_line = h
+
+        for text in textlines:
+            remain = 'X'
+            while remain != "":
+                vout, remain = self.SetFlow(text, pagew)
+                if self.draw == True and txtdraw == True:
+                    test_out = vout
+                    if align == wx.ALIGN_LEFT:
+                        self.DC.DrawText(test_out, indent, y)
+
+                    elif align == wx.ALIGN_CENTRE:
+                        diff = self.GetCellDiff(test_out, pagew)
+                        self.DC.DrawText(test_out, indent+diff/2, y)
+
+                    elif align == wx.ALIGN_RIGHT:
+                        diff = self.GetCellDiff(test_out, pagew)
+                        self.DC.DrawText(test_out, indent+diff, y)
+
+                    else:
+                        self.DC.DrawText(test_out, indent, y_out)
+                text = remain
+                y = y + y_line
+        return y - y_line
+
+    def GetDate(self):
+        date, time = self.GetNow()
+        return date
+
+    def GetDateTime(self):
+        date, time = self.GetNow()
+        return date + ' ' + time
+
+    def GetNow(self):
+        now = wx.DateTime.Now()
+        date = now.FormatDate()
+        time = now.FormatTime()
+        return date, time
+
+    def SetPreview(self, preview):
+        self.preview = preview
+
+    def SetPSize(self, width, height):
+        self.pwidth = width/self.scale
+        self.pheight = height/self.scale
+
+    def SetScale(self, scale):
+        self.scale = scale
+
+    def SetPTSize(self, width, height):
+        self.ptwidth = width
+        self.ptheight = height
+
+    def getWidth(self):
+        return self.sizew
+
+    def getHeight(self):
+        return self.sizeh
+
+
+class PrintTableDraw(wx.ScrolledWindow, PrintBase):
+    def __init__(self, parent, DC, size):
+        self.parent = parent
+        self.DC = DC
+        self.scale = parent.scale
+        self.width = size[0]
+        self.height = size[1]
+        self.SetDefaults()
+
+    def SetDefaults(self):
+        self.page = 1
+        self.total_pages = None
+
+        self.page_width = self.parent.page_width
+        self.page_height = self.parent.page_height
+
+        self.left_margin = self.parent.left_margin
+        self.right_margin = self.parent.right_margin
+
+        self.top_margin  = self.parent.top_margin
+        self.bottom_margin = self.parent.bottom_margin
+        self.cell_left_margin = self.parent.cell_left_margin
+        self.cell_right_margin = self.parent.cell_right_margin
+
+        self.label_colour = self.parent.label_colour
+
+        self.row_line_colour = self.parent.row_line_colour
+        self.row_line_size = self.parent.row_line_size
+
+        self.row_def_line_colour = self.parent.row_def_line_colour
+        self.row_def_line_size = self.parent.row_def_line_size
+
+        self.column_line_colour = self.parent.column_line_colour
+        self.column_line_size = self.parent.column_line_size
+
+        self.column_def_line_size = self.parent.column_def_line_size
+        self.column_def_line_colour = self.parent.column_def_line_colour
+
+        self.text_font = self.parent.text_font
+
+        self.label_font = self.parent.label_font
+
+    def AdjustValues(self):
+        self.vertical_offset = self.pheight * self.parent.vertical_offset
+        self.horizontal_offset = self.pheight * self.parent.horizontal_offset
+
+        self.pcell_left_margin = self.pwidth * self.cell_left_margin
+        self.pcell_right_margin = self.pwidth * self.cell_right_margin
+        self.ptop_margin = self.pheight * self.top_margin
+        self.pbottom_margin = self.pheight * self.bottom_margin
+
+        self.pheader_margin = self.pheight * self.parent.header_margin
+        self.pfooter_margin = self.pheight * self.parent.footer_margin
+
+        self.cell_colour = self.parent.set_cell_colour
+        self.cell_text = self.parent.set_cell_text
+
+        self.column = []
+        self.column_align = []
+        self.column_bgcolour = []
+        self.column_txtcolour = []
+
+        set_column_align = self.parent.set_column_align
+        set_column_bgcolour = self.parent.set_column_bgcolour
+        set_column_txtcolour = self.parent.set_column_txtcolour
+
+        pos_x = self.left_margin * self.pwidth + self.horizontal_offset     # left margin
+        self.column.append(pos_x)
+
+        #module logic expects two dimensional data -- fix input if needed
+        if isinstance(self.data,types.StringTypes):
+            self.data = [[copy.copy(self.data)]] # a string becomes a single cell
+        try:
+            rows = len(self.data)
+        except TypeError:
+            self.data = [[str(self.data)]] # a non-iterable becomes a single cell
+            rows = 1
+        first_value = self.data[0]
+
+        if isinstance(first_value, types.StringTypes): # a sequence of strings
+            if self.label == [] and self.set_column == []:
+                data = []
+                for x in self.data:     #becomes one column
+                    data.append([x])
+            else:
+                data = [self.data]      #becames one row
+            self.data = data
+            first_value = data[0]
+        try:
+            column_total = len(first_value)
+        except TypeError:    # a sequence of non-iterables
+            if self.label == [] and self.set_column == []:
+                data = []       #becomes one column
+                for x in self.data:
+                    data.append([str(x)])
+                column_total = 1
+            else:
+                data = [self.data] #becomes one row
+                column_total = len(self.data)
+            self.data = data
+            first_value = data[0]
+
+        if self.set_column == []:
+            table_width = self.page_width - self.left_margin - self.right_margin
+            if self.label == []:
+                temp = first_value
+            else:
+                temp = self.label
+            width = table_width/(len(temp))
+            for val in temp:
+                column_width = width * self.pwidth
+                pos_x = pos_x + column_width
+                self.column.append(pos_x)   # position of each column
+        else:
+            for val in self.set_column:
+                column_width = val * self.pwidth
+                pos_x = pos_x + column_width
+                self.column.append(pos_x)   # position of each column
+
+        if pos_x > self.page_width * self.pwidth:    # check if it fits in page
+            print "Warning, Too Wide for Page"
+            return
+
+        if self.label != []:
+            if len(self.column) -1 != len(self.label):
+                print "Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label)
+                return
+
+        if column_total != len(self.column) -1:
+            print "Cannot fit", first_value, 'in', len(self.column)-1, 'columns.'
+            return
+
+        for col in range(column_total):
+            try:
+                align = set_column_align[col]       # check if custom column alignment
+            except:
+                align = wx.ALIGN_LEFT
+            self.column_align.append(align)
+
+            try:
+                colour = set_column_bgcolour[col]     # check if custom column background colour
+            except:
+                colour = self.parent.column_colour
+            self.column_bgcolour.append(colour)
+
+            try:
+                colour = set_column_txtcolour[col]     # check if custom column text colour
+            except:
+                colour = self.GetFontColour(self.parent.text_font)
+            self.column_txtcolour.append(colour)
+
+
+    def SetPointAdjust(self):
+        f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL)     # setup using 10 point
+        self.DC.SetFont(f)
+        f.SetFaceName(self.text_font["Name"])
+        x, y = self.DC.GetTextExtent("W")
+
+        self.label_pt_space_before = self.parent.label_pt_adj_before * y/10        # extra spacing for label per point value
+        self.label_pt_space_after = self.parent.label_pt_adj_after * y/10
+
+        self.text_pt_space_before = self.parent.text_pt_adj_before * y/10        # extra spacing for row text per point value
+        self.text_pt_space_after = self.parent.text_pt_adj_after * y/10
+
+    def SetPage(self, page):
+        self.page = page
+
+    def SetColumns(self, col):
+        self.column = col
+
+    def OutCanvas(self):
+        self.AdjustValues()
+        self.SetPointAdjust()
+
+        self.y_start = self.ptop_margin + self.vertical_offset
+        self.y_end = self.parent.page_height * self.pheight - self.pbottom_margin + self.vertical_offset
+
+        self.SetPrintFont(self.label_font)
+
+        x, y = self.DC.GetTextExtent("W")
+        self.label_space = y
+
+        self.SetPrintFont(self.text_font)
+
+        x, y = self.DC.GetTextExtent("W")
+        self.space = y
+
+        if self.total_pages is None:
+            self.GetTotalPages()    # total pages for display/printing
+
+        self.data_cnt = self.page_index[self.page-1]
+
+        self.draw = True
+        self.PrintHeader()
+        self.PrintFooter()
+        self.OutPage()
+
+    def GetTotalPages(self):
+        self.data_cnt = 0
+        self.draw = False
+        self.page_index = [0]
+
+        cnt = 0
+        while 1:
+            test = self.OutPage()
+            self.page_index.append(self.data_cnt)
+            if  test == False:
+                break
+            cnt = cnt + 1
+
+        self.total_pages = cnt + 1
+
+    def OutPage(self):
+        self.y = self.y_start
+        self.end_x = self.column[-1]
+
+        if self.data_cnt < len(self.data):  # if there data for display on the page
+            if self.label != []:        # check if header defined
+                self.PrintLabel()
+        else:
+            return False
+
+        for val in self.data:
+            try:
+                row_val = self.data[self.data_cnt]
+            except:
+                self.FinishDraw()
+                return False
+
+            max_y = self.PrintRow(row_val, False)       # test to see if row will fit in remaining space
+            test = max_y + self.space
+
+            if test > self.y_end:
+                break
+
+            self.ColourRowCells(max_y-self.y+self.space)       # colour the row/column
+            max_y = self.PrintRow(row_val, True)      # row fits - print text
+            self.DrawGridLine()     # top line of cell
+            self.y = max_y + self.space
+
+            if self.y > self.y_end:
+                break
+
+            self.data_cnt = self.data_cnt + 1
+
+        self.FinishDraw()
+
+        if self.data_cnt == len(self.data):    # last value in list
+            return False
+
+        return True
+
+
+    def PrintLabel(self):
+        self.pt_space_before = self.label_pt_space_before   # set the point spacing
+        self.pt_space_after = self.label_pt_space_after
+
+        self.LabelColorRow(self.label_colour)
+        self.SetPrintFont(self.label_font)
+
+        self.col = 0
+        max_y = 0
+        for vtxt in self.label:
+            self.region = self.column[self.col+1] - self.column[self.col]
+            self.indent = self.column[self.col]
+
+            self.align = wx.ALIGN_LEFT
+
+            max_out = self.OutTextRegion(vtxt, True)
+            if max_out > max_y:
+                max_y = max_out
+            self.col = self.col + 1
+
+        self.DrawGridLine()     # top line of label
+        self.y = max_y + self.label_space
+
+    def PrintHeader(self):      # print the header array
+        if self.draw == False:
+            return
+
+        for val in self.parent.header:
+            self.SetPrintFont(val["Font"])
+
+            header_indent = val["Indent"] * self.pwidth
+            text = val["Text"]
+
+            htype = val["Type"]
+            if htype == "Date":
+                addtext = self.GetDate()
+            elif htype == "Date & Time":
+                addtext = self.GetDateTime()
+            else:
+                addtext = ""
+
+            self.OutTextPageWidth(text+addtext, self.pheader_margin, val["Align"], header_indent, True)
+
+    def PrintFooter(self):      # print the header array
+        if self.draw == False:
+            return
+
+        footer_pos = self.parent.page_height * self.pheight - self.pfooter_margin + self.vertical_offset
+        for val in self.parent.footer:
+            self.SetPrintFont(val["Font"])
+
+            footer_indent = val["Indent"] * self.pwidth
+            text = val["Text"]
+
+            ftype = val["Type"]
+            if ftype == "Pageof":
+                addtext = "Page " + str(self.page) + " of " + str(self.total_pages)
+            elif ftype == "Page":
+                addtext = "Page " + str(self.page)
+            elif ftype == "Num":
+                addtext = str(self.page)
+            elif ftype == "Date":
+                addtext = self.GetDate()
+            elif ftype == "Date & Time":
+                addtext = self.GetDateTime()
+            else:
+                addtext = ""
+
+            self.OutTextPageWidth(text+addtext, footer_pos, val["Align"], footer_indent, True)
+
+
+    def LabelColorRow(self, colour):
+        brush = wx.Brush(colour, wx.SOLID)
+        self.DC.SetBrush(brush)
+        height = self.label_space + self.label_pt_space_before + self.label_pt_space_after
+        self.DC.DrawRectangle(self.column[0], self.y,
+                              self.end_x-self.column[0]+1, height)
+
+    def ColourRowCells(self, height):
+        if self.draw == False:
+            return
+
+        col = 0
+        for colour in self.column_bgcolour:
+            cellcolour = self.GetCellColour(self.data_cnt, col)
+            if cellcolour is not None:
+                colour = cellcolour
+
+            brush = wx.Brush(colour, wx.SOLID)
+            self.DC.SetBrush(brush)
+            self.DC.SetPen(wx.Pen(wx.NamedColour('WHITE'), 0))
+
+            start_x = self.column[col]
+            width = self.column[col+1] - start_x + 2
+            self.DC.DrawRectangle(start_x, self.y, width, height)
+            col = col + 1
+
+    def PrintRow(self, row_val, draw = True, align = wx.ALIGN_LEFT):
+        self.SetPrintFont(self.text_font)
+
+        self.pt_space_before = self.text_pt_space_before   # set the point spacing
+        self.pt_space_after = self.text_pt_space_after
+
+        self.col = 0
+        max_y = 0
+        for vtxt in row_val:
+            if not isinstance(vtxt,types.StringTypes):
+                vtxt = str(vtxt)
+            self.region = self.column[self.col+1] - self.column[self.col]
+            self.indent = self.column[self.col]
+            self.align = self.column_align[self.col]
+
+            fcolour = self.column_txtcolour[self.col]       # set font colour
+            celltext = self.GetCellTextColour(self.data_cnt, self.col)
+            if celltext is not None:
+                fcolour = celltext      # override the column colour
+
+            self.DC.SetTextForeground(fcolour)
+
+            max_out = self.OutTextRegion(vtxt, draw)
+            if max_out > max_y:
+                max_y = max_out
+            self.col = self.col + 1
+        return max_y
+
+    def GetCellColour(self, row, col):      # check if custom colour defined for the cell background
+        try:
+            set = self.cell_colour[row]
+        except:
+            return None
+        try:
+            colour = set[col]
+            return colour
+        except:
+            return None
+
+    def GetCellTextColour(self, row, col):      # check if custom colour defined for the cell text
+        try:
+            set = self.cell_text[row]
+        except:
+            return None
+        try:
+            colour = set[col]
+            return colour
+        except:
+            return None
+
+    def FinishDraw(self):
+        self.DrawGridLine()     # draw last row line
+        self.DrawColumns()      # draw all vertical lines
+
+    def DrawGridLine(self):
+        if self.draw == True \
+        and len(self.column) > 2:    #supress grid lines if only one column
+            try:
+                size = self.row_line_size[self.data_cnt]
+            except:
+                size = self.row_def_line_size
+
+            try:
+                colour = self.row_line_colour[self.data_cnt]
+            except:
+                colour = self.row_def_line_colour
+
+            self.DC.SetPen(wx.Pen(colour, size))
+
+            y_out = self.y
+#            y_out = self.y + self.pt_space_before + self.pt_space_after     # adjust for extra spacing
+            self.DC.DrawLine(self.column[0], y_out, self.end_x, y_out)
+
+    def DrawColumns(self):
+        if self.draw == True \
+        and len(self.column) > 2:   #surpress grid line if only one column
+            col = 0
+            for val in self.column:
+                try:
+                    size = self.column_line_size[col]
+                except:
+                    size = self.column_def_line_size
+
+                try:
+                    colour = self.column_line_colour[col]
+                except:
+                    colour = self.column_def_line_colour
+
+                indent = val
+
+                self.DC.SetPen(wx.Pen(colour, size))
+                self.DC.DrawLine(indent, self.y_start, indent, self.y)
+                col = col + 1
+
+    def DrawText(self):
+        self.DoRefresh()
+
+    def DoDrawing(self, DC):
+        size = DC.GetSize()
+        self.DC = DC
+
+        DC.BeginDrawing()
+        self.DrawText()
+        DC.EndDrawing()
+
+        self.sizew = DC.MaxY()
+        self.sizeh = DC.MaxX()
+
+
+class PrintTable:
+    def __init__(self, parentFrame=None):
+        self.data = []
+        self.set_column = []
+        self.label = []
+        self.header = []
+        self.footer = []
+
+        self.set_column_align = {}
+        self.set_column_bgcolour = {}
+        self.set_column_txtcolour = {}
+        self.set_cell_colour = {}
+        self.set_cell_text = {}
+        self.column_line_size = {}
+        self.column_line_colour = {}
+        self.row_line_size = {}
+        self.row_line_colour = {}
+
+        self.parentFrame = parentFrame
+        self.SetPreviewSize()
+
+        self.printData = wx.PrintData()
+        self.scale = 1.0
+
+        self.SetParms()
+        self.SetColors()
+        self.SetFonts()
+        self.TextSpacing()
+
+        self.SetPrinterOffset()
+        self.SetHeaderValue()
+        self.SetFooterValue()
+        self.SetMargins()
+        self.SetPortrait()
+
+    def SetPreviewSize(self, position = wx.Point(0, 0), size="Full"):
+        if size == "Full":
+            r = wx.GetClientDisplayRect()
+            self.preview_frame_size = r.GetSize()
+            self.preview_frame_pos = r.GetPosition()
+        else:
+            self.preview_frame_size = size
+            self.preview_frame_pos = position
+
+    def SetPaperId(self, paper):
+        self.printData.SetPaperId(paper)
+
+    def SetOrientation(self, orient):
+        self.printData.SetOrientation(orient)
+
+    def SetColors(self):
+        self.row_def_line_colour = wx.NamedColour('BLACK')
+        self.row_def_line_size = 1
+
+        self.column_def_line_colour = wx.NamedColour('BLACK')
+        self.column_def_line_size = 1
+        self.column_colour = wx.NamedColour('WHITE')
+
+        self.label_colour = wx.NamedColour('LIGHT GREY')
+
+    def SetFonts(self):
+        self.label_font = { "Name": self.default_font_name, "Size": 12, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+        self.text_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+
+    def TextSpacing(self):
+        self.label_pt_adj_before = 0     # point adjustment before and after the label text
+        self.label_pt_adj_after = 0
+
+        self.text_pt_adj_before = 0     # point adjustment before and after the row text
+        self.text_pt_adj_after = 0
+
+    def SetLabelSpacing(self, before, after):        # method to set the label space adjustment
+        self.label_pt_adj_before = before
+        self.label_pt_adj_after = after
+
+    def SetRowSpacing(self, before, after):         # method to set the row space adjustment
+        self.text_pt_adj_before = before
+        self.text_pt_adj_after = after
+
+    def SetPrinterOffset(self):        # offset to adjust for printer
+        self.vertical_offset = -0.1
+        self.horizontal_offset = -0.1
+
+    def SetHeaderValue(self):
+        self.header_margin = 0.25
+        self.header_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+        self.header_align = wx.ALIGN_CENTRE
+        self.header_indent = 0
+        self.header_type = "Text"
+
+    def SetFooterValue(self):
+        self.footer_margin = 0.7
+        self.footer_font = { "Name": self.default_font_name, "Size": 11, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+        self.footer_align = wx.ALIGN_CENTRE
+        self.footer_indent = 0
+        self.footer_type = "Pageof"
+
+    def SetMargins(self):
+        self.left_margin = 0.5
+        self.right_margin = 0.5    # only used if no column sizes
+
+        self.top_margin  = 0.8
+        self.bottom_margin = 1.0
+        self.cell_left_margin = 0.1
+        self.cell_right_margin = 0.1
+
+    def SetPortrait(self):
+        self.printData.SetPaperId(wx.PAPER_LETTER)
+        self.printData.SetOrientation(wx.PORTRAIT)
+        self.page_width = 8.5
+        self.page_height = 11.0
+
+    def SetLandscape(self):
+        self.printData.SetOrientation(wx.LANDSCAPE)
+        self.page_width = 11.0
+        self.page_height = 8.5
+
+    def SetParms(self):
+        self.ymax = 1
+        self.xmax = 1
+        self.page = 1
+        self.total_pg = 100
+
+        self.preview = None
+        self.page = 0
+
+        self.default_font_name = "Arial"
+        self.default_font = { "Name": self.default_font_name, "Size": 10, "Colour": [0, 0, 0], "Attr": [0, 0, 0] }
+
+    def SetColAlignment(self, col, align=wx.ALIGN_LEFT):
+        self.set_column_align[col] = align
+
+    def SetColBackgroundColour(self, col, colour):
+        self.set_column_bgcolour[col] = colour
+
+    def SetColTextColour(self, col, colour):
+        self.set_column_txtcolour[col] = colour
+
+    def SetCellColour(self, row, col, colour):      # cell background colour
+        try:
+            set = self.set_cell_colour[row]     # test if row already exists
+            try:
+                set[col] = colour       # test if column already exists
+            except:
+                set = { col: colour }       # create the column value
+        except:
+            set = { col: colour }           # create the column value
+
+        self.set_cell_colour[row] = set    # create dictionary item for colour settings
+
+    def SetCellText(self, row, col, colour):        # font colour for custom cells
+        try:
+            set = self.set_cell_text[row]     # test if row already exists
+            try:
+                set[col] = colour       # test if column already exists
+            except:
+                set = { col: colour }       # create the column value
+        except:
+            set = { col: colour }           # create the column value
+
+        self.set_cell_text[row] = set    # create dictionary item for colour settings
+
+    def SetColumnLineSize(self, col, size):      # column line size
+        self.column_line_size[col] = size    # create dictionary item for column line settings
+
+    def SetColumnLineColour(self, col, colour):
+        self.column_line_colour[col] = colour
+
+    def SetRowLineSize(self, row, size):
+        self.row_line_size[row] = size
+
+    def SetRowLineColour(self, row, colour):
+        self.row_line_colour[row] = colour
+
+    def GetColour(self, colour):        # returns colours based from wxColour value
+        red = colour.Red()
+        blue = colour.Blue()
+        green = colour.Green()
+        return [red, green, blue ]
+
+    def SetHeader(self, text = "", type = "Text", font=None, align = None, indent = None, colour = None, size = None):
+        set = { "Text": text }
+
+        if font is None:
+            set["Font"] = copy.copy(self.default_font)
+        else:
+            set["Font"] = font
+
+        if colour is not None:
+            setfont = set["Font"]
+            setfont["Colour"] = self.GetColour(colour)
+
+        if size is not None:
+            setfont = set["Font"]
+            setfont["Size"] = size
+
+        if align is None:
+            set["Align"] = self.header_align
+        else:
+            set["Align"] = align
+
+        if indent is None:
+            set["Indent"] = self.header_indent
+        else:
+            set["Indent"] = indent
+
+        if type is None:
+            set["Type"] = self.header_type
+        else:
+            set["Type"] = type
+
+        self.header.append(set)
+
+    def SetFooter(self, text = "", type = None, font=None, align = None, indent = None, colour = None, size = None):
+        set = { "Text": text }
+
+        if font is None:
+            set["Font"] = copy.copy(self.default_font)
+        else:
+            set["Font"] = font
+
+        if colour is not None:
+            setfont = set["Font"]
+            setfont["Colour"] = self.GetColour(colour)
+
+        if size is not None:
+            setfont = set["Font"]
+            setfont["Size"] = size
+
+        if align is None:
+            set["Align"] = self.footer_align
+        else:
+            set["Align"] = align
+
+        if indent is None:
+            set["Indent"] = self.footer_indent
+        else:
+            set["Indent"] = indent
+
+        if type is None:
+            set["Type"] = self.footer_type
+        else:
+            set["Type"] = type
+
+        self.footer.append(set)
+
+    def Preview(self):
+        data = wx.PrintDialogData(self.printData)
+        printout = SetPrintout(self)
+        printout2 = SetPrintout(self)
+        self.preview = wx.PrintPreview(printout, printout2, data)
+        if not self.preview.Ok():
+            wxMessageBox("There was a problem printing!", "Printing", wx.OK)
+            return
+
+        self.preview.SetZoom(60)        # initial zoom value
+        frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview")
+
+        frame.Initialize()
+        if self.parentFrame:
+            frame.SetPosition(self.preview_frame_pos)
+            frame.SetSize(self.preview_frame_size)
+        frame.Show(True)
+
+    def Print(self):
+        pdd = wx.PrintDialogData(self.printData)
+        printer = wx.Printer(pdd)
+        printout = SetPrintout(self)
+        if not printer.Print(self.parentFrame, printout):
+            wx.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx.OK)
+        else:
+            self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() )
+        printout.Destroy()
+
+    def DoDrawing(self, DC):
+        size = DC.GetSize()
+        DC.BeginDrawing()
+
+        table = PrintTableDraw(self, DC, size)
+        table.data = self.data
+        table.set_column = self.set_column
+        table.label = self.label
+        table.SetPage(self.page)
+
+        if self.preview is None:
+            table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
+            table.SetPTSize(size[0], size[1])
+            table.SetPreview(False)
+        else:
+            if self.preview == 1:
+                table.scale = self.scale
+                table.SetPSize(size[0]/self.page_width, size[1]/self.page_height)
+            else:
+                table.SetPSize(self.pwidth, self.pheight)
+
+            table.SetPTSize(self.ptwidth, self.ptheight)
+            table.SetPreview(self.preview)
+
+        table.OutCanvas()
+        self.page_total = table.total_pages     # total display pages
+
+        DC.EndDrawing()
+
+        self.ymax = DC.MaxY()
+        self.xmax = DC.MaxX()
+
+        self.sizeh = size[0]
+        self.sizew = size[1]
+
+    def GetTotalPages(self):
+        self.page_total = 100
+        return self.page_total
+
+    def HasPage(self, page):
+        if page <= self.page_total:
+            return True
+        else:
+            return False
+
+    def SetPage(self, page):
+        self.page = page
+
+    def SetPageSize(self, width, height):
+        self.pwidth, self.pheight = width, height
+
+    def SetTotalSize(self, width, height):
+        self.ptwidth, self.ptheight = width, height
+
+    def SetPreview(self, preview, scale):
+        self.preview = preview
+        self.scale = scale
+
+    def SetTotalSize(self, width, height):
+        self.ptwidth = width
+        self.ptheight = height
+
+class PrintGrid:
+    def __init__(self, parent, grid, format = [], total_col = None, total_row = None):
+        if total_row is None:
+            total_row = grid.GetNumberRows()
+        if total_col is None:
+            total_col = grid.GetNumberCols()
+
+        self.total_row = total_row
+        self.total_col = total_col
+        self.grid = grid
+
+        data = []
+        for row in range(total_row):
+            row_val = []
+            value = grid.GetRowLabelValue(row)
+            row_val.append(value)
+
+            for col in range(total_col):
+                value = grid.GetCellValue(row, col)
+                row_val.append(value)
+            data.append(row_val)
+
+        label = [""]
+        for col in range(total_col):
+            value = grid.GetColLabelValue(col)
+            label.append(value)
+
+        self.table = PrintTable(parent)
+        self.table.cell_left_margin = 0.0
+        self.table.cell_right_margin = 0.0
+
+        self.table.label = label
+        self.table.set_column = format
+        self.table.data = data
+
+    def GetTable(self):
+        return self.table
+
+    def SetAttributes(self):
+        for row in range(self.total_row):
+            for col in range(self.total_col):
+                colour = self.grid.GetCellTextColour(row, col-1)
+                self.table.SetCellText(row, col, colour)
+
+                colour = self.grid.GetCellBackgroundColour(row, col-1)
+                self.table.SetCellColour(row, col, colour)
+
+    def Preview(self):
+        self.table.Preview()
+
+    def Print(self):
+        self.table.Print()
+
+
+class SetPrintout(wx.Printout):
+    def __init__(self, canvas):
+        wx.Printout.__init__(self)
+        self.canvas = canvas
+        self.end_pg = 1000
+
+    def OnBeginDocument(self, start, end):
+        return super(SetPrintout, self).OnBeginDocument(start, end)
+
+    def OnEndDocument(self):
+        super(SetPrintout, self).OnEndDocument()
+
+    def HasPage(self, page):
+        try:
+            end = self.canvas.HasPage(page)
+            return end
+        except:
+            return True
+
+    def GetPageInfo(self):
+        try:
+            self.end_pg = self.canvas.GetTotalPages()
+        except:
+            pass
+
+        end_pg = self.end_pg
+        str_pg = 1
+        return (str_pg, end_pg, str_pg, end_pg)
+
+    def OnPreparePrinting(self):
+        super(SetPrintout, self).OnPreparePrinting()
+
+    def OnBeginPrinting(self):
+        dc = self.GetDC()
+
+        self.preview = self.IsPreview()
+        if (self.preview):
+            self.pixelsPerInch = self.GetPPIScreen()
+        else:
+            self.pixelsPerInch = self.GetPPIPrinter()
+
+        (w, h) = dc.GetSize()
+        scaleX = float(w) / 1000
+        scaleY = float(h) / 1000
+        self.printUserScale = min(scaleX, scaleY)
+
+        super(SetPrintout, self).OnBeginPrinting()
+
+    def GetSize(self):
+        self.psizew, self.psizeh = self.GetPPIPrinter()
+        return self.psizew, self.psizeh
+
+    def GetTotalSize(self):
+        self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
+        return self.ptsizew, self.ptsizeh
+
+    def OnPrintPage(self, page):
+        dc = self.GetDC()
+        (w, h) = dc.GetSize()
+        scaleX = float(w) / 1000
+        scaleY = float(h) / 1000
+        self.printUserScale = min(scaleX, scaleY)
+        dc.SetUserScale(self.printUserScale, self.printUserScale)
+
+        self.preview = self.IsPreview()
+
+        self.canvas.SetPreview(self.preview, self.printUserScale)
+        self.canvas.SetPage(page)
+
+        self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
+        self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
+
+        self.psizew, self.psizeh = self.GetPPIPrinter()
+        self.canvas.SetPageSize(self.psizew, self.psizeh)
+
+        self.canvas.DoDrawing(dc)
+        return True
+
+if __name__ == '__main__':
+    app = wx.PySimpleApp()
+    frame = wx.Frame(None, -1, "Dummy wx frame for testing printout.py")
+    frame.Show(True)
+    ptbl = PrintTable(frame)
+    ptbl.SetHeader('This is the test HEADER')
+    # a single sequence will print out as a single column with no borders ...
+    ptbl.data = (
+        'This is the first line of text.',
+        'This is the second line\nand the third. The fourth will be the number "4.0".',
+        04.00,
+        'This is the fifth line, but by design it is too long to fit in the width of a standard'\
+         ' page, so it will be forced to wrap around in order to fit without having '\
+         'some of its verbose verbage truncated.',
+        'Here we have the final line.'
+        )
+    #... but, if labels or columns are defined, a single sequence will print out as a single row
+    ##ptbl.label = ('One','Two','Three','Four','5')
+    ptbl.Preview()
+    app.MainLoop()