]>
Commit | Line | Data |
---|---|---|
be05b434 RD |
1 | import wx |
2 | import os | |
3 | ||
4 | FONTSIZE = 10 | |
5 | ||
6 | class TextDocPrintout(wx.Printout): | |
7 | """ | |
8 | A printout class that is able to print simple text documents. | |
9 | Does not handle page numbers or titles, and it assumes that no | |
10 | lines are longer than what will fit within the page width. Those | |
11 | features are left as an exercise for the reader. ;-) | |
12 | """ | |
13 | def __init__(self, text, title, margins): | |
14 | wx.Printout.__init__(self, title) | |
15 | self.lines = text.split('\n') | |
16 | self.margins = margins | |
17 | ||
18 | ||
19 | def HasPage(self, page): | |
20 | return page <= self.numPages | |
21 | ||
22 | def GetPageInfo(self): | |
23 | return (1, self.numPages, 1, self.numPages) | |
24 | ||
25 | ||
26 | def CalculateScale(self, dc): | |
27 | # Scale the DC such that the printout is roughly the same as | |
28 | # the screen scaling. | |
29 | ppiPrinterX, ppiPrinterY = self.GetPPIPrinter() | |
30 | ppiScreenX, ppiScreenY = self.GetPPIScreen() | |
31 | logScale = float(ppiPrinterX)/float(ppiScreenX) | |
32 | ||
33 | # Now adjust if the real page size is reduced (such as when | |
34 | # drawing on a scaled wx.MemoryDC in the Print Preview.) If | |
35 | # page width == DC width then nothing changes, otherwise we | |
36 | # scale down for the DC. | |
37 | pw, ph = self.GetPageSizePixels() | |
38 | dw, dh = dc.GetSize() | |
39 | scale = logScale * float(dw)/float(pw) | |
40 | ||
41 | # Set the DC's scale. | |
42 | dc.SetUserScale(scale, scale) | |
43 | ||
44 | # Find the logical units per millimeter (for calculating the | |
45 | # margins) | |
46 | self.logUnitsMM = float(ppiPrinterX)/(logScale*25.4) | |
47 | ||
48 | ||
49 | def CalculateLayout(self, dc): | |
50 | # Determine the position of the margins and the | |
51 | # page/line height | |
52 | topLeft, bottomRight = self.margins | |
53 | dw, dh = dc.GetSize() | |
54 | self.x1 = topLeft.x * self.logUnitsMM | |
55 | self.y1 = topLeft.y * self.logUnitsMM | |
56 | self.x2 = dc.DeviceToLogicalXRel(dw) - bottomRight.x * self.logUnitsMM | |
57 | self.y2 = dc.DeviceToLogicalYRel(dh) - bottomRight.y * self.logUnitsMM | |
58 | ||
59 | # use a 1mm buffer around the inside of the box, and a few | |
60 | # pixels between each line | |
61 | self.pageHeight = self.y2 - self.y1 - 2*self.logUnitsMM | |
62 | font = wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL) | |
63 | dc.SetFont(font) | |
64 | self.lineHeight = dc.GetCharHeight() | |
65 | self.linesPerPage = int(self.pageHeight/self.lineHeight) | |
66 | ||
67 | ||
68 | def OnPreparePrinting(self): | |
69 | # calculate the number of pages | |
70 | dc = self.GetDC() | |
71 | self.CalculateScale(dc) | |
72 | self.CalculateLayout(dc) | |
73 | self.numPages = len(self.lines) / self.linesPerPage | |
74 | if len(self.lines) % self.linesPerPage != 0: | |
75 | self.numPages += 1 | |
76 | ||
77 | ||
78 | def OnPrintPage(self, page): | |
79 | dc = self.GetDC() | |
80 | self.CalculateScale(dc) | |
81 | self.CalculateLayout(dc) | |
82 | ||
83 | # draw a page outline at the margin points | |
84 | dc.SetPen(wx.Pen("black", 0)) | |
85 | dc.SetBrush(wx.TRANSPARENT_BRUSH) | |
86 | r = wx.RectPP((self.x1, self.y1), | |
87 | (self.x2, self.y2)) | |
88 | dc.DrawRectangleRect(r) | |
89 | dc.SetClippingRect(r) | |
90 | ||
91 | # Draw the text lines for this page | |
92 | line = (page-1) * self.linesPerPage | |
93 | x = self.x1 + self.logUnitsMM | |
94 | y = self.y1 + self.logUnitsMM | |
95 | while line < (page * self.linesPerPage): | |
96 | dc.DrawText(self.lines[line], x, y) | |
97 | y += self.lineHeight | |
98 | line += 1 | |
99 | if line >= len(self.lines): | |
100 | break | |
101 | return True | |
102 | ||
103 | ||
104 | class PrintFrameworkSample(wx.Frame): | |
105 | def __init__(self): | |
106 | wx.Frame.__init__(self, None, size=(640, 480), | |
107 | title="Print Framework Sample") | |
108 | self.CreateStatusBar() | |
109 | ||
110 | # A text widget to display the doc and let it be edited | |
111 | self.tc = wx.TextCtrl(self, -1, "", | |
112 | style=wx.TE_MULTILINE|wx.TE_DONTWRAP) | |
113 | self.tc.SetFont(wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL)) | |
114 | filename = os.path.join(os.path.dirname(__file__), "sample-text.txt") | |
115 | self.tc.SetValue(open(filename).read()) | |
116 | self.tc.Bind(wx.EVT_SET_FOCUS, self.OnClearSelection) | |
117 | wx.CallAfter(self.tc.SetInsertionPoint, 0) | |
118 | ||
119 | # Create the menu and menubar | |
120 | menu = wx.Menu() | |
121 | item = menu.Append(-1, "Page Setup...\tF5", | |
122 | "Set up page margins and etc.") | |
123 | self.Bind(wx.EVT_MENU, self.OnPageSetup, item) | |
124 | item = menu.Append(-1, "Print Preview...\tF6", | |
125 | "View the printout on-screen") | |
126 | self.Bind(wx.EVT_MENU, self.OnPrintPreview, item) | |
127 | item = menu.Append(-1, "Print...\tF7", "Print the document") | |
128 | self.Bind(wx.EVT_MENU, self.OnPrint, item) | |
129 | menu.AppendSeparator() | |
130 | ## item = menu.Append(-1, "Test other stuff...\tF9", "") | |
131 | ## self.Bind(wx.EVT_MENU, self.OnPrintTest, item) | |
132 | ## menu.AppendSeparator() | |
133 | item = menu.Append(wx.ID_EXIT, "E&xit\tCtrl-Q", "Close this application") | |
134 | self.Bind(wx.EVT_MENU, self.OnExit, item) | |
135 | ||
136 | menubar = wx.MenuBar() | |
137 | menubar.Append(menu, "&File") | |
138 | self.SetMenuBar(menubar) | |
139 | ||
140 | # initialize the print data and set some default values | |
141 | self.pdata = wx.PrintData() | |
142 | self.pdata.SetPaperId(wx.PAPER_LETTER) | |
143 | self.pdata.SetOrientation(wx.PORTRAIT) | |
144 | self.margins = (wx.Point(15,15), wx.Point(15,15)) | |
145 | ||
146 | ||
147 | def OnExit(self, evt): | |
148 | self.Close() | |
149 | ||
150 | ||
151 | def OnClearSelection(self, evt): | |
152 | evt.Skip() | |
153 | wx.CallAfter(self.tc.SetInsertionPoint, | |
154 | self.tc.GetInsertionPoint()) | |
155 | ||
156 | ||
157 | def OnPageSetup(self, evt): | |
158 | data = wx.PageSetupDialogData() | |
159 | data.SetPrintData(self.pdata) | |
160 | ||
161 | data.SetDefaultMinMargins(True) | |
162 | data.SetMarginTopLeft(self.margins[0]) | |
163 | data.SetMarginBottomRight(self.margins[1]) | |
164 | ||
165 | dlg = wx.PageSetupDialog(self, data) | |
166 | if dlg.ShowModal() == wx.ID_OK: | |
167 | data = dlg.GetPageSetupData() | |
168 | self.pdata = wx.PrintData(data.GetPrintData()) # force a copy | |
169 | self.pdata.SetPaperId(data.GetPaperId()) | |
170 | self.margins = (data.GetMarginTopLeft(), | |
171 | data.GetMarginBottomRight()) | |
172 | dlg.Destroy() | |
173 | ||
174 | ||
175 | def OnPrintPreview(self, evt): | |
176 | data = wx.PrintDialogData(self.pdata) | |
177 | text = self.tc.GetValue() | |
178 | printout1 = TextDocPrintout(text, "title", self.margins) | |
179 | printout2 = None #TextDocPrintout(text, "title", self.margins) | |
180 | preview = wx.PrintPreview(printout1, printout2, data) | |
181 | if not preview.Ok(): | |
182 | wx.MessageBox("Unable to create PrintPreview!", "Error") | |
183 | else: | |
184 | # create the preview frame such that it overlays the app frame | |
185 | frame = wx.PreviewFrame(preview, self, "Print Preview", | |
186 | pos=self.GetPosition(), | |
187 | size=self.GetSize()) | |
188 | frame.Initialize() | |
189 | frame.Show() | |
190 | ||
191 | ||
192 | def OnPrint(self, evt): | |
193 | data = wx.PrintDialogData(self.pdata) | |
194 | printer = wx.Printer(data) | |
195 | text = self.tc.GetValue() | |
196 | printout = TextDocPrintout(text, "title", self.margins) | |
197 | useSetupDialog = True | |
198 | if not printer.Print(self, printout, useSetupDialog) \ | |
199 | and printer.GetLastError() == wx.PRINTER_ERROR: | |
200 | wx.MessageBox( | |
201 | "There was a problem printing.\n" | |
202 | "Perhaps your current printer is not set correctly?", | |
203 | "Printing Error", wx.OK) | |
204 | else: | |
205 | data = printer.GetPrintDialogData() | |
206 | self.pdata = wx.PrintData(data.GetPrintData()) # force a copy | |
207 | printout.Destroy() | |
208 | ||
209 | ||
210 | def OnPrintTest(self, evt): | |
211 | data = wx.PrintDialogData(self.pdata) | |
212 | dlg = wx.PrintDialog(self, data) | |
213 | if dlg.ShowModal() == wx.ID_OK: | |
214 | data = dlg.GetPrintDialogData() | |
215 | ||
216 | print "GetFromPage:", data.GetFromPage() | |
217 | print "GetToPage:", data.GetToPage() | |
218 | print "GetMinPage:", data.GetMinPage() | |
219 | print "GetMaxPage:", data.GetMaxPage() | |
220 | print "GetNoCopies:", data.GetNoCopies() | |
221 | print "GetAllPages:", data.GetAllPages() | |
222 | print "GetSelection:", data.GetSelection() | |
223 | print "GetCollate:", data.GetCollate() | |
224 | print "GetPrintToFile:", data.GetPrintToFile() | |
225 | ||
226 | self.pdata = wx.PrintData(data.GetPrintData()) | |
227 | ||
228 | print "GetPrinterName:", self.pdata.GetPrinterName() | |
229 | ||
230 | dlg.Destroy() | |
231 | ||
232 | ||
233 | app = wx.PySimpleApp() | |
234 | frm = PrintFrameworkSample() | |
235 | frm.Show() | |
236 | app.MainLoop() |