]> git.saurik.com Git - wxWidgets.git/blame - samples/printing/printing.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / samples / printing / printing.cpp
CommitLineData
6adaedf0 1/////////////////////////////////////////////////////////////////////////////
f415cab9 2// Name: samples/printing.cpp
be5a51fb 3// Purpose: Printing demo for wxWidgets
6adaedf0 4// Author: Julian Smart
48ed4a89 5// Modified by: Francesco Montorsi
6adaedf0 6// Created: 1995
6adaedf0
JS
7// Copyright: (c) Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
c801d85f 10
c801d85f
KB
11// For compilers that support precompilation, includes "wx/wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
48ed4a89 15 #pragma hdrstop
c801d85f
KB
16#endif
17
18#ifndef WX_PRECOMP
48ed4a89
FM
19 #include "wx/wx.h"
20 #include "wx/log.h"
c801d85f
KB
21#endif
22
e4b19d9b 23#if !wxUSE_PRINTING_ARCHITECTURE
48ed4a89 24 #error "You must set wxUSE_PRINTING_ARCHITECTURE to 1 in setup.h, and recompile the library."
c801d85f
KB
25#endif
26
27#include <ctype.h>
28#include "wx/metafile.h"
29#include "wx/print.h"
30#include "wx/printdlg.h"
cac7ac30 31#include "wx/image.h"
031b2a7b
RR
32#include "wx/accel.h"
33
ccb2be5b 34#if wxUSE_POSTSCRIPT
48ed4a89
FM
35 #include "wx/generic/printps.h"
36 #include "wx/generic/prntdlgg.h"
dfad0599 37#endif
c801d85f 38
7e38ae60 39#if wxUSE_GRAPHICS_CONTEXT
48ed4a89 40 #include "wx/graphics.h"
7e38ae60
RR
41#endif
42
f415cab9 43#ifdef __WXMAC__
5f05e514 44 #include "wx/osx/printdlg.h"
f415cab9
JS
45#endif
46
c801d85f
KB
47#include "printing.h"
48
e7092398 49#ifndef wxHAS_IMAGES_IN_RESOURCES
3cb332c1 50 #include "../sample.xpm"
4bc67cc5
RR
51#endif
52
7bcb11d3 53// Global print data, to remember settings during the session
48ed4a89 54wxPrintData *g_printData = NULL;
7bcb11d3
JS
55
56// Global page setup data
48ed4a89 57wxPageSetupDialogData* g_pageSetupData = NULL;
c801d85f 58
c801d85f 59
c801d85f 60
48ed4a89
FM
61// ----------------------------------------------------------------------------
62// MyApp
63// ----------------------------------------------------------------------------
64
65IMPLEMENT_APP(MyApp)
7b25d8e7 66
c801d85f
KB
67bool MyApp::OnInit(void)
68{
45e6e6f8
VZ
69 if ( !wxApp::OnInit() )
70 return false;
71
cac7ac30
RR
72 wxInitAllImageHandlers();
73
48ed4a89
FM
74
75 // init global objects
76 // -------------------
9134af5b 77
7bcb11d3 78 g_printData = new wxPrintData;
48ed4a89 79
d5eaa19f 80 // You could set an initial paper size here
48ed4a89
FM
81#if 0
82 g_printData->SetPaperId(wxPAPER_LETTER); // for Americans
83 g_printData->SetPaperId(wxPAPER_A4); // for everyone else
84#endif
f415cab9 85
7bcb11d3 86 g_pageSetupData = new wxPageSetupDialogData;
48ed4a89 87
f415cab9
JS
88 // copy over initial paper size from print record
89 (*g_pageSetupData) = *g_printData;
48ed4a89
FM
90
91 // Set some initial page margins in mm.
f415cab9
JS
92 g_pageSetupData->SetMarginTopLeft(wxPoint(15, 15));
93 g_pageSetupData->SetMarginBottomRight(wxPoint(15, 15));
9134af5b 94
48ed4a89
FM
95
96 // init local GUI objects
97 // ----------------------
98
99#if 0
100 wxImage image( wxT("test.jpg") );
101 image.SetAlpha();
102 int i,j;
103 for (i = 0; i < image.GetWidth(); i++)
104 for (j = 0; j < image.GetHeight(); j++)
105 image.SetAlpha( i, j, 50 );
106 m_bitmap = image;
107#endif
108 m_angle = 30;
109 m_testFont.Create(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
110
111
7bcb11d3 112 // Create the main frame window
48ed4a89
FM
113 // ----------------------------
114
9a83f860 115 MyFrame* frame = new MyFrame((wxFrame *) NULL, wxT("wxWidgets Printing Demo"),
48ed4a89
FM
116 wxPoint(0, 0), wxSize(400, 400));
117
118 frame->Centre(wxBOTH);
119 frame->Show();
120
48ed4a89
FM
121 return true;
122}
123
124int MyApp::OnExit()
125{
126 delete g_printData;
127 delete g_pageSetupData;
128
129 return wxApp::OnExit();
130}
131
132void MyApp::Draw(wxDC&dc)
133{
134 // This routine just draws a bunch of random stuff on the screen so that we
135 // can check that different types of object are being drawn consistently
136 // between the screen image, the print preview image (at various zoom
137 // levels), and the printed page.
138 dc.SetBackground(*wxWHITE_BRUSH);
139 // dc.Clear();
140 dc.SetFont(m_testFont);
141
142 // dc.SetBackgroundMode(wxTRANSPARENT);
143
144 dc.SetPen(*wxBLACK_PEN);
145 dc.SetBrush(*wxLIGHT_GREY_BRUSH);
146
147 dc.DrawRectangle(0, 0, 230, 350);
148 dc.DrawLine(0, 0, 229, 349);
149 dc.DrawLine(229, 0, 0, 349);
150 dc.SetBrush(*wxTRANSPARENT_BRUSH);
151
152 dc.SetBrush(*wxCYAN_BRUSH);
153 dc.SetPen(*wxRED_PEN);
154
155 dc.DrawRoundedRectangle(0, 20, 200, 80, 20);
156
157 dc.DrawText( wxT("Rectangle 200 by 80"), 40, 40);
158
0856cb25 159 dc.SetPen( wxPen(*wxBLACK, 0, wxPENSTYLE_DOT_DASH) );
48ed4a89
FM
160 dc.DrawEllipse(50, 140, 100, 50);
161 dc.SetPen(*wxRED_PEN);
162
163 dc.DrawText( wxT("Test message: this is in 10 point text"), 10, 180);
164
165#if wxUSE_UNICODE
166 const char *test = "Hebrew שלום -- Japanese (日本語)";
167 wxString tmp = wxConvUTF8.cMB2WC( test );
168 dc.DrawText( tmp, 10, 200 );
169#endif
170
171 wxPoint points[5];
172 points[0].x = 0;
173 points[0].y = 0;
174 points[1].x = 20;
175 points[1].y = 0;
176 points[2].x = 20;
177 points[2].y = 20;
178 points[3].x = 10;
179 points[3].y = 20;
180 points[4].x = 10;
181 points[4].y = -20;
182 dc.DrawPolygon( 5, points, 20, 250, wxODDEVEN_RULE );
183 dc.DrawPolygon( 5, points, 50, 250, wxWINDING_RULE );
184
185 dc.DrawEllipticArc( 80, 250, 60, 30, 0.0, 270.0 );
186
187 points[0].x = 150;
188 points[0].y = 250;
189 points[1].x = 180;
190 points[1].y = 250;
191 points[2].x = 180;
192 points[2].y = 220;
193 points[3].x = 200;
194 points[3].y = 220;
195 dc.DrawSpline( 4, points );
196
197 dc.DrawArc( 20,10, 10,10, 25,40 );
198
199 wxString str;
200 int i = 0;
201 str.Printf( wxT("---- Text at angle %d ----"), i );
202 dc.DrawRotatedText( str, 100, 300, i );
203
204 i = m_angle;
205 str.Printf( wxT("---- Text at angle %d ----"), i );
206 dc.DrawRotatedText( str, 100, 300, i );
207
3cb332c1 208 wxIcon my_icon = wxICON(sample);
48ed4a89
FM
209
210 dc.DrawIcon( my_icon, 100, 100);
211
212 if (m_bitmap.IsOk())
213 dc.DrawBitmap( m_bitmap, 10, 10 );
214
215#if wxUSE_GRAPHICS_CONTEXT
216 wxGraphicsContext *gc = NULL;
217
218 wxPrinterDC *printer_dc = wxDynamicCast( &dc, wxPrinterDC );
219 if (printer_dc)
220 gc = wxGraphicsContext::Create( *printer_dc );
221
222 wxWindowDC *window_dc = wxDynamicCast( &dc, wxWindowDC );
223 if (window_dc)
224 gc = wxGraphicsContext::Create( *window_dc );
225
8371a353
JS
226#ifdef __WXMSW__
227 wxEnhMetaFileDC *emf_dc = wxDynamicCast( &dc, wxEnhMetaFileDC );
228 if (emf_dc)
229 gc = wxGraphicsContext::Create( *emf_dc );
230#endif
231
48ed4a89
FM
232 if (gc)
233 {
234 // make a path that contains a circle and some lines, centered at 100,100
235 gc->SetPen( *wxRED_PEN );
a5e40d85 236
48ed4a89
FM
237 wxGraphicsPath path = gc->CreatePath();
238 path.AddCircle( 50.0, 50.0, 50.0 );
239 path.MoveToPoint(0.0, 50.0);
240 path.AddLineToPoint(100.0, 50.0);
241 path.MoveToPoint(50.0, 0.0);
242 path.AddLineToPoint(50.0, 100.0 );
243 path.CloseSubpath();
244 path.AddRectangle(25.0, 25.0, 50.0, 50.0);
245
246 gc->StrokePath(path);
247
a5e40d85 248 // draw some text
a29df062 249 wxString text("Text by wxGraphicsContext");
17c02cc8
JS
250 gc->SetFont( m_testFont, *wxBLACK );
251 gc->DrawText(text, 25.0, 60.0);
a5e40d85
JS
252
253 // draw rectangle around the text
254 double w, h, d, el;
255 gc->GetTextExtent(text, &w, &h, &d, &el);
17c02cc8
JS
256 gc->SetPen( *wxBLACK_PEN );
257 gc->DrawRectangle(25.0, 60.0, w, h);
a5e40d85 258
48ed4a89
FM
259 delete gc;
260 }
261#endif
262}
263
264
265// ----------------------------------------------------------------------------
266// MyFrame
267// ----------------------------------------------------------------------------
268
269BEGIN_EVENT_TABLE(MyFrame, wxFrame)
270 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
271 EVT_MENU(wxID_PRINT, MyFrame::OnPrint)
272 EVT_MENU(wxID_PREVIEW, MyFrame::OnPrintPreview)
273 EVT_MENU(WXPRINT_PAGE_SETUP, MyFrame::OnPageSetup)
274 EVT_MENU(wxID_ABOUT, MyFrame::OnPrintAbout)
ccb2be5b 275#if wxUSE_POSTSCRIPT
48ed4a89
FM
276 EVT_MENU(WXPRINT_PRINT_PS, MyFrame::OnPrintPS)
277 EVT_MENU(WXPRINT_PREVIEW_PS, MyFrame::OnPrintPreviewPS)
278 EVT_MENU(WXPRINT_PAGE_SETUP_PS, MyFrame::OnPageSetupPS)
279#endif
280#ifdef __WXMAC__
281 EVT_MENU(WXPRINT_PAGE_MARGINS, MyFrame::OnPageMargins)
282#endif
283 EVT_MENU(WXPRINT_ANGLEUP, MyFrame::OnAngleUp)
284 EVT_MENU(WXPRINT_ANGLEDOWN, MyFrame::OnAngleDown)
6aacfc73
VZ
285
286 EVT_MENU_RANGE(WXPRINT_FRAME_MODAL_APP,
287 WXPRINT_FRAME_MODAL_NON,
288 MyFrame::OnPreviewFrameModalityKind)
48ed4a89
FM
289END_EVENT_TABLE()
290
291MyFrame::MyFrame(wxFrame *frame, const wxString&title, const wxPoint&pos, const wxSize&size)
292 : wxFrame(frame, wxID_ANY, title, pos, size)
293{
294 m_canvas = NULL;
6aacfc73 295 m_previewModality = wxPreviewFrame_AppModal;
9134af5b 296
8520f137 297#if wxUSE_STATUSBAR
48ed4a89
FM
298 // Give us a status line
299 CreateStatusBar(2);
9a83f860 300 SetStatusText(wxT("Printing demo"));
8520f137 301#endif // wxUSE_STATUSBAR
9134af5b 302
7bcb11d3 303 // Load icon and bitmap
3cb332c1 304 SetIcon( wxICON( sample) );
9134af5b 305
7bcb11d3
JS
306 // Make a menubar
307 wxMenu *file_menu = new wxMenu;
9134af5b 308
9a83f860
VZ
309 file_menu->Append(wxID_PRINT, wxT("&Print..."), wxT("Print"));
310 file_menu->Append(WXPRINT_PAGE_SETUP, wxT("Page Set&up..."), wxT("Page setup"));
f415cab9 311#ifdef __WXMAC__
9a83f860 312 file_menu->Append(WXPRINT_PAGE_MARGINS, wxT("Page Margins..."), wxT("Page margins"));
f415cab9 313#endif
9a83f860 314 file_menu->Append(wxID_PREVIEW, wxT("Print Pre&view"), wxT("Preview"));
9134af5b 315
6aacfc73
VZ
316 wxMenu * const menuModalKind = new wxMenu;
317 menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_APP, "&App modal");
318 menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_WIN, "&Window modal");
319 menuModalKind->AppendRadioItem(WXPRINT_FRAME_MODAL_NON, "&Not modal");
320 file_menu->AppendSubMenu(menuModalKind, "Preview frame &modal kind");
3d2d8da1 321#if wxUSE_ACCEL
031b2a7b
RR
322 // Accelerators
323 wxAcceleratorEntry entries[1];
48ed4a89 324 entries[0].Set(wxACCEL_CTRL, (int) 'V', wxID_PREVIEW);
031b2a7b 325 wxAcceleratorTable accel(1, entries);
48ed4a89 326 SetAcceleratorTable(accel);
3d2d8da1
RR
327#endif
328
ccb2be5b 329#if wxUSE_POSTSCRIPT
7bcb11d3 330 file_menu->AppendSeparator();
9a83f860
VZ
331 file_menu->Append(WXPRINT_PRINT_PS, wxT("Print PostScript..."), wxT("Print (PostScript)"));
332 file_menu->Append(WXPRINT_PAGE_SETUP_PS, wxT("Page Setup PostScript..."), wxT("Page setup (PostScript)"));
333 file_menu->Append(WXPRINT_PREVIEW_PS, wxT("Print Preview PostScript"), wxT("Preview (PostScript)"));
c801d85f 334#endif
f415cab9 335
cac7ac30 336 file_menu->AppendSeparator();
9a83f860
VZ
337 file_menu->Append(WXPRINT_ANGLEUP, wxT("Angle up\tAlt-U"), wxT("Raise rotated text angle"));
338 file_menu->Append(WXPRINT_ANGLEDOWN, wxT("Angle down\tAlt-D"), wxT("Lower rotated text angle"));
7bcb11d3 339 file_menu->AppendSeparator();
9a83f860 340 file_menu->Append(wxID_EXIT, wxT("E&xit"), wxT("Exit program"));
9134af5b 341
7bcb11d3 342 wxMenu *help_menu = new wxMenu;
9a83f860 343 help_menu->Append(wxID_ABOUT, wxT("&About"), wxT("About this demo"));
9134af5b 344
7bcb11d3 345 wxMenuBar *menu_bar = new wxMenuBar;
9134af5b 346
9a83f860
VZ
347 menu_bar->Append(file_menu, wxT("&File"));
348 menu_bar->Append(help_menu, wxT("&Help"));
9134af5b 349
7bcb11d3 350 // Associate the menu bar with the frame
48ed4a89 351 SetMenuBar(menu_bar);
9134af5b 352
c801d85f 353
48ed4a89
FM
354 // create the canvas
355 // -----------------
e3065973 356
48ed4a89
FM
357 m_canvas = new MyCanvas(this, wxPoint(0, 0), wxSize(100, 100),
358 wxRETAINED|wxHSCROLL|wxVSCROLL);
c801d85f 359
48ed4a89
FM
360 // Give it scrollbars: the virtual canvas is 20 * 50 = 1000 pixels in each direction
361 m_canvas->SetScrollbars(20, 20, 50, 50);
c801d85f
KB
362}
363
e3e65dac 364void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
c801d85f 365{
9134af5b 366 Close(true /*force closing*/);
c801d85f
KB
367}
368
e3e65dac 369void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
c801d85f 370{
7bcb11d3
JS
371 wxPrintDialogData printDialogData(* g_printData);
372
48ed4a89 373 wxPrinter printer(&printDialogData);
9a83f860 374 MyPrintout printout(this, wxT("My printout"));
9134af5b 375 if (!printer.Print(this, &printout, true /*prompt*/))
f6bcfd97
BP
376 {
377 if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
43b2d5e7 378 {
9a83f860 379 wxLogError(wxT("There was a problem printing. Perhaps your current printer is not set correctly?"));
43b2d5e7 380 }
f6bcfd97 381 else
43b2d5e7 382 {
9a83f860 383 wxLogMessage(wxT("You canceled printing"));
43b2d5e7 384 }
f6bcfd97 385 }
7bcb11d3
JS
386 else
387 {
388 (*g_printData) = printer.GetPrintDialogData().GetPrintData();
389 }
c801d85f
KB
390}
391
e3e65dac 392void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event))
c801d85f 393{
7bcb11d3
JS
394 // Pass two printout objects: for preview, and possible printing.
395 wxPrintDialogData printDialogData(* g_printData);
48ed4a89
FM
396 wxPrintPreview *preview =
397 new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData);
398 if (!preview->IsOk())
7bcb11d3 399 {
c801d85f 400 delete preview;
9a83f860 401 wxLogError(wxT("There was a problem previewing.\nPerhaps your current printer is not set correctly?"));
c801d85f 402 return;
7bcb11d3 403 }
9134af5b 404
48ed4a89 405 wxPreviewFrame *frame =
9a83f860 406 new wxPreviewFrame(preview, this, wxT("Demo Print Preview"), wxPoint(100, 100), wxSize(600, 650));
7bcb11d3 407 frame->Centre(wxBOTH);
5d4c2aca 408 frame->InitializeWithModality(m_previewModality);
9134af5b 409 frame->Show();
c801d85f
KB
410}
411
e3e65dac 412void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
c801d85f 413{
cac7ac30 414 (*g_pageSetupData) = *g_printData;
c801d85f 415
7bcb11d3
JS
416 wxPageSetupDialog pageSetupDialog(this, g_pageSetupData);
417 pageSetupDialog.ShowModal();
9134af5b 418
f415cab9
JS
419 (*g_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
420 (*g_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
c801d85f
KB
421}
422
ccb2be5b 423#if wxUSE_POSTSCRIPT
dfad0599
JS
424void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event))
425{
ccb2be5b
VZ
426 wxPrintDialogData printDialogData(* g_printData);
427
428 wxPostScriptPrinter printer(&printDialogData);
429 MyPrintout printout(this, wxT("My printout"));
9134af5b 430 printer.Print(this, &printout, true/*prompt*/);
7bcb11d3 431
ccb2be5b 432 (*g_printData) = printer.GetPrintDialogData().GetPrintData();
dfad0599
JS
433}
434
435void MyFrame::OnPrintPreviewPS(wxCommandEvent& WXUNUSED(event))
436{
7bcb11d3
JS
437 // Pass two printout objects: for preview, and possible printing.
438 wxPrintDialogData printDialogData(* g_printData);
ccb2be5b 439 wxPrintPreview *preview = new wxPrintPreview(new MyPrintout(this), new MyPrintout(this), &printDialogData);
48ed4a89 440 wxPreviewFrame *frame =
9a83f860 441 new wxPreviewFrame(preview, this, wxT("Demo Print Preview"), wxPoint(100, 100), wxSize(600, 650));
7bcb11d3
JS
442 frame->Centre(wxBOTH);
443 frame->Initialize();
9134af5b 444 frame->Show();
dfad0599
JS
445}
446
e3e65dac 447void MyFrame::OnPageSetupPS(wxCommandEvent& WXUNUSED(event))
c801d85f 448{
7bcb11d3 449 (*g_pageSetupData) = * g_printData;
c801d85f 450
7bcb11d3
JS
451 wxGenericPageSetupDialog pageSetupDialog(this, g_pageSetupData);
452 pageSetupDialog.ShowModal();
c801d85f 453
f415cab9
JS
454 (*g_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData();
455 (*g_pageSetupData) = pageSetupDialog.GetPageSetupDialogData();
456}
457#endif
458
f415cab9
JS
459#ifdef __WXMAC__
460void MyFrame::OnPageMargins(wxCommandEvent& WXUNUSED(event))
461{
462 (*g_pageSetupData) = *g_printData;
463
464 wxMacPageMarginsDialog pageMarginsDialog(this, g_pageSetupData);
465 pageMarginsDialog.ShowModal();
466
467 (*g_printData) = pageMarginsDialog.GetPageSetupDialogData().GetPrintData();
468 (*g_pageSetupData) = pageMarginsDialog.GetPageSetupDialogData();
c801d85f 469}
dfad0599
JS
470#endif
471
e3e65dac 472void MyFrame::OnPrintAbout(wxCommandEvent& WXUNUSED(event))
c801d85f 473{
9a83f860
VZ
474 (void)wxMessageBox(wxT("wxWidgets printing demo\nAuthor: Julian Smart"),
475 wxT("About wxWidgets printing demo"), wxOK|wxCENTRE);
c801d85f
KB
476}
477
abc2a4cc 478void MyFrame::OnAngleUp(wxCommandEvent& WXUNUSED(event))
cac7ac30 479{
48ed4a89
FM
480 wxGetApp().IncrementAngle();
481 m_canvas->Refresh();
cac7ac30
RR
482}
483
abc2a4cc 484void MyFrame::OnAngleDown(wxCommandEvent& WXUNUSED(event))
cac7ac30 485{
48ed4a89
FM
486 wxGetApp().DecrementAngle();
487 m_canvas->Refresh();
cac7ac30
RR
488}
489
6aacfc73
VZ
490void MyFrame::OnPreviewFrameModalityKind(wxCommandEvent& event)
491{
492 m_previewModality = static_cast<wxPreviewFrameModalityKind>(
493 wxPreviewFrame_AppModal +
494 (event.GetId() - WXPRINT_FRAME_MODAL_APP));
495}
c801d85f 496
48ed4a89
FM
497// ----------------------------------------------------------------------------
498// MyCanvas
499// ----------------------------------------------------------------------------
c801d85f
KB
500
501BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
48ed4a89 502 // EVT_PAINT(MyCanvas::OnPaint)
c801d85f
KB
503END_EVENT_TABLE()
504
48ed4a89
FM
505MyCanvas::MyCanvas(wxFrame *frame, const wxPoint&pos, const wxSize&size, long style)
506 : wxScrolledWindow(frame, wxID_ANY, pos, size, style)
c801d85f 507{
48ed4a89 508 SetBackgroundColour(*wxWHITE);
c801d85f
KB
509}
510
48ed4a89 511//void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(evt))
c801d85f
KB
512void MyCanvas::OnDraw(wxDC& dc)
513{
48ed4a89
FM
514 //wxPaintDC dc(this);
515 wxGetApp().Draw(dc);
c801d85f
KB
516}
517
48ed4a89
FM
518
519// ----------------------------------------------------------------------------
520// MyPrintout
521// ----------------------------------------------------------------------------
c801d85f 522
c801d85f
KB
523bool MyPrintout::OnPrintPage(int page)
524{
7bcb11d3
JS
525 wxDC *dc = GetDC();
526 if (dc)
527 {
528 if (page == 1)
f415cab9 529 DrawPageOne();
7bcb11d3 530 else if (page == 2)
f415cab9 531 DrawPageTwo();
9134af5b 532
f415cab9
JS
533 // Draw page numbers at top left corner of printable area, sized so that
534 // screen size of text matches paper size.
535 MapScreenSizeToPage();
48ed4a89
FM
536
537 dc->DrawText(wxString::Format(wxT("PAGE %d"), page), 0, 0);
9134af5b
DS
538
539 return true;
7bcb11d3
JS
540 }
541 else
9134af5b 542 return false;
c801d85f
KB
543}
544
545bool MyPrintout::OnBeginDocument(int startPage, int endPage)
546{
7bcb11d3 547 if (!wxPrintout::OnBeginDocument(startPage, endPage))
9134af5b
DS
548 return false;
549
550 return true;
c801d85f
KB
551}
552
553void MyPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
554{
7bcb11d3
JS
555 *minPage = 1;
556 *maxPage = 2;
557 *selPageFrom = 1;
558 *selPageTo = 2;
c801d85f
KB
559}
560
561bool MyPrintout::HasPage(int pageNum)
562{
7bcb11d3 563 return (pageNum == 1 || pageNum == 2);
c801d85f
KB
564}
565
f415cab9 566void MyPrintout::DrawPageOne()
c801d85f 567{
f415cab9
JS
568 // You might use THIS code if you were scaling graphics of known size to fit
569 // on the page. The commented-out code illustrates different ways of scaling
570 // the graphics.
571
572 // We know the graphic is 230x350. If we didn't know this, we'd need to
573 // calculate it.
574 wxCoord maxX = 230;
575 wxCoord maxY = 350;
576
577 // This sets the user scale and origin of the DC so that the image fits
578 // within the paper rectangle (but the edges could be cut off by printers
579 // that can't print to the edges of the paper -- which is most of them. Use
580 // this if your image already has its own margins.
581// FitThisSizeToPaper(wxSize(maxX, maxY));
582// wxRect fitRect = GetLogicalPaperRect();
583
584 // This sets the user scale and origin of the DC so that the image fits
585 // within the page rectangle, which is the printable area on Mac and MSW
586 // and is the entire page on other platforms.
587// FitThisSizeToPage(wxSize(maxX, maxY));
588// wxRect fitRect = GetLogicalPageRect();
589
590 // This sets the user scale and origin of the DC so that the image fits
591 // within the page margins as specified by g_PageSetupData, which you can
592 // change (on some platforms, at least) in the Page Setup dialog. Note that
593 // on Mac, the native Page Setup dialog doesn't let you change the margins
594 // of a wxPageSetupDialogData object, so you'll have to write your own dialog or
595 // use the Mac-only wxMacPageMarginsDialog, as we do in this program.
596 FitThisSizeToPageMargins(wxSize(maxX, maxY), *g_pageSetupData);
597 wxRect fitRect = GetLogicalPageMarginsRect(*g_pageSetupData);
598
599 // This sets the user scale and origin of the DC so that the image appears
600 // on the paper at the same size that it appears on screen (i.e., 10-point
601 // type on screen is 10-point on the printed page) and is positioned in the
602 // top left corner of the page rectangle (just as the screen image appears
603 // in the top left corner of the window).
604// MapScreenSizeToPage();
605// wxRect fitRect = GetLogicalPageRect();
606
607 // You could also map the screen image to the entire paper at the same size
608 // as it appears on screen.
609// MapScreenSizeToPaper();
610// wxRect fitRect = GetLogicalPaperRect();
611
612 // You might also wish to do you own scaling in order to draw objects at
613 // full native device resolution. In this case, you should do the following.
614 // Note that you can use the GetLogicalXXXRect() commands to obtain the
615 // appropriate rect to scale to.
616// MapScreenSizeToDevice();
617// wxRect fitRect = GetLogicalPageRect();
618
619 // Each of the preceding Fit or Map routines positions the origin so that
620 // the drawn image is positioned at the top left corner of the reference
621 // rectangle. You can easily center or right- or bottom-justify the image as
622 // follows.
623
624 // This offsets the image so that it is centered within the reference
625 // rectangle defined above.
626 wxCoord xoff = (fitRect.width - maxX) / 2;
627 wxCoord yoff = (fitRect.height - maxY) / 2;
628 OffsetLogicalOrigin(xoff, yoff);
629
630 // This offsets the image so that it is positioned at the bottom right of
631 // the reference rectangle defined above.
632// wxCoord xoff = (fitRect.width - maxX);
633// wxCoord yoff = (fitRect.height - maxY);
634// OffsetLogicalOrigin(xoff, yoff);
635
48ed4a89 636 wxGetApp().Draw(*GetDC());
c801d85f
KB
637}
638
f415cab9 639void MyPrintout::DrawPageTwo()
c801d85f 640{
77efa6a8
RR
641 // You might use THIS code to set the printer DC to ROUGHLY reflect
642 // the screen text size. This page also draws lines of actual length
643 // 5cm on the page.
9134af5b 644
f415cab9
JS
645 // Compare this to DrawPageOne(), which uses the really convenient routines
646 // from wxPrintout to fit the screen image onto the printed page. This page
647 // illustrates how to do all the scaling calculations yourself, if you're so
648 // inclined.
649
650 wxDC *dc = GetDC();
651
7bcb11d3
JS
652 // Get the logical pixels per inch of screen and printer
653 int ppiScreenX, ppiScreenY;
654 GetPPIScreen(&ppiScreenX, &ppiScreenY);
655 int ppiPrinterX, ppiPrinterY;
656 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
9134af5b 657
4c51a665 658 // This scales the DC so that the printout roughly represents the screen
f415cab9
JS
659 // scaling. The text point size _should_ be the right size but in fact is
660 // too small for some reason. This is a detail that will need to be
661 // addressed at some point but can be fudged for the moment.
7bcb11d3 662 float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
9134af5b 663
f415cab9
JS
664 // Now we have to check in case our real page size is reduced (e.g. because
665 // we're drawing to a print preview memory DC)
7bcb11d3
JS
666 int pageWidth, pageHeight;
667 int w, h;
668 dc->GetSize(&w, &h);
669 GetPageSizePixels(&pageWidth, &pageHeight);
9134af5b 670
f415cab9
JS
671 // If printer pageWidth == current DC width, then this doesn't change. But w
672 // might be the preview bitmap width, so scale down.
7bcb11d3
JS
673 float overallScale = scale * (float)(w/(float)pageWidth);
674 dc->SetUserScale(overallScale, overallScale);
9134af5b 675
f415cab9
JS
676 // Calculate conversion factor for converting millimetres into logical
677 // units. There are approx. 25.4 mm to the inch. There are ppi device units
678 // to the inch. Therefore 1 mm corresponds to ppi/25.4 device units. We also
679 // divide by the screen-to-printer scaling factor, because we need to
7bcb11d3 680 // unscale to pass logical units to DrawLine.
9134af5b 681
7bcb11d3 682 // Draw 50 mm by 50 mm L shape
70949ed5 683 float logUnitsFactor = (float)(ppiPrinterX/(scale*25.4));
7bcb11d3
JS
684 float logUnits = (float)(50*logUnitsFactor);
685 dc->SetPen(* wxBLACK_PEN);
686 dc->DrawLine(50, 250, (long)(50.0 + logUnits), 250);
687 dc->DrawLine(50, 250, 50, (long)(250.0 + logUnits));
9134af5b 688
7bcb11d3 689 dc->SetBackgroundMode(wxTRANSPARENT);
1db4e8dd 690 dc->SetBrush(*wxTRANSPARENT_BRUSH);
9134af5b 691
d57bf685 692 { // GetTextExtent demo:
9a83f860
VZ
693 wxString words[7] = { wxT("This "), wxT("is "), wxT("GetTextExtent "),
694 wxT("testing "), wxT("string. "), wxT("Enjoy "), wxT("it!") };
6f207e66 695 wxCoord w, h;
d57bf685
VS
696 long x = 200, y= 250;
697 wxFont fnt(15, wxSWISS, wxNORMAL, wxNORMAL);
9134af5b 698
d57bf685 699 dc->SetFont(fnt);
9134af5b 700
77efa6a8
RR
701 for (int i = 0; i < 7; i++)
702 {
703 wxString word = words[i];
704 word.Remove( word.Len()-1, 1 );
705 dc->GetTextExtent(word, &w, &h);
d57bf685 706 dc->DrawRectangle(x, y, w, h);
77efa6a8 707 dc->GetTextExtent(words[i], &w, &h);
d57bf685
VS
708 dc->DrawText(words[i], x, y);
709 x += w;
710 }
9134af5b 711
d57bf685 712 }
9134af5b 713
48ed4a89 714 dc->SetFont(wxGetApp().GetTestFont());
9134af5b 715
9a83f860 716 dc->DrawText(wxT("Some test text"), 200, 300 );
92980e90 717
7bcb11d3 718 // TESTING
9134af5b 719
7bcb11d3
JS
720 int leftMargin = 20;
721 int rightMargin = 20;
722 int topMargin = 20;
723 int bottomMargin = 20;
9134af5b 724
7bcb11d3
JS
725 int pageWidthMM, pageHeightMM;
726 GetPageSizeMM(&pageWidthMM, &pageHeightMM);
9134af5b 727
7bcb11d3
JS
728 float leftMarginLogical = (float)(logUnitsFactor*leftMargin);
729 float topMarginLogical = (float)(logUnitsFactor*topMargin);
730 float bottomMarginLogical = (float)(logUnitsFactor*(pageHeightMM - bottomMargin));
731 float rightMarginLogical = (float)(logUnitsFactor*(pageWidthMM - rightMargin));
9134af5b 732
7bcb11d3 733 dc->SetPen(* wxRED_PEN);
9134af5b 734 dc->DrawLine( (long)leftMarginLogical, (long)topMarginLogical,
7bcb11d3 735 (long)rightMarginLogical, (long)topMarginLogical);
9134af5b 736 dc->DrawLine( (long)leftMarginLogical, (long)bottomMarginLogical,
7bcb11d3 737 (long)rightMarginLogical, (long)bottomMarginLogical);
9134af5b 738
9a83f860 739 WritePageHeader(this, dc, wxT("A header"), logUnitsFactor);
c801d85f
KB
740}
741
742// Writes a header on a page. Margin units are in millimetres.
48ed4a89 743bool MyPrintout::WritePageHeader(wxPrintout *printout, wxDC *dc, const wxString&text, float mmToLogical)
c801d85f 744{
48ed4a89
FM
745#if 0
746 static wxFont *headerFont = (wxFont *) NULL;
747 if (!headerFont)
748 {
749 headerFont = wxTheFontList->FindOrCreateFont(16, wxSWISS, wxNORMAL, wxBOLD);
750 }
751 dc->SetFont(headerFont);
752#endif
9134af5b 753
7bcb11d3 754 int pageWidthMM, pageHeightMM;
9134af5b 755
7bcb11d3 756 printout->GetPageSizeMM(&pageWidthMM, &pageHeightMM);
8afa4fde 757 wxUnusedVar(pageHeightMM);
9134af5b 758
7bcb11d3
JS
759 int leftMargin = 10;
760 int topMargin = 10;
761 int rightMargin = 10;
9134af5b 762
7bcb11d3
JS
763 float leftMarginLogical = (float)(mmToLogical*leftMargin);
764 float topMarginLogical = (float)(mmToLogical*topMargin);
765 float rightMarginLogical = (float)(mmToLogical*(pageWidthMM - rightMargin));
9134af5b 766
6f207e66 767 wxCoord xExtent, yExtent;
7bcb11d3 768 dc->GetTextExtent(text, &xExtent, &yExtent);
48ed4a89 769
7bcb11d3
JS
770 float xPos = (float)(((((pageWidthMM - leftMargin - rightMargin)/2.0)+leftMargin)*mmToLogical) - (xExtent/2.0));
771 dc->DrawText(text, (long)xPos, (long)topMarginLogical);
9134af5b 772
7bcb11d3 773 dc->SetPen(* wxBLACK_PEN);
9134af5b 774 dc->DrawLine( (long)leftMarginLogical, (long)(topMarginLogical+yExtent),
48ed4a89 775 (long)rightMarginLogical, (long)topMarginLogical+yExtent );
9134af5b
DS
776
777 return true;
c801d85f 778}