]> git.saurik.com Git - wxWidgets.git/blob - src/common/prntbase.cpp
Allow wxThread::Wait() and Delete() to block, even under wxMSW.
[wxWidgets.git] / src / common / prntbase.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/prntbase.cpp
3 // Purpose: Printing framework base class implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_PRINTING_ARCHITECTURE
20
21 #include "wx/dcprint.h"
22
23 #ifndef WX_PRECOMP
24 #if defined(__WXMSW__)
25 #include "wx/msw/wrapcdlg.h"
26 #endif // MSW
27 #include "wx/utils.h"
28 #include "wx/dc.h"
29 #include "wx/app.h"
30 #include "wx/math.h"
31 #include "wx/msgdlg.h"
32 #include "wx/layout.h"
33 #include "wx/choice.h"
34 #include "wx/button.h"
35 #include "wx/bmpbuttn.h"
36 #include "wx/settings.h"
37 #include "wx/dcmemory.h"
38 #include "wx/dcclient.h"
39 #include "wx/stattext.h"
40 #include "wx/intl.h"
41 #include "wx/textdlg.h"
42 #include "wx/sizer.h"
43 #include "wx/module.h"
44 #endif // !WX_PRECOMP
45
46 #include "wx/prntbase.h"
47 #include "wx/printdlg.h"
48 #include "wx/print.h"
49 #include "wx/dcprint.h"
50 #include "wx/artprov.h"
51
52 #include <stdlib.h>
53 #include <string.h>
54
55 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
56 #include "wx/msw/printdlg.h"
57 #include "wx/msw/dcprint.h"
58 #elif defined(__WXMAC__)
59 #include "wx/osx/printdlg.h"
60 #include "wx/osx/private/print.h"
61 #include "wx/osx/dcprint.h"
62 #elif defined(__WXPM__)
63 #include "wx/os2/dcprint.h"
64 #include "wx/generic/prntdlgg.h"
65 #else
66 #include "wx/generic/prntdlgg.h"
67 #include "wx/dcps.h"
68 #endif
69
70 #ifdef __WXMSW__
71 #ifndef __WIN32__
72 #include <print.h>
73 #endif
74 #endif // __WXMSW__
75
76 //----------------------------------------------------------------------------
77 // wxPrintFactory
78 //----------------------------------------------------------------------------
79
80 wxPrintFactory *wxPrintFactory::m_factory = NULL;
81
82 void wxPrintFactory::SetPrintFactory( wxPrintFactory *factory )
83 {
84 if (wxPrintFactory::m_factory)
85 delete wxPrintFactory::m_factory;
86
87 wxPrintFactory::m_factory = factory;
88 }
89
90 wxPrintFactory *wxPrintFactory::GetFactory()
91 {
92 if (!wxPrintFactory::m_factory)
93 wxPrintFactory::m_factory = new wxNativePrintFactory;
94
95 return wxPrintFactory::m_factory;
96 }
97
98 //----------------------------------------------------------------------------
99 // wxNativePrintFactory
100 //----------------------------------------------------------------------------
101
102 wxPrinterBase *wxNativePrintFactory::CreatePrinter( wxPrintDialogData *data )
103 {
104 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
105 return new wxWindowsPrinter( data );
106 #elif defined(__WXMAC__)
107 return new wxMacPrinter( data );
108 #elif defined(__WXPM__)
109 return new wxOS2Printer( data );
110 #else
111 return new wxPostScriptPrinter( data );
112 #endif
113 }
114
115 wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
116 wxPrintout *printout, wxPrintDialogData *data )
117 {
118 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
119 return new wxWindowsPrintPreview( preview, printout, data );
120 #elif defined(__WXMAC__)
121 return new wxMacPrintPreview( preview, printout, data );
122 #elif defined(__WXPM__)
123 return new wxOS2PrintPreview( preview, printout, data );
124 #else
125 return new wxPostScriptPrintPreview( preview, printout, data );
126 #endif
127 }
128
129 wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
130 wxPrintout *printout, wxPrintData *data )
131 {
132 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
133 return new wxWindowsPrintPreview( preview, printout, data );
134 #elif defined(__WXMAC__)
135 return new wxMacPrintPreview( preview, printout, data );
136 #elif defined(__WXPM__)
137 return new wxOS2PrintPreview( preview, printout, data );
138 #else
139 return new wxPostScriptPrintPreview( preview, printout, data );
140 #endif
141 }
142
143 wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
144 wxPrintDialogData *data )
145 {
146 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
147 return new wxWindowsPrintDialog( parent, data );
148 #elif defined(__WXMAC__)
149 return new wxMacPrintDialog( parent, data );
150 #else
151 return new wxGenericPrintDialog( parent, data );
152 #endif
153 }
154
155 wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
156 wxPrintData *data )
157 {
158 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
159 return new wxWindowsPrintDialog( parent, data );
160 #elif defined(__WXMAC__)
161 return new wxMacPrintDialog( parent, data );
162 #else
163 return new wxGenericPrintDialog( parent, data );
164 #endif
165 }
166
167 wxPageSetupDialogBase *wxNativePrintFactory::CreatePageSetupDialog( wxWindow *parent,
168 wxPageSetupDialogData *data )
169 {
170 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
171 return new wxWindowsPageSetupDialog( parent, data );
172 #elif defined(__WXMAC__)
173 return new wxMacPageSetupDialog( parent, data );
174 #else
175 return new wxGenericPageSetupDialog( parent, data );
176 #endif
177 }
178
179 bool wxNativePrintFactory::HasPrintSetupDialog()
180 {
181 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
182 return false;
183 #elif defined(__WXMAC__)
184 return false;
185 #else
186 // Only here do we need to provide the print setup
187 // dialog ourselves, the other platforms either have
188 // none, don't make it accessible or let you configure
189 // the printer from the wxPrintDialog anyway.
190 return true;
191 #endif
192
193 }
194
195 wxDialog *wxNativePrintFactory::CreatePrintSetupDialog( wxWindow *parent,
196 wxPrintData *data )
197 {
198 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
199 wxUnusedVar(parent);
200 wxUnusedVar(data);
201 return NULL;
202 #elif defined(__WXMAC__)
203 wxUnusedVar(parent);
204 wxUnusedVar(data);
205 return NULL;
206 #else
207 // Only here do we need to provide the print setup
208 // dialog ourselves, the other platforms either have
209 // none, don't make it accessible or let you configure
210 // the printer from the wxPrintDialog anyway.
211 return new wxGenericPrintSetupDialog( parent, data );
212 #endif
213 }
214
215 wxDCImpl* wxNativePrintFactory::CreatePrinterDCImpl( wxPrinterDC *owner, const wxPrintData& data )
216 {
217 #if defined(__WXGTK__) || defined(__WXMOTIF__) || ( defined(__WXUNIVERSAL__) && !defined(__WXMAC__) )
218 return new wxPostScriptDCImpl( owner, data );
219 #else
220 return new wxPrinterDCImpl( owner, data );
221 #endif
222 }
223
224 bool wxNativePrintFactory::HasOwnPrintToFile()
225 {
226 // Only relevant for PostScript and here the
227 // setup dialog provides no "print to file"
228 // option. In the GNOME setup dialog, the
229 // setup dialog has its own print to file.
230 return false;
231 }
232
233 bool wxNativePrintFactory::HasPrinterLine()
234 {
235 // Only relevant for PostScript for now
236 return true;
237 }
238
239 wxString wxNativePrintFactory::CreatePrinterLine()
240 {
241 // Only relevant for PostScript for now
242
243 // We should query "lpstat -d" here
244 return _("Generic PostScript");
245 }
246
247 bool wxNativePrintFactory::HasStatusLine()
248 {
249 // Only relevant for PostScript for now
250 return true;
251 }
252
253 wxString wxNativePrintFactory::CreateStatusLine()
254 {
255 // Only relevant for PostScript for now
256
257 // We should query "lpstat -r" or "lpstat -p" here
258 return _("Ready");
259 }
260
261 wxPrintNativeDataBase *wxNativePrintFactory::CreatePrintNativeData()
262 {
263 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
264 return new wxWindowsPrintNativeData;
265 #elif defined(__WXMAC__)
266 return wxOSXCreatePrintData();
267 #else
268 return new wxPostScriptPrintNativeData;
269 #endif
270 }
271
272 //----------------------------------------------------------------------------
273 // wxPrintNativeDataBase
274 //----------------------------------------------------------------------------
275
276 IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase, wxObject)
277
278 wxPrintNativeDataBase::wxPrintNativeDataBase()
279 {
280 m_ref = 1;
281 }
282
283 //----------------------------------------------------------------------------
284 // wxPrintFactoryModule
285 //----------------------------------------------------------------------------
286
287 class wxPrintFactoryModule: public wxModule
288 {
289 public:
290 wxPrintFactoryModule() {}
291 bool OnInit() { return true; }
292 void OnExit() { wxPrintFactory::SetPrintFactory( NULL ); }
293
294 private:
295 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule)
296 };
297
298 IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule, wxModule)
299
300 //----------------------------------------------------------------------------
301 // wxPrinterBase
302 //----------------------------------------------------------------------------
303
304 IMPLEMENT_CLASS(wxPrinterBase, wxObject)
305
306 wxPrinterBase::wxPrinterBase(wxPrintDialogData *data)
307 {
308 m_currentPrintout = NULL;
309 sm_abortWindow = NULL;
310 sm_abortIt = false;
311 if (data)
312 m_printDialogData = (*data);
313 sm_lastError = wxPRINTER_NO_ERROR;
314 }
315
316 wxWindow *wxPrinterBase::sm_abortWindow = NULL;
317 bool wxPrinterBase::sm_abortIt = false;
318 wxPrinterError wxPrinterBase::sm_lastError = wxPRINTER_NO_ERROR;
319
320 wxPrinterBase::~wxPrinterBase()
321 {
322 }
323
324 wxWindow *wxPrinterBase::CreateAbortWindow(wxWindow *parent, wxPrintout * printout)
325 {
326 wxPrintAbortDialog *dialog = new wxPrintAbortDialog(parent, _("Printing ") , wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE);
327
328 wxBoxSizer *button_sizer = new wxBoxSizer( wxVERTICAL );
329 button_sizer->Add( new wxStaticText(dialog, wxID_ANY, _("Please wait while printing\n") + printout->GetTitle() ), 0, wxALL, 10 );
330 button_sizer->Add( new wxButton( dialog, wxID_CANCEL, wxT("Cancel") ), 0, wxALL | wxALIGN_CENTER, 10 );
331
332 dialog->SetAutoLayout( true );
333 dialog->SetSizer( button_sizer );
334
335 button_sizer->Fit(dialog);
336 button_sizer->SetSizeHints (dialog) ;
337
338 return dialog;
339 }
340
341 void wxPrinterBase::ReportError(wxWindow *parent, wxPrintout *WXUNUSED(printout), const wxString& message)
342 {
343 wxMessageBox(message, _("Printing Error"), wxOK, parent);
344 }
345
346 wxPrintDialogData& wxPrinterBase::GetPrintDialogData() const
347 {
348 return (wxPrintDialogData&) m_printDialogData;
349 }
350
351 //----------------------------------------------------------------------------
352 // wxPrinter
353 //----------------------------------------------------------------------------
354
355 IMPLEMENT_CLASS(wxPrinter, wxPrinterBase)
356
357 wxPrinter::wxPrinter(wxPrintDialogData *data)
358 {
359 m_pimpl = wxPrintFactory::GetFactory()->CreatePrinter( data );
360 }
361
362 wxPrinter::~wxPrinter()
363 {
364 delete m_pimpl;
365 }
366
367 wxWindow *wxPrinter::CreateAbortWindow(wxWindow *parent, wxPrintout *printout)
368 {
369 return m_pimpl->CreateAbortWindow( parent, printout );
370 }
371
372 void wxPrinter::ReportError(wxWindow *parent, wxPrintout *printout, const wxString& message)
373 {
374 m_pimpl->ReportError( parent, printout, message );
375 }
376
377 bool wxPrinter::Setup(wxWindow *parent)
378 {
379 return m_pimpl->Setup( parent );
380 }
381
382 bool wxPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
383 {
384 return m_pimpl->Print( parent, printout, prompt );
385 }
386
387 wxDC* wxPrinter::PrintDialog(wxWindow *parent)
388 {
389 return m_pimpl->PrintDialog( parent );
390 }
391
392 wxPrintDialogData& wxPrinter::GetPrintDialogData() const
393 {
394 return m_pimpl->GetPrintDialogData();
395 }
396
397 // ---------------------------------------------------------------------------
398 // wxPrintDialogBase: the dialog for printing.
399 // ---------------------------------------------------------------------------
400
401 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase, wxDialog)
402
403 wxPrintDialogBase::wxPrintDialogBase(wxWindow *parent,
404 wxWindowID id,
405 const wxString &title,
406 const wxPoint &pos,
407 const wxSize &size,
408 long style)
409 : wxDialog( parent, id, title.empty() ? wxString(_("Print")) : title,
410 pos, size, style )
411 {
412 }
413
414 // ---------------------------------------------------------------------------
415 // wxPrintDialog: the dialog for printing
416 // ---------------------------------------------------------------------------
417
418 IMPLEMENT_CLASS(wxPrintDialog, wxObject)
419
420 wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintDialogData* data)
421 {
422 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
423 }
424
425 wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintData* data)
426 {
427 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
428 }
429
430 wxPrintDialog::~wxPrintDialog()
431 {
432 delete m_pimpl;
433 }
434
435 int wxPrintDialog::ShowModal()
436 {
437 return m_pimpl->ShowModal();
438 }
439
440 wxPrintDialogData& wxPrintDialog::GetPrintDialogData()
441 {
442 return m_pimpl->GetPrintDialogData();
443 }
444
445 wxPrintData& wxPrintDialog::GetPrintData()
446 {
447 return m_pimpl->GetPrintData();
448 }
449
450 wxDC *wxPrintDialog::GetPrintDC()
451 {
452 return m_pimpl->GetPrintDC();
453 }
454
455 // ---------------------------------------------------------------------------
456 // wxPageSetupDialogBase: the page setup dialog
457 // ---------------------------------------------------------------------------
458
459 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase, wxDialog)
460
461 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow *parent,
462 wxWindowID id,
463 const wxString &title,
464 const wxPoint &pos,
465 const wxSize &size,
466 long style)
467 : wxDialog( parent, id, title.empty() ? wxString(_("Page setup")) : title,
468 pos, size, style )
469 {
470 }
471
472 // ---------------------------------------------------------------------------
473 // wxPageSetupDialog: the page setup dialog
474 // ---------------------------------------------------------------------------
475
476 IMPLEMENT_CLASS(wxPageSetupDialog, wxObject)
477
478 wxPageSetupDialog::wxPageSetupDialog(wxWindow *parent, wxPageSetupDialogData *data )
479 {
480 m_pimpl = wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent, data );
481 }
482
483 wxPageSetupDialog::~wxPageSetupDialog()
484 {
485 delete m_pimpl;
486 }
487
488 int wxPageSetupDialog::ShowModal()
489 {
490 return m_pimpl->ShowModal();
491 }
492
493 wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupDialogData()
494 {
495 return m_pimpl->GetPageSetupDialogData();
496 }
497
498 // old name
499 wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupData()
500 {
501 return m_pimpl->GetPageSetupDialogData();
502 }
503
504 //----------------------------------------------------------------------------
505 // wxPrintAbortDialog
506 //----------------------------------------------------------------------------
507
508 BEGIN_EVENT_TABLE(wxPrintAbortDialog, wxDialog)
509 EVT_BUTTON(wxID_CANCEL, wxPrintAbortDialog::OnCancel)
510 END_EVENT_TABLE()
511
512 void wxPrintAbortDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
513 {
514 wxPrinterBase::sm_abortIt = true;
515 wxPrinterBase::sm_abortWindow->Show(false);
516 wxPrinterBase::sm_abortWindow->Close(true);
517 wxPrinterBase::sm_abortWindow->Destroy();
518 wxPrinterBase::sm_abortWindow = NULL;
519 }
520
521 //----------------------------------------------------------------------------
522 // wxPrintout
523 //----------------------------------------------------------------------------
524
525 IMPLEMENT_ABSTRACT_CLASS(wxPrintout, wxObject)
526
527 wxPrintout::wxPrintout(const wxString& title)
528 {
529 m_printoutTitle = title ;
530 m_printoutDC = NULL;
531 m_pageWidthMM = 0;
532 m_pageHeightMM = 0;
533 m_pageWidthPixels = 0;
534 m_pageHeightPixels = 0;
535 m_PPIScreenX = 0;
536 m_PPIScreenY = 0;
537 m_PPIPrinterX = 0;
538 m_PPIPrinterY = 0;
539 m_preview = NULL;
540 }
541
542 wxPrintout::~wxPrintout()
543 {
544 }
545
546 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage), int WXUNUSED(endPage))
547 {
548 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle);
549 }
550
551 void wxPrintout::OnEndDocument()
552 {
553 GetDC()->EndDoc();
554 }
555
556 void wxPrintout::OnBeginPrinting()
557 {
558 }
559
560 void wxPrintout::OnEndPrinting()
561 {
562 }
563
564 bool wxPrintout::HasPage(int page)
565 {
566 return (page == 1);
567 }
568
569 void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toPage)
570 {
571 *minPage = 1;
572 *maxPage = 32000;
573 *fromPage = 1;
574 *toPage = 1;
575 }
576
577 void wxPrintout::FitThisSizeToPaper(const wxSize& imageSize)
578 {
579 // Set the DC scale and origin so that the given image size fits within the
580 // entire page and the origin is at the top left corner of the page. Note
581 // that with most printers, portions of the page will be non-printable. Use
582 // this if you're managing your own page margins.
583 if (!m_printoutDC) return;
584 wxRect paperRect = GetPaperRectPixels();
585 wxCoord pw, ph;
586 GetPageSizePixels(&pw, &ph);
587 wxCoord w, h;
588 m_printoutDC->GetSize(&w, &h);
589 float scaleX = ((float(paperRect.width) * w) / (float(pw) * imageSize.x));
590 float scaleY = ((float(paperRect.height) * h) / (float(ph) * imageSize.y));
591 float actualScale = wxMin(scaleX, scaleY);
592 m_printoutDC->SetUserScale(actualScale, actualScale);
593 m_printoutDC->SetDeviceOrigin(0, 0);
594 wxRect logicalPaperRect = GetLogicalPaperRect();
595 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
596 }
597
598 void wxPrintout::FitThisSizeToPage(const wxSize& imageSize)
599 {
600 // Set the DC scale and origin so that the given image size fits within the
601 // printable area of the page and the origin is at the top left corner of
602 // the printable area.
603 if (!m_printoutDC) return;
604 int w, h;
605 m_printoutDC->GetSize(&w, &h);
606 float scaleX = float(w) / imageSize.x;
607 float scaleY = float(h) / imageSize.y;
608 float actualScale = wxMin(scaleX, scaleY);
609 m_printoutDC->SetUserScale(actualScale, actualScale);
610 m_printoutDC->SetDeviceOrigin(0, 0);
611 }
612
613 void wxPrintout::FitThisSizeToPageMargins(const wxSize& imageSize, const wxPageSetupDialogData& pageSetupData)
614 {
615 // Set the DC scale and origin so that the given image size fits within the
616 // page margins defined in the given wxPageSetupDialogData object and the
617 // origin is at the top left corner of the page margins.
618 if (!m_printoutDC) return;
619 wxRect paperRect = GetPaperRectPixels();
620 wxCoord pw, ph;
621 GetPageSizePixels(&pw, &ph);
622 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
623 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
624 wxCoord mw, mh;
625 GetPageSizeMM(&mw, &mh);
626 float mmToDeviceX = float(pw) / mw;
627 float mmToDeviceY = float(ph) / mh;
628 wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x),
629 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
630 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
631 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
632 wxCoord w, h;
633 m_printoutDC->GetSize(&w, &h);
634 float scaleX = (float(pageMarginsRect.width) * w) / (float(pw) * imageSize.x);
635 float scaleY = (float(pageMarginsRect.height) * h) / (float(ph) * imageSize.y);
636 float actualScale = wxMin(scaleX, scaleY);
637 m_printoutDC->SetUserScale(actualScale, actualScale);
638 m_printoutDC->SetDeviceOrigin(0, 0);
639 wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
640 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
641 }
642
643 void wxPrintout::MapScreenSizeToPaper()
644 {
645 // Set the DC scale so that an image on the screen is the same size on the
646 // paper and the origin is at the top left of the paper. Note that with most
647 // printers, portions of the page will be cut off. Use this if you're
648 // managing your own page margins.
649 if (!m_printoutDC) return;
650 MapScreenSizeToPage();
651 wxRect logicalPaperRect = GetLogicalPaperRect();
652 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
653 }
654
655 void wxPrintout::MapScreenSizeToPage()
656 {
657 // Set the DC scale and origin so that an image on the screen is the same
658 // size on the paper and the origin is at the top left of the printable area.
659 if (!m_printoutDC) return;
660 int ppiScreenX, ppiScreenY;
661 GetPPIScreen(&ppiScreenX, &ppiScreenY);
662 int ppiPrinterX, ppiPrinterY;
663 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
664 int w, h;
665 m_printoutDC->GetSize(&w, &h);
666 int pageSizePixelsX, pageSizePixelsY;
667 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
668 float userScaleX = (float(ppiPrinterX) * w) / (float(ppiScreenX) * pageSizePixelsX);
669 float userScaleY = (float(ppiPrinterY) * h) / (float(ppiScreenY) * pageSizePixelsY);
670 m_printoutDC->SetUserScale(userScaleX, userScaleY);
671 m_printoutDC->SetDeviceOrigin(0, 0);
672 }
673
674 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData& pageSetupData)
675 {
676 // Set the DC scale so that an image on the screen is the same size on the
677 // paper and the origin is at the top left of the page margins defined by
678 // the given wxPageSetupDialogData object.
679 if (!m_printoutDC) return;
680 MapScreenSizeToPage();
681 wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
682 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
683 }
684
685 void wxPrintout::MapScreenSizeToDevice()
686 {
687 // Set the DC scale so that a screen pixel is the same size as a device
688 // pixel and the origin is at the top left of the printable area.
689 if (!m_printoutDC) return;
690 int w, h;
691 m_printoutDC->GetSize(&w, &h);
692 int pageSizePixelsX, pageSizePixelsY;
693 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
694 float userScaleX = float(w) / pageSizePixelsX;
695 float userScaleY = float(h) / pageSizePixelsY;
696 m_printoutDC->SetUserScale(userScaleX, userScaleY);
697 m_printoutDC->SetDeviceOrigin(0, 0);
698 }
699
700 wxRect wxPrintout::GetLogicalPaperRect() const
701 {
702 // Return the rectangle in logical units that corresponds to the paper
703 // rectangle.
704 wxRect paperRect = GetPaperRectPixels();
705 wxCoord pw, ph;
706 GetPageSizePixels(&pw, &ph);
707 wxCoord w, h;
708 m_printoutDC->GetSize(&w, &h);
709 if (w == pw && h == ph) {
710 // this DC matches the printed page, so no scaling
711 return wxRect(m_printoutDC->DeviceToLogicalX(paperRect.x),
712 m_printoutDC->DeviceToLogicalY(paperRect.y),
713 m_printoutDC->DeviceToLogicalXRel(paperRect.width),
714 m_printoutDC->DeviceToLogicalYRel(paperRect.height));
715 }
716 // This DC doesn't match the printed page, so we have to scale.
717 float scaleX = float(w) / pw;
718 float scaleY = float(h) / ph;
719 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(paperRect.x * scaleX)),
720 m_printoutDC->DeviceToLogicalY(wxRound(paperRect.y * scaleY)),
721 m_printoutDC->DeviceToLogicalXRel(wxRound(paperRect.width * scaleX)),
722 m_printoutDC->DeviceToLogicalYRel(wxRound(paperRect.height * scaleY)));
723 }
724
725 wxRect wxPrintout::GetLogicalPageRect() const
726 {
727 // Return the rectangle in logical units that corresponds to the printable
728 // area.
729 int w, h;
730 m_printoutDC->GetSize(&w, &h);
731 return wxRect(m_printoutDC->DeviceToLogicalX(0),
732 m_printoutDC->DeviceToLogicalY(0),
733 m_printoutDC->DeviceToLogicalXRel(w),
734 m_printoutDC->DeviceToLogicalYRel(h));
735 }
736
737 wxRect wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData& pageSetupData) const
738 {
739 // Return the rectangle in logical units that corresponds to the region
740 // within the page margins as specified by the given wxPageSetupDialogData
741 // object.
742
743 // We get the paper size in device units and the margins in mm,
744 // so we need to calculate the conversion with this trick
745 wxCoord pw, ph;
746 GetPageSizePixels(&pw, &ph);
747 wxCoord mw, mh;
748 GetPageSizeMM(&mw, &mh);
749 float mmToDeviceX = float(pw) / mw;
750 float mmToDeviceY = float(ph) / mh;
751
752 // paper size in device units
753 wxRect paperRect = GetPaperRectPixels();
754
755 // margins in mm
756 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
757 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
758
759 // calculate margins in device units
760 wxRect pageMarginsRect(
761 paperRect.x + wxRound(mmToDeviceX * topLeft.x),
762 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
763 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
764 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
765
766 wxCoord w, h;
767 m_printoutDC->GetSize(&w, &h);
768 if (w == pw && h == ph)
769 {
770 // this DC matches the printed page, so no scaling
771 return wxRect(
772 m_printoutDC->DeviceToLogicalX(pageMarginsRect.x),
773 m_printoutDC->DeviceToLogicalY(pageMarginsRect.y),
774 m_printoutDC->DeviceToLogicalXRel(pageMarginsRect.width),
775 m_printoutDC->DeviceToLogicalYRel(pageMarginsRect.height));
776 }
777
778 // This DC doesn't match the printed page, so we have to scale.
779 float scaleX = float(w) / pw;
780 float scaleY = float(h) / ph;
781 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(pageMarginsRect.x * scaleX)),
782 m_printoutDC->DeviceToLogicalY(wxRound(pageMarginsRect.y * scaleY)),
783 m_printoutDC->DeviceToLogicalXRel(wxRound(pageMarginsRect.width * scaleX)),
784 m_printoutDC->DeviceToLogicalYRel(wxRound(pageMarginsRect.height * scaleY)));
785 }
786
787 void wxPrintout::SetLogicalOrigin(wxCoord x, wxCoord y)
788 {
789 // Set the device origin by specifying a point in logical coordinates.
790 m_printoutDC->SetDeviceOrigin(
791 m_printoutDC->LogicalToDeviceX(x),
792 m_printoutDC->LogicalToDeviceY(y) );
793 }
794
795 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff, wxCoord yoff)
796 {
797 // Offset the device origin by a specified distance in device coordinates.
798 wxPoint dev_org = m_printoutDC->GetDeviceOrigin();
799 m_printoutDC->SetDeviceOrigin(
800 dev_org.x + m_printoutDC->LogicalToDeviceXRel(xoff),
801 dev_org.y + m_printoutDC->LogicalToDeviceYRel(yoff) );
802 }
803
804
805 //----------------------------------------------------------------------------
806 // wxPreviewCanvas
807 //----------------------------------------------------------------------------
808
809 IMPLEMENT_CLASS(wxPreviewCanvas, wxWindow)
810
811 BEGIN_EVENT_TABLE(wxPreviewCanvas, wxScrolledWindow)
812 EVT_PAINT(wxPreviewCanvas::OnPaint)
813 EVT_CHAR(wxPreviewCanvas::OnChar)
814 EVT_IDLE(wxPreviewCanvas::OnIdle)
815 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged)
816 #if wxUSE_MOUSEWHEEL
817 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel)
818 #endif
819 END_EVENT_TABLE()
820
821 // VZ: the current code doesn't refresh properly without
822 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
823 // really horrible flicker when resizing the preview frame, but without
824 // this style it simply doesn't work correctly at all...
825 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase *preview, wxWindow *parent,
826 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
827 wxScrolledWindow(parent, wxID_ANY, pos, size, style | wxFULL_REPAINT_ON_RESIZE, name)
828 {
829 m_printPreview = preview;
830 #ifdef __WXMAC__
831 // The app workspace colour is always white, but we should have
832 // a contrast with the page.
833 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
834 #elif defined(__WXGTK__)
835 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
836 #else
837 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
838 #endif
839 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
840
841 SetScrollbars(10, 10, 100, 100);
842 }
843
844 wxPreviewCanvas::~wxPreviewCanvas()
845 {
846 }
847
848 void wxPreviewCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
849 {
850 wxPaintDC dc(this);
851 PrepareDC( dc );
852
853 /*
854 #ifdef __WXGTK__
855 if (!GetUpdateRegion().IsEmpty())
856 dc.SetClippingRegion( GetUpdateRegion() );
857 #endif
858 */
859
860 if (m_printPreview)
861 {
862 m_printPreview->PaintPage(this, dc);
863 }
864 }
865
866 void wxPreviewCanvas::OnIdle(wxIdleEvent& event)
867 {
868 event.Skip();
869
870 // prevent UpdatePageRendering() from being called recursively:
871 static bool s_inIdle = false;
872 if ( s_inIdle )
873 return;
874 s_inIdle = true;
875
876 if ( m_printPreview )
877 {
878 if ( m_printPreview->UpdatePageRendering() )
879 Refresh();
880 }
881
882 s_inIdle = false;
883 }
884
885 // Responds to colour changes, and passes event on to children.
886 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent& event)
887 {
888 #ifdef __WXMAC__
889 // The app workspace colour is always white, but we should have
890 // a contrast with the page.
891 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
892 #elif defined(__WXGTK__)
893 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
894 #else
895 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
896 #endif
897 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
898 Refresh();
899
900 // Propagate the event to the non-top-level children
901 wxWindow::OnSysColourChanged(event);
902 }
903
904 void wxPreviewCanvas::OnChar(wxKeyEvent &event)
905 {
906 wxPreviewControlBar* controlBar = ((wxPreviewFrame*) GetParent())->GetControlBar();
907 switch (event.GetKeyCode())
908 {
909 case WXK_RETURN:
910 controlBar->OnPrint();
911 return;
912 case (int)'+':
913 case WXK_NUMPAD_ADD:
914 case WXK_ADD:
915 controlBar->DoZoomIn();
916 return;
917 case (int)'-':
918 case WXK_NUMPAD_SUBTRACT:
919 case WXK_SUBTRACT:
920 controlBar->DoZoomOut();
921 return;
922 }
923
924 if (!event.ControlDown())
925 {
926 event.Skip();
927 return;
928 }
929
930 switch(event.GetKeyCode())
931 {
932 case WXK_PAGEDOWN:
933 controlBar->OnNext(); break;
934 case WXK_PAGEUP:
935 controlBar->OnPrevious(); break;
936 case WXK_HOME:
937 controlBar->OnFirst(); break;
938 case WXK_END:
939 controlBar->OnLast(); break;
940 default:
941 event.Skip();
942 }
943 }
944
945 #if wxUSE_MOUSEWHEEL
946
947 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent& event)
948 {
949 wxPreviewControlBar *
950 controlBar = wxStaticCast(GetParent(), wxPreviewFrame)->GetControlBar();
951
952 if ( controlBar )
953 {
954 if ( event.ControlDown() && event.GetWheelRotation() != 0 )
955 {
956 int currentZoom = controlBar->GetZoomControl();
957
958 int delta;
959 if ( currentZoom < 100 )
960 delta = 5;
961 else if ( currentZoom <= 120 )
962 delta = 10;
963 else
964 delta = 50;
965
966 if ( event.GetWheelRotation() > 0 )
967 delta = -delta;
968
969 int newZoom = currentZoom + delta;
970 if ( newZoom < 10 )
971 newZoom = 10;
972 if ( newZoom > 200 )
973 newZoom = 200;
974 if ( newZoom != currentZoom )
975 {
976 controlBar->SetZoomControl(newZoom);
977 m_printPreview->SetZoom(newZoom);
978 Refresh();
979 }
980 return;
981 }
982 }
983
984 event.Skip();
985 }
986
987 #endif // wxUSE_MOUSEWHEEL
988
989 // ----------------------------------------------------------------------------
990 // wxPrintPageTextCtrl
991 // ----------------------------------------------------------------------------
992
993 // This text control contains the page number in the interval specified during
994 // its construction. Invalid pages are not accepted and the control contents is
995 // validated when it loses focus. Conversely, if the user changes the page to
996 // another valid one or presses Enter, OnGotoPage() method of the preview object
997 // will be called.
998 class wxPrintPageTextCtrl : public wxTextCtrl
999 {
1000 public:
1001 wxPrintPageTextCtrl(wxPreviewControlBar *preview, int minPage, int maxPage)
1002 : wxTextCtrl(preview,
1003 wxID_PREVIEW_GOTO,
1004 PageAsString(minPage),
1005 wxDefaultPosition,
1006 // We use hardcoded 99999 for the width instead of fitting
1007 // it to the values we can show because the control looks
1008 // uncomfortably narrow if the real page number is just
1009 // one or two digits.
1010 wxSize(preview->GetTextExtent("99999").x, wxDefaultCoord),
1011 wxTE_PROCESS_ENTER
1012 #if wxUSE_VALIDATORS
1013 , wxTextValidator(wxFILTER_DIGITS)
1014 #endif // wxUSE_VALIDATORS
1015 ),
1016 m_preview(preview),
1017 m_minPage(minPage),
1018 m_maxPage(maxPage)
1019 {
1020 m_page = minPage;
1021
1022 Connect(wxEVT_KILL_FOCUS,
1023 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus));
1024 Connect(wxEVT_COMMAND_TEXT_ENTER,
1025 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter));
1026 }
1027
1028 // Helpers to conveniently set or get the current page number. Return value
1029 // is 0 if the current controls contents is invalid.
1030 void SetPageNumber(int page)
1031 {
1032 wxASSERT( IsValidPage(page) );
1033
1034 SetValue(PageAsString(page));
1035 }
1036
1037 int GetPageNumber() const
1038 {
1039 long value;
1040 if ( !GetValue().ToLong(&value) || !IsValidPage(value) )
1041 return 0;
1042
1043 // Cast is safe because the value is less than (int) m_maxPage.
1044 return static_cast<int>(value);
1045 }
1046
1047 private:
1048 static wxString PageAsString(int page)
1049 {
1050 return wxString::Format("%d", page);
1051 }
1052
1053 bool IsValidPage(int page) const
1054 {
1055 return page >= m_minPage && page <= m_maxPage;
1056 }
1057
1058 bool DoChangePage()
1059 {
1060 const int page = GetPageNumber();
1061
1062 if ( !page )
1063 return false;
1064
1065 if ( page != m_page )
1066 {
1067 // We have a valid page, remember it.
1068 m_page = page;
1069
1070 // And notify the owner about the change.
1071 m_preview->OnGotoPage();
1072 }
1073 //else: Nothing really changed.
1074
1075 return true;
1076 }
1077
1078 void OnKillFocus(wxFocusEvent& event)
1079 {
1080 if ( !DoChangePage() )
1081 {
1082 // The current contents is invalid so reset it back to the last
1083 // known good page index.
1084 SetPageNumber(m_page);
1085 }
1086
1087 event.Skip();
1088 }
1089
1090 void OnTextEnter(wxCommandEvent& WXUNUSED(event))
1091 {
1092 DoChangePage();
1093 }
1094
1095
1096 wxPreviewControlBar * const m_preview;
1097
1098 const int m_minPage,
1099 m_maxPage;
1100
1101 // This is the last valid page value that we had, we revert to it if an
1102 // invalid page is entered.
1103 int m_page;
1104
1105 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl);
1106 };
1107
1108 //----------------------------------------------------------------------------
1109 // wxPreviewControlBar
1110 //----------------------------------------------------------------------------
1111
1112 IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
1113
1114 BEGIN_EVENT_TABLE(wxPreviewControlBar, wxPanel)
1115 EVT_BUTTON(wxID_PREVIEW_CLOSE, wxPreviewControlBar::OnWindowClose)
1116 EVT_BUTTON(wxID_PREVIEW_PRINT, wxPreviewControlBar::OnPrintButton)
1117 EVT_BUTTON(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnPreviousButton)
1118 EVT_BUTTON(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnNextButton)
1119 EVT_BUTTON(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnFirstButton)
1120 EVT_BUTTON(wxID_PREVIEW_LAST, wxPreviewControlBar::OnLastButton)
1121 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnZoomInButton)
1122 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnZoomOutButton)
1123
1124 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnUpdatePreviousButton)
1125 EVT_UPDATE_UI(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnUpdateNextButton)
1126 EVT_UPDATE_UI(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnUpdateFirstButton)
1127 EVT_UPDATE_UI(wxID_PREVIEW_LAST, wxPreviewControlBar::OnUpdateLastButton)
1128 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnUpdateZoomInButton)
1129 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnUpdateZoomOutButton)
1130
1131 EVT_CHOICE(wxID_PREVIEW_ZOOM, wxPreviewControlBar::OnZoomChoice)
1132 EVT_PAINT(wxPreviewControlBar::OnPaint)
1133
1134 END_EVENT_TABLE()
1135
1136 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
1137 wxWindow *parent, const wxPoint& pos, const wxSize& size,
1138 long style, const wxString& name):
1139 wxPanel(parent, wxID_ANY, pos, size, style, name)
1140 {
1141 m_printPreview = preview;
1142 m_closeButton = NULL;
1143 m_zoomControl = NULL;
1144 m_currentPageText = NULL;
1145 m_buttonFlags = buttons;
1146 }
1147
1148 wxPreviewControlBar::~wxPreviewControlBar()
1149 {
1150 }
1151
1152 void wxPreviewControlBar::OnPaint(wxPaintEvent& WXUNUSED(event))
1153 {
1154 wxPaintDC dc(this);
1155
1156 int w, h;
1157 GetSize(&w, &h);
1158 dc.SetPen(*wxBLACK_PEN);
1159 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1160 dc.DrawLine( 0, h-1, w, h-1 );
1161 }
1162
1163 void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
1164 {
1165 wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
1166 frame->Close(true);
1167 }
1168
1169 void wxPreviewControlBar::OnPrint(void)
1170 {
1171 wxPrintPreviewBase *preview = GetPrintPreview();
1172 preview->Print(true);
1173 }
1174
1175 void wxPreviewControlBar::OnNext()
1176 {
1177 if ( IsNextEnabled() )
1178 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1179 }
1180
1181 void wxPreviewControlBar::OnPrevious()
1182 {
1183 if ( IsPreviousEnabled() )
1184 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1185 }
1186
1187 void wxPreviewControlBar::OnFirst()
1188 {
1189 if ( IsFirstEnabled() )
1190 DoGotoPage(GetPrintPreview()->GetMinPage());
1191 }
1192
1193 void wxPreviewControlBar::OnLast()
1194 {
1195 if ( IsLastEnabled() )
1196 DoGotoPage(GetPrintPreview()->GetMaxPage());
1197 }
1198
1199 bool wxPreviewControlBar::IsNextEnabled() const
1200 {
1201 wxPrintPreviewBase *preview = GetPrintPreview();
1202 if ( !preview )
1203 return false;
1204
1205 const int currentPage = preview->GetCurrentPage();
1206 return currentPage < preview->GetMaxPage() &&
1207 preview->GetPrintout()->HasPage(currentPage + 1);
1208 }
1209
1210 bool wxPreviewControlBar::IsPreviousEnabled() const
1211 {
1212 wxPrintPreviewBase *preview = GetPrintPreview();
1213 if ( !preview )
1214 return false;
1215
1216 const int currentPage = preview->GetCurrentPage();
1217 return currentPage > preview->GetMinPage() &&
1218 preview->GetPrintout()->HasPage(currentPage - 1);
1219 }
1220
1221 bool wxPreviewControlBar::IsFirstEnabled() const
1222 {
1223 wxPrintPreviewBase *preview = GetPrintPreview();
1224 if (!preview)
1225 return false;
1226
1227 return preview->GetPrintout()->HasPage(preview->GetMinPage());
1228 }
1229
1230 bool wxPreviewControlBar::IsLastEnabled() const
1231 {
1232 wxPrintPreviewBase *preview = GetPrintPreview();
1233 if (!preview)
1234 return false;
1235
1236 return preview->GetPrintout()->HasPage(preview->GetMaxPage());
1237 }
1238
1239 void wxPreviewControlBar::DoGotoPage(int page)
1240 {
1241 wxPrintPreviewBase *preview = GetPrintPreview();
1242 wxCHECK_RET( preview, "Shouldn't be called if there is no preview." );
1243
1244 preview->SetCurrentPage(page);
1245
1246 if ( m_currentPageText )
1247 m_currentPageText->SetPageNumber(page);
1248 }
1249
1250 void wxPreviewControlBar::OnGotoPage()
1251 {
1252 wxPrintPreviewBase *preview = GetPrintPreview();
1253 if (preview)
1254 {
1255 if (preview->GetMinPage() > 0)
1256 {
1257 long currentPage = m_currentPageText->GetPageNumber();
1258 if ( currentPage )
1259 {
1260 if (preview->GetPrintout()->HasPage(currentPage))
1261 {
1262 preview->SetCurrentPage(currentPage);
1263 }
1264 }
1265 }
1266 }
1267 }
1268
1269 void wxPreviewControlBar::DoZoom()
1270 {
1271 int zoom = GetZoomControl();
1272 if (GetPrintPreview())
1273 GetPrintPreview()->SetZoom(zoom);
1274 }
1275
1276 bool wxPreviewControlBar::IsZoomInEnabled() const
1277 {
1278 if ( !m_zoomControl )
1279 return false;
1280
1281 const unsigned sel = m_zoomControl->GetSelection();
1282 return sel < m_zoomControl->GetCount() - 1;
1283 }
1284
1285 bool wxPreviewControlBar::IsZoomOutEnabled() const
1286 {
1287 return m_zoomControl && m_zoomControl->GetSelection() > 0;
1288 }
1289
1290 void wxPreviewControlBar::DoZoomIn()
1291 {
1292 if (IsZoomInEnabled())
1293 {
1294 m_zoomControl->SetSelection(m_zoomControl->GetSelection() + 1);
1295 DoZoom();
1296 }
1297 }
1298
1299 void wxPreviewControlBar::DoZoomOut()
1300 {
1301 if (IsZoomOutEnabled())
1302 {
1303 m_zoomControl->SetSelection(m_zoomControl->GetSelection() - 1);
1304 DoZoom();
1305 }
1306 }
1307
1308 namespace
1309 {
1310
1311 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1312 // sequentially to it in the simplest way possible.
1313 class SizerWithButtons
1314 {
1315 public:
1316 // Constructor creates the sizer that will hold the buttons and stores the
1317 // parent that will be used for their creation.
1318 SizerWithButtons(wxWindow *parent)
1319 : m_sizer(new wxBoxSizer(wxHORIZONTAL)),
1320 m_parent(parent)
1321 {
1322 m_hasContents =
1323 m_needsSeparator = false;
1324 }
1325
1326 // Destructor associates the sizer with the parent window.
1327 ~SizerWithButtons()
1328 {
1329 m_parent->SetSizer(m_sizer);
1330 m_sizer->Fit(m_parent);
1331 }
1332
1333
1334 // Add an arbitrary window to the sizer.
1335 void Add(wxWindow *win)
1336 {
1337 if ( m_needsSeparator )
1338 {
1339 m_needsSeparator = false;
1340
1341 m_sizer->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1342 }
1343
1344 m_hasContents = true;
1345
1346 m_sizer->Add(win,
1347 wxSizerFlags().Border(wxLEFT | wxTOP | wxBOTTOM).Center());
1348 }
1349
1350 // Add a button with the specified id, bitmap and tooltip.
1351 void AddButton(wxWindowID btnId,
1352 const wxArtID& artId,
1353 const wxString& tooltip)
1354 {
1355 // We don't use (smaller) images inside a button with a text label but
1356 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1357 // wxART_BUTTON here.
1358 wxBitmap bmp = wxArtProvider::GetBitmap(artId, wxART_TOOLBAR);
1359 wxBitmapButton * const btn = new wxBitmapButton(m_parent, btnId, bmp);
1360 btn->SetToolTip(tooltip);
1361
1362 Add(btn);
1363 }
1364
1365 // Add a control at the right end of the window. This should be called last
1366 // as everything else added after it will be added on the right side too.
1367 void AddAtEnd(wxWindow *win)
1368 {
1369 m_sizer->AddStretchSpacer();
1370 m_sizer->Add(win,
1371 wxSizerFlags().Border(wxTOP | wxBOTTOM | wxRIGHT).Center());
1372 }
1373
1374 // Indicates the end of a group of buttons, a separator will be added after
1375 // it.
1376 void EndOfGroup()
1377 {
1378 if ( m_hasContents )
1379 {
1380 m_needsSeparator = true;
1381 m_hasContents = false;
1382 }
1383 }
1384
1385 private:
1386 wxSizer * const m_sizer;
1387 wxWindow * const m_parent;
1388
1389 // If true, we have some controls since the last group beginning. This is
1390 // used to avoid inserting two consecutive separators if EndOfGroup() is
1391 // called twice.
1392 bool m_hasContents;
1393
1394 // If true, a separator should be inserted before adding the next button.
1395 bool m_needsSeparator;
1396
1397 wxDECLARE_NO_COPY_CLASS(SizerWithButtons);
1398 };
1399
1400 } // anonymous namespace
1401
1402 void wxPreviewControlBar::CreateButtons()
1403 {
1404 SizerWithButtons sizer(this);
1405
1406 // Print button group (a single button).
1407 if (m_buttonFlags & wxPREVIEW_PRINT)
1408 {
1409 sizer.AddButton(wxID_PREVIEW_PRINT, wxART_PRINT, _("Print"));
1410 sizer.EndOfGroup();
1411 }
1412
1413 // Page selection buttons group.
1414 if (m_buttonFlags & wxPREVIEW_FIRST)
1415 {
1416 sizer.AddButton(wxID_PREVIEW_FIRST, wxART_GOTO_FIRST, _("First page"));
1417 }
1418
1419 if (m_buttonFlags & wxPREVIEW_PREVIOUS)
1420 {
1421 sizer.AddButton(wxID_PREVIEW_PREVIOUS, wxART_GO_BACK, _("Previous page"));
1422 }
1423
1424 if (m_buttonFlags & wxPREVIEW_GOTO)
1425 {
1426 int minPage, maxPage, pageFrom, pageTo;
1427 m_printPreview->GetPrintout()->GetPageInfo(&minPage, &maxPage,
1428 &pageFrom, &pageTo);
1429
1430 m_currentPageText = new wxPrintPageTextCtrl(this, minPage, maxPage);
1431 sizer.Add(m_currentPageText);
1432
1433 wxStaticText *
1434 maxPageText = new wxStaticText(this, wxID_ANY,
1435 wxString::Format("/ %d", maxPage));
1436
1437 sizer.Add(maxPageText);
1438 }
1439
1440 if (m_buttonFlags & wxPREVIEW_NEXT)
1441 {
1442 sizer.AddButton(wxID_PREVIEW_NEXT, wxART_GO_FORWARD, _("Next page"));
1443 }
1444
1445 if (m_buttonFlags & wxPREVIEW_LAST)
1446 {
1447 sizer.AddButton(wxID_PREVIEW_LAST, wxART_GOTO_LAST, _("Last page"));
1448 }
1449
1450 sizer.EndOfGroup();
1451
1452 // Zoom controls group.
1453 if (m_buttonFlags & wxPREVIEW_ZOOM)
1454 {
1455 sizer.AddButton(wxID_PREVIEW_ZOOM_OUT, wxART_MINUS, _("Zoom Out"));
1456
1457 wxString choices[] =
1458 {
1459 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1460 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1461 wxT("120%"), wxT("150%"), wxT("200%")
1462 };
1463 int n = WXSIZEOF(choices);
1464
1465 m_zoomControl = new wxChoice( this, wxID_PREVIEW_ZOOM, wxDefaultPosition, wxSize(70,wxDefaultCoord), n, choices, 0 );
1466 sizer.Add(m_zoomControl);
1467 SetZoomControl(m_printPreview->GetZoom());
1468
1469 sizer.AddButton(wxID_PREVIEW_ZOOM_IN, wxART_PLUS, _("Zoom In"));
1470
1471 sizer.EndOfGroup();
1472 }
1473
1474 // Close button group (single button again).
1475 m_closeButton = new wxButton(this, wxID_PREVIEW_CLOSE, _("&Close"));
1476 sizer.AddAtEnd(m_closeButton);
1477 }
1478
1479 void wxPreviewControlBar::SetZoomControl(int zoom)
1480 {
1481 if (m_zoomControl)
1482 {
1483 int n, count = m_zoomControl->GetCount();
1484 long val;
1485 for (n=0; n<count; n++)
1486 {
1487 if (m_zoomControl->GetString(n).BeforeFirst(wxT('%')).ToLong(&val) &&
1488 (val >= long(zoom)))
1489 {
1490 m_zoomControl->SetSelection(n);
1491 return;
1492 }
1493 }
1494
1495 m_zoomControl->SetSelection(count-1);
1496 }
1497 }
1498
1499 int wxPreviewControlBar::GetZoomControl()
1500 {
1501 if (m_zoomControl && (m_zoomControl->GetStringSelection() != wxEmptyString))
1502 {
1503 long val;
1504 if (m_zoomControl->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val))
1505 return int(val);
1506 }
1507
1508 return 0;
1509 }
1510
1511
1512 /*
1513 * Preview frame
1514 */
1515
1516 IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
1517
1518 BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
1519 EVT_CHAR_HOOK(wxPreviewFrame::OnChar)
1520 EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
1521 END_EVENT_TABLE()
1522
1523 void wxPreviewFrame::OnChar(wxKeyEvent &event)
1524 {
1525 if ( event.GetKeyCode() == WXK_ESCAPE )
1526 {
1527 Close(true);
1528 }
1529 else
1530 {
1531 event.Skip();
1532 }
1533 }
1534
1535 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
1536 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
1537 wxFrame(parent, wxID_ANY, title, pos, size, style, name)
1538 {
1539 m_printPreview = preview;
1540 m_controlBar = NULL;
1541 m_previewCanvas = NULL;
1542 m_windowDisabler = NULL;
1543
1544 // Give the application icon
1545 #ifdef __WXMSW__
1546 wxFrame* topFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
1547 if (topFrame)
1548 SetIcons(topFrame->GetIcons());
1549 #endif
1550 }
1551
1552 wxPreviewFrame::~wxPreviewFrame()
1553 {
1554 }
1555
1556 void wxPreviewFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
1557 {
1558 if (m_windowDisabler)
1559 delete m_windowDisabler;
1560
1561 // Need to delete the printout and the print preview
1562 wxPrintout *printout = m_printPreview->GetPrintout();
1563 if (printout)
1564 {
1565 delete printout;
1566 m_printPreview->SetPrintout(NULL);
1567 m_printPreview->SetCanvas(NULL);
1568 m_printPreview->SetFrame(NULL);
1569 }
1570
1571 m_previewCanvas->SetPreview(NULL);
1572 wxDELETE(m_printPreview);
1573
1574 Destroy();
1575 }
1576
1577 void wxPreviewFrame::Initialize()
1578 {
1579 #if wxUSE_STATUSBAR
1580 CreateStatusBar();
1581 #endif
1582 CreateCanvas();
1583 CreateControlBar();
1584
1585 m_printPreview->SetCanvas(m_previewCanvas);
1586 m_printPreview->SetFrame(this);
1587
1588 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
1589
1590 item0->Add( m_controlBar, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1591 item0->Add( m_previewCanvas, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1592
1593 SetAutoLayout( true );
1594 SetSizer( item0 );
1595
1596 m_windowDisabler = new wxWindowDisabler(this);
1597
1598 Layout();
1599
1600 m_printPreview->AdjustScrollbars(m_previewCanvas);
1601 m_previewCanvas->SetFocus();
1602 m_controlBar->SetFocus();
1603 }
1604
1605 void wxPreviewFrame::CreateCanvas()
1606 {
1607 m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
1608 }
1609
1610 void wxPreviewFrame::CreateControlBar()
1611 {
1612 long buttons = wxPREVIEW_DEFAULT;
1613 if (m_printPreview->GetPrintoutForPrinting())
1614 buttons |= wxPREVIEW_PRINT;
1615
1616 m_controlBar = new wxPreviewControlBar(m_printPreview, buttons, this);
1617 m_controlBar->CreateButtons();
1618 }
1619
1620 /*
1621 * Print preview
1622 */
1623
1624 IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
1625
1626 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1627 wxPrintout *printoutForPrinting,
1628 wxPrintData *data)
1629 {
1630 if (data)
1631 m_printDialogData = (*data);
1632
1633 Init(printout, printoutForPrinting);
1634 }
1635
1636 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1637 wxPrintout *printoutForPrinting,
1638 wxPrintDialogData *data)
1639 {
1640 if (data)
1641 m_printDialogData = (*data);
1642
1643 Init(printout, printoutForPrinting);
1644 }
1645
1646 void wxPrintPreviewBase::Init(wxPrintout *printout,
1647 wxPrintout *printoutForPrinting)
1648 {
1649 m_isOk = true;
1650 m_previewPrintout = printout;
1651 if (m_previewPrintout)
1652 m_previewPrintout->SetPreview(static_cast<wxPrintPreview *>(this));
1653
1654 m_printPrintout = printoutForPrinting;
1655
1656 m_previewCanvas = NULL;
1657 m_previewFrame = NULL;
1658 m_previewBitmap = NULL;
1659 m_previewFailed = false;
1660 m_currentPage = 1;
1661 m_currentZoom = 70;
1662 m_topMargin =
1663 m_leftMargin = 2*wxSizerFlags::GetDefaultBorder();
1664 m_pageWidth = 0;
1665 m_pageHeight = 0;
1666 m_printingPrepared = false;
1667 m_minPage = 1;
1668 m_maxPage = 1;
1669 }
1670
1671 wxPrintPreviewBase::~wxPrintPreviewBase()
1672 {
1673 if (m_previewPrintout)
1674 delete m_previewPrintout;
1675 if (m_previewBitmap)
1676 delete m_previewBitmap;
1677 if (m_printPrintout)
1678 delete m_printPrintout;
1679 }
1680
1681 bool wxPrintPreviewBase::SetCurrentPage(int pageNum)
1682 {
1683 if (m_currentPage == pageNum)
1684 return true;
1685
1686 m_currentPage = pageNum;
1687
1688 InvalidatePreviewBitmap();
1689
1690 if (m_previewCanvas)
1691 {
1692 AdjustScrollbars(m_previewCanvas);
1693
1694 m_previewCanvas->Refresh();
1695 m_previewCanvas->SetFocus();
1696 }
1697 return true;
1698 }
1699
1700 int wxPrintPreviewBase::GetCurrentPage() const
1701 { return m_currentPage; }
1702 void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
1703 { m_previewPrintout = printout; }
1704 wxPrintout *wxPrintPreviewBase::GetPrintout() const
1705 { return m_previewPrintout; }
1706 wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
1707 { return m_printPrintout; }
1708 void wxPrintPreviewBase::SetFrame(wxFrame *frame)
1709 { m_previewFrame = frame; }
1710 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
1711 { m_previewCanvas = canvas; }
1712 wxFrame *wxPrintPreviewBase::GetFrame() const
1713 { return m_previewFrame; }
1714 wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
1715 { return m_previewCanvas; }
1716
1717 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas *canvas, wxRect& pageRect, wxRect& paperRect)
1718 {
1719 // Calculate the rectangles for the printable area of the page and the
1720 // entire paper as they appear on the canvas on-screen.
1721 int canvasWidth, canvasHeight;
1722 canvas->GetSize(&canvasWidth, &canvasHeight);
1723
1724 float zoomScale = float(m_currentZoom) / 100;
1725 float screenPrintableWidth = zoomScale * m_pageWidth * m_previewScaleX;
1726 float screenPrintableHeight = zoomScale * m_pageHeight * m_previewScaleY;
1727
1728 wxRect devicePaperRect = m_previewPrintout->GetPaperRectPixels();
1729 wxCoord devicePrintableWidth, devicePrintableHeight;
1730 m_previewPrintout->GetPageSizePixels(&devicePrintableWidth, &devicePrintableHeight);
1731 float scaleX = screenPrintableWidth / devicePrintableWidth;
1732 float scaleY = screenPrintableHeight / devicePrintableHeight;
1733 paperRect.width = wxCoord(scaleX * devicePaperRect.width);
1734 paperRect.height = wxCoord(scaleY * devicePaperRect.height);
1735
1736 paperRect.x = wxCoord((canvasWidth - paperRect.width)/ 2.0);
1737 if (paperRect.x < m_leftMargin)
1738 paperRect.x = m_leftMargin;
1739 paperRect.y = wxCoord((canvasHeight - paperRect.height)/ 2.0);
1740 if (paperRect.y < m_topMargin)
1741 paperRect.y = m_topMargin;
1742
1743 pageRect.x = paperRect.x - wxCoord(scaleX * devicePaperRect.x);
1744 pageRect.y = paperRect.y - wxCoord(scaleY * devicePaperRect.y);
1745 pageRect.width = wxCoord(screenPrintableWidth);
1746 pageRect.height = wxCoord(screenPrintableHeight);
1747 }
1748
1749
1750 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1751 {
1752 wxDELETE(m_previewBitmap);
1753 // if there was a problem with rendering the preview, try again now
1754 // that it changed in some way (less memory may be needed, for example):
1755 m_previewFailed = false;
1756 }
1757
1758 bool wxPrintPreviewBase::UpdatePageRendering()
1759 {
1760 if ( m_previewBitmap )
1761 return false;
1762
1763 if ( m_previewFailed )
1764 return false;
1765
1766 if ( !RenderPage(m_currentPage) )
1767 {
1768 m_previewFailed = true; // don't waste time failing again
1769 return false;
1770 }
1771
1772 return true;
1773 }
1774
1775 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
1776 {
1777 DrawBlankPage(canvas, dc);
1778
1779 if (!m_previewBitmap)
1780 return false;
1781 if (!canvas)
1782 return false;
1783
1784 wxRect pageRect, paperRect;
1785 CalcRects(canvas, pageRect, paperRect);
1786 wxMemoryDC temp_dc;
1787 temp_dc.SelectObject(*m_previewBitmap);
1788
1789 dc.Blit(pageRect.x, pageRect.y,
1790 m_previewBitmap->GetWidth(), m_previewBitmap->GetHeight(), &temp_dc, 0, 0);
1791
1792 temp_dc.SelectObject(wxNullBitmap);
1793 return true;
1794 }
1795
1796 // Adjusts the scrollbars for the current scale
1797 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas *canvas)
1798 {
1799 if (!canvas)
1800 return ;
1801
1802 wxRect pageRect, paperRect;
1803 CalcRects(canvas, pageRect, paperRect);
1804 int totalWidth = paperRect.width + 2 * m_leftMargin;
1805 int totalHeight = paperRect.height + 2 * m_topMargin;
1806 int scrollUnitsX = totalWidth / 10;
1807 int scrollUnitsY = totalHeight / 10;
1808 wxSize virtualSize = canvas->GetVirtualSize();
1809 if (virtualSize.GetWidth() != totalWidth || virtualSize.GetHeight() != totalHeight)
1810 canvas->SetScrollbars(10, 10, scrollUnitsX, scrollUnitsY, 0, 0, true);
1811 }
1812
1813 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC& dc, int pageNum)
1814 {
1815 m_previewPrintout->SetDC(&dc);
1816 m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
1817
1818 // Need to delay OnPreparePrinting() until here, so we have enough
1819 // information.
1820 if (!m_printingPrepared)
1821 {
1822 m_previewPrintout->OnPreparePrinting();
1823 int selFrom, selTo;
1824 m_previewPrintout->GetPageInfo(&m_minPage, &m_maxPage, &selFrom, &selTo);
1825 m_printingPrepared = true;
1826 }
1827
1828 m_previewPrintout->OnBeginPrinting();
1829
1830 if (!m_previewPrintout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
1831 {
1832 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK);
1833 return false;
1834 }
1835
1836 m_previewPrintout->OnPrintPage(pageNum);
1837 m_previewPrintout->OnEndDocument();
1838 m_previewPrintout->OnEndPrinting();
1839
1840 m_previewPrintout->SetDC(NULL);
1841
1842 return true;
1843 }
1844
1845 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap& bmp, int pageNum)
1846 {
1847 wxMemoryDC memoryDC;
1848 memoryDC.SelectObject(bmp);
1849 memoryDC.Clear();
1850
1851 return RenderPageIntoDC(memoryDC, pageNum);
1852 }
1853
1854 bool wxPrintPreviewBase::RenderPage(int pageNum)
1855 {
1856 wxBusyCursor busy;
1857
1858 if (!m_previewCanvas)
1859 {
1860 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1861 return false;
1862 }
1863
1864 wxRect pageRect, paperRect;
1865 CalcRects(m_previewCanvas, pageRect, paperRect);
1866
1867 if (!m_previewBitmap)
1868 {
1869 m_previewBitmap = new wxBitmap(pageRect.width, pageRect.height);
1870
1871 if (!m_previewBitmap || !m_previewBitmap->Ok())
1872 {
1873 InvalidatePreviewBitmap();
1874 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
1875 return false;
1876 }
1877 }
1878
1879 if ( !RenderPageIntoBitmap(*m_previewBitmap, pageNum) )
1880 {
1881 InvalidatePreviewBitmap();
1882 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
1883 return false;
1884 }
1885
1886 #if wxUSE_STATUSBAR
1887 wxString status;
1888 if (m_maxPage != 0)
1889 status = wxString::Format(_("Page %d of %d"), pageNum, m_maxPage);
1890 else
1891 status = wxString::Format(_("Page %d"), pageNum);
1892
1893 if (m_previewFrame)
1894 m_previewFrame->SetStatusText(status);
1895 #endif
1896
1897 return true;
1898 }
1899
1900 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
1901 {
1902 wxRect pageRect, paperRect;
1903
1904 CalcRects(canvas, pageRect, paperRect);
1905
1906 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
1907 wxCoord shadowOffset = 4;
1908
1909 dc.SetPen(*wxBLACK_PEN);
1910 dc.SetBrush(*wxBLACK_BRUSH);
1911 dc.DrawRectangle(paperRect.x + shadowOffset, paperRect.y + paperRect.height + 1,
1912 paperRect.width, shadowOffset);
1913
1914 dc.DrawRectangle(paperRect.x + paperRect.width, paperRect.y + shadowOffset,
1915 shadowOffset, paperRect.height);
1916
1917 // Draw blank page allowing for 1-pixel border AROUND the actual paper
1918 dc.SetPen(*wxBLACK_PEN);
1919 dc.SetBrush(*wxWHITE_BRUSH);
1920 dc.DrawRectangle(paperRect.x - 2, paperRect.y - 1,
1921 paperRect.width + 3, paperRect.height + 2);
1922
1923 return true;
1924 }
1925
1926 void wxPrintPreviewBase::SetZoom(int percent)
1927 {
1928 if (m_currentZoom == percent)
1929 return;
1930
1931 m_currentZoom = percent;
1932
1933 InvalidatePreviewBitmap();
1934
1935 if (m_previewCanvas)
1936 {
1937 AdjustScrollbars(m_previewCanvas);
1938 ((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
1939 m_previewCanvas->ClearBackground();
1940 m_previewCanvas->Refresh();
1941 m_previewCanvas->SetFocus();
1942 }
1943 }
1944
1945 wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
1946 {
1947 return m_printDialogData;
1948 }
1949
1950 int wxPrintPreviewBase::GetZoom() const
1951 { return m_currentZoom; }
1952 int wxPrintPreviewBase::GetMaxPage() const
1953 { return m_maxPage; }
1954 int wxPrintPreviewBase::GetMinPage() const
1955 { return m_minPage; }
1956 bool wxPrintPreviewBase::IsOk() const
1957 { return m_isOk; }
1958 void wxPrintPreviewBase::SetOk(bool ok)
1959 { m_isOk = ok; }
1960
1961 //----------------------------------------------------------------------------
1962 // wxPrintPreview
1963 //----------------------------------------------------------------------------
1964
1965 IMPLEMENT_CLASS(wxPrintPreview, wxPrintPreviewBase)
1966
1967 wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1968 wxPrintout *printoutForPrinting,
1969 wxPrintDialogData *data) :
1970 wxPrintPreviewBase( printout, printoutForPrinting, data )
1971 {
1972 m_pimpl = wxPrintFactory::GetFactory()->
1973 CreatePrintPreview( printout, printoutForPrinting, data );
1974 }
1975
1976 wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1977 wxPrintout *printoutForPrinting,
1978 wxPrintData *data ) :
1979 wxPrintPreviewBase( printout, printoutForPrinting, data )
1980 {
1981 m_pimpl = wxPrintFactory::GetFactory()->
1982 CreatePrintPreview( printout, printoutForPrinting, data );
1983 }
1984
1985 wxPrintPreview::~wxPrintPreview()
1986 {
1987 delete m_pimpl;
1988
1989 // don't delete twice
1990 m_printPrintout = NULL;
1991 m_previewPrintout = NULL;
1992 m_previewBitmap = NULL;
1993 }
1994
1995 bool wxPrintPreview::SetCurrentPage(int pageNum)
1996 {
1997 return m_pimpl->SetCurrentPage( pageNum );
1998 }
1999
2000 int wxPrintPreview::GetCurrentPage() const
2001 {
2002 return m_pimpl->GetCurrentPage();
2003 }
2004
2005 void wxPrintPreview::SetPrintout(wxPrintout *printout)
2006 {
2007 m_pimpl->SetPrintout( printout );
2008 }
2009
2010 wxPrintout *wxPrintPreview::GetPrintout() const
2011 {
2012 return m_pimpl->GetPrintout();
2013 }
2014
2015 wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
2016 {
2017 return m_pimpl->GetPrintoutForPrinting();
2018 }
2019
2020 void wxPrintPreview::SetFrame(wxFrame *frame)
2021 {
2022 m_pimpl->SetFrame( frame );
2023 }
2024
2025 void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
2026 {
2027 m_pimpl->SetCanvas( canvas );
2028 }
2029
2030 wxFrame *wxPrintPreview::GetFrame() const
2031 {
2032 return m_pimpl->GetFrame();
2033 }
2034
2035 wxPreviewCanvas *wxPrintPreview::GetCanvas() const
2036 {
2037 return m_pimpl->GetCanvas();
2038 }
2039
2040 bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
2041 {
2042 return m_pimpl->PaintPage( canvas, dc );
2043 }
2044
2045 bool wxPrintPreview::UpdatePageRendering()
2046 {
2047 return m_pimpl->UpdatePageRendering();
2048 }
2049
2050 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
2051 {
2052 return m_pimpl->DrawBlankPage( canvas, dc );
2053 }
2054
2055 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas *canvas)
2056 {
2057 m_pimpl->AdjustScrollbars( canvas );
2058 }
2059
2060 bool wxPrintPreview::RenderPage(int pageNum)
2061 {
2062 return m_pimpl->RenderPage( pageNum );
2063 }
2064
2065 void wxPrintPreview::SetZoom(int percent)
2066 {
2067 m_pimpl->SetZoom( percent );
2068 }
2069
2070 int wxPrintPreview::GetZoom() const
2071 {
2072 return m_pimpl->GetZoom();
2073 }
2074
2075 wxPrintDialogData& wxPrintPreview::GetPrintDialogData()
2076 {
2077 return m_pimpl->GetPrintDialogData();
2078 }
2079
2080 int wxPrintPreview::GetMaxPage() const
2081 {
2082 return m_pimpl->GetMaxPage();
2083 }
2084
2085 int wxPrintPreview::GetMinPage() const
2086 {
2087 return m_pimpl->GetMinPage();
2088 }
2089
2090 bool wxPrintPreview::IsOk() const
2091 {
2092 return m_pimpl->Ok();
2093 }
2094
2095 void wxPrintPreview::SetOk(bool ok)
2096 {
2097 m_pimpl->SetOk( ok );
2098 }
2099
2100 bool wxPrintPreview::Print(bool interactive)
2101 {
2102 return m_pimpl->Print( interactive );
2103 }
2104
2105 void wxPrintPreview::DetermineScaling()
2106 {
2107 m_pimpl->DetermineScaling();
2108 }
2109
2110 #endif // wxUSE_PRINTING_ARCHITECTURE