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: prntbase.cpp 60850 2009-06-01 10:16:13Z JS $
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 // change this to 1 to use experimental high-quality printing on Windows
22 // (NB: this can't be in msw/printwin.cpp because of binary compatibility)
23 #define wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW 0
24 
25 #if wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
26     #if !defined(__WXMSW__) || !wxUSE_IMAGE || !wxUSE_WXDIB
27         #undef wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
28         #define wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW 0
29     #endif
30 #endif
31 
32 #if wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
33 #include "wx/msw/enhmeta.h"
34 #endif
35 
36 #if wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW && !wxUSE_ENH_METAFILE_FROM_DC
37 #error Please set wxUSE_ENH_METAFILE_FROM_DC to 1 in include/wx/msw/enhmeta.h.
38 #endif
39 
40 #include "wx/dcprint.h"
41 
42 #ifndef WX_PRECOMP
43     #if defined(__WXMSW__)
44         #include "wx/msw/wrapcdlg.h"
45     #endif // MSW
46     #include "wx/utils.h"
47     #include "wx/dc.h"
48     #include "wx/app.h"
49     #include "wx/math.h"
50     #include "wx/msgdlg.h"
51     #include "wx/layout.h"
52     #include "wx/choice.h"
53     #include "wx/button.h"
54     #include "wx/settings.h"
55     #include "wx/dcmemory.h"
56     #include "wx/stattext.h"
57     #include "wx/intl.h"
58     #include "wx/textdlg.h"
59     #include "wx/sizer.h"
60     #include "wx/module.h"
61 #endif // !WX_PRECOMP
62 
63 #include "wx/prntbase.h"
64 #include "wx/printdlg.h"
65 #include "wx/print.h"
66 #include "wx/dcprint.h"
67 
68 #include <stdlib.h>
69 #include <string.h>
70 
71 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
72 #include "wx/msw/printdlg.h"
73 #elif defined(__WXMAC__)
74 #include "wx/mac/printdlg.h"
75 #include "wx/mac/private/print.h"
76 #else
77 #include "wx/generic/prntdlgg.h"
78 #include "wx/dcps.h"
79 #endif
80 
81 #ifdef __WXMSW__
82     #ifndef __WIN32__
83         #include <print.h>
84     #endif
85 #endif // __WXMSW__
86 
87 #if wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
88 
89 #include "wx/msw/dib.h"
90 #include "wx/image.h"
91 
92 typedef bool (wxPrintPreviewBase::*RenderPageIntoDCFunc)(wxDC&, int);
93 static bool RenderPageIntoBitmapHQ(wxPrintPreviewBase *preview,
94                                    RenderPageIntoDCFunc RenderPageIntoDC,
95                                    wxBitmap& bmp, int pageNum);
96 #endif // wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
97 
98 //----------------------------------------------------------------------------
99 // wxPrintFactory
100 //----------------------------------------------------------------------------
101 
102 wxPrintFactory *wxPrintFactory::m_factory = NULL;
103 
SetPrintFactory(wxPrintFactory * factory)104 void wxPrintFactory::SetPrintFactory( wxPrintFactory *factory )
105 {
106     if (wxPrintFactory::m_factory)
107         delete wxPrintFactory::m_factory;
108 
109     wxPrintFactory::m_factory = factory;
110 }
111 
GetFactory()112 wxPrintFactory *wxPrintFactory::GetFactory()
113 {
114     if (!wxPrintFactory::m_factory)
115         wxPrintFactory::m_factory = new wxNativePrintFactory;
116 
117     return wxPrintFactory::m_factory;
118 }
119 
120 //----------------------------------------------------------------------------
121 // wxNativePrintFactory
122 //----------------------------------------------------------------------------
123 
CreatePrinter(wxPrintDialogData * data)124 wxPrinterBase *wxNativePrintFactory::CreatePrinter( wxPrintDialogData *data )
125 {
126 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
127     return new wxWindowsPrinter( data );
128 #elif defined(__WXMAC__)
129     return new wxMacPrinter( data );
130 #elif defined(__WXPM__)
131     return new wxOS2Printer( data );
132 #else
133     return new wxPostScriptPrinter( data );
134 #endif
135 }
136 
CreatePrintPreview(wxPrintout * preview,wxPrintout * printout,wxPrintDialogData * data)137 wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
138     wxPrintout *printout, wxPrintDialogData *data )
139 {
140 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
141     return new wxWindowsPrintPreview( preview, printout, data );
142 #elif defined(__WXMAC__)
143     return new wxMacPrintPreview( preview, printout, data );
144 #elif defined(__WXPM__)
145     return new wxOS2PrintPreview( preview, printout, data );
146 #else
147     return new wxPostScriptPrintPreview( preview, printout, data );
148 #endif
149 }
150 
CreatePrintPreview(wxPrintout * preview,wxPrintout * printout,wxPrintData * data)151 wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
152     wxPrintout *printout, wxPrintData *data )
153 {
154 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
155     return new wxWindowsPrintPreview( preview, printout, data );
156 #elif defined(__WXMAC__)
157     return new wxMacPrintPreview( preview, printout, data );
158 #elif defined(__WXPM__)
159     return new wxOS2PrintPreview( preview, printout, data );
160 #else
161     return new wxPostScriptPrintPreview( preview, printout, data );
162 #endif
163 }
164 
CreatePrintDialog(wxWindow * parent,wxPrintDialogData * data)165 wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
166                                                   wxPrintDialogData *data )
167 {
168 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
169     return new wxWindowsPrintDialog( parent, data );
170 #elif defined(__WXMAC__)
171     return new wxMacPrintDialog( parent, data );
172 #else
173     return new wxGenericPrintDialog( parent, data );
174 #endif
175 }
176 
CreatePrintDialog(wxWindow * parent,wxPrintData * data)177 wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
178                                                   wxPrintData *data )
179 {
180 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
181     return new wxWindowsPrintDialog( parent, data );
182 #elif defined(__WXMAC__)
183     return new wxMacPrintDialog( parent, data );
184 #else
185     return new wxGenericPrintDialog( parent, data );
186 #endif
187 }
188 
CreatePageSetupDialog(wxWindow * parent,wxPageSetupDialogData * data)189 wxPageSetupDialogBase *wxNativePrintFactory::CreatePageSetupDialog( wxWindow *parent,
190                                                   wxPageSetupDialogData *data )
191 {
192 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
193     return new wxWindowsPageSetupDialog( parent, data );
194 #elif defined(__WXMAC__)
195     return new wxMacPageSetupDialog( parent, data );
196 #else
197     return new wxGenericPageSetupDialog( parent, data );
198 #endif
199 }
200 
HasPrintSetupDialog()201 bool wxNativePrintFactory::HasPrintSetupDialog()
202 {
203 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
204     return false;
205 #elif defined(__WXMAC__)
206     return false;
207 #else
208     // Only here do we need to provide the print setup
209     // dialog ourselves, the other platforms either have
210     // none, don't make it accessible or let you configure
211     // the printer from the wxPrintDialog anyway.
212     return true;
213 #endif
214 
215 }
216 
CreatePrintSetupDialog(wxWindow * parent,wxPrintData * data)217 wxDialog *wxNativePrintFactory::CreatePrintSetupDialog( wxWindow *parent,
218                                                         wxPrintData *data )
219 {
220 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
221     wxUnusedVar(parent);
222     wxUnusedVar(data);
223     return NULL;
224 #elif defined(__WXMAC__)
225     wxUnusedVar(parent);
226     wxUnusedVar(data);
227     return NULL;
228 #else
229     // Only here do we need to provide the print setup
230     // dialog ourselves, the other platforms either have
231     // none, don't make it accessible or let you configure
232     // the printer from the wxPrintDialog anyway.
233     return new wxGenericPrintSetupDialog( parent, data );
234 #endif
235 }
236 
CreatePrinterDC(const wxPrintData & data)237 wxDC* wxNativePrintFactory::CreatePrinterDC( const wxPrintData& data )
238 {
239 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
240     return new wxPrinterDC(data);
241 #elif defined(__WXMAC__)
242     return new wxPrinterDC(data);
243 #else
244     return new wxPostScriptDC(data);
245 #endif
246 }
247 
HasOwnPrintToFile()248 bool wxNativePrintFactory::HasOwnPrintToFile()
249 {
250     // Only relevant for PostScript and here the
251     // setup dialog provides no "print to file"
252     // option. In the GNOME setup dialog, the
253     // setup dialog has its own print to file.
254     return false;
255 }
256 
HasPrinterLine()257 bool wxNativePrintFactory::HasPrinterLine()
258 {
259     // Only relevant for PostScript for now
260     return true;
261 }
262 
CreatePrinterLine()263 wxString wxNativePrintFactory::CreatePrinterLine()
264 {
265     // Only relevant for PostScript for now
266 
267     // We should query "lpstat -d" here
268     return _("Generic PostScript");
269 }
270 
HasStatusLine()271 bool wxNativePrintFactory::HasStatusLine()
272 {
273     // Only relevant for PostScript for now
274     return true;
275 }
276 
CreateStatusLine()277 wxString wxNativePrintFactory::CreateStatusLine()
278 {
279     // Only relevant for PostScript for now
280 
281     // We should query "lpstat -r" or "lpstat -p" here
282     return _("Ready");
283 }
284 
CreatePrintNativeData()285 wxPrintNativeDataBase *wxNativePrintFactory::CreatePrintNativeData()
286 {
287 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
288     return new wxWindowsPrintNativeData;
289 #elif defined(__WXMAC__)
290     return new wxMacCarbonPrintData;
291 #else
292     return new wxPostScriptPrintNativeData;
293 #endif
294 }
295 
296 //----------------------------------------------------------------------------
297 // wxPrintNativeDataBase
298 //----------------------------------------------------------------------------
299 
IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase,wxObject)300 IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase, wxObject)
301 
302 wxPrintNativeDataBase::wxPrintNativeDataBase()
303 {
304     m_ref = 1;
305 }
306 
307 //----------------------------------------------------------------------------
308 // wxPrintFactoryModule
309 //----------------------------------------------------------------------------
310 
311 class wxPrintFactoryModule: public wxModule
312 {
313 public:
wxPrintFactoryModule()314     wxPrintFactoryModule() {}
OnInit()315     bool OnInit() { return true; }
OnExit()316     void OnExit() { wxPrintFactory::SetPrintFactory( NULL ); }
317 
318 private:
319     DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule)
320 };
321 
IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule,wxModule)322 IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule, wxModule)
323 
324 //----------------------------------------------------------------------------
325 // wxPrinterBase
326 //----------------------------------------------------------------------------
327 
328 IMPLEMENT_CLASS(wxPrinterBase, wxObject)
329 
330 wxPrinterBase::wxPrinterBase(wxPrintDialogData *data)
331 {
332     m_currentPrintout = (wxPrintout *) NULL;
333     sm_abortWindow = (wxWindow *) NULL;
334     sm_abortIt = false;
335     if (data)
336         m_printDialogData = (*data);
337     sm_lastError = wxPRINTER_NO_ERROR;
338 }
339 
340 wxWindow *wxPrinterBase::sm_abortWindow = (wxWindow *) NULL;
341 bool wxPrinterBase::sm_abortIt = false;
342 wxPrinterError wxPrinterBase::sm_lastError = wxPRINTER_NO_ERROR;
343 
~wxPrinterBase()344 wxPrinterBase::~wxPrinterBase()
345 {
346 }
347 
CreateAbortWindow(wxWindow * parent,wxPrintout * printout)348 wxWindow *wxPrinterBase::CreateAbortWindow(wxWindow *parent, wxPrintout * printout)
349 {
350     wxPrintAbortDialog *dialog = new wxPrintAbortDialog(parent, _("Printing ") , wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE);
351 
352     wxBoxSizer *button_sizer = new wxBoxSizer( wxVERTICAL );
353     button_sizer->Add( new wxStaticText(dialog, wxID_ANY, _("Please wait while printing\n") + printout->GetTitle() ), 0, wxALL, 10 );
354     button_sizer->Add( new wxButton( dialog, wxID_CANCEL, wxT("Cancel") ), 0, wxALL | wxALIGN_CENTER, 10 );
355 
356     dialog->SetAutoLayout( true );
357     dialog->SetSizer( button_sizer );
358 
359     button_sizer->Fit(dialog);
360     button_sizer->SetSizeHints (dialog) ;
361 
362     return dialog;
363 }
364 
ReportError(wxWindow * parent,wxPrintout * WXUNUSED (printout),const wxString & message)365 void wxPrinterBase::ReportError(wxWindow *parent, wxPrintout *WXUNUSED(printout), const wxString& message)
366 {
367     wxMessageBox(message, _("Printing Error"), wxOK, parent);
368 }
369 
GetPrintDialogData() const370 wxPrintDialogData& wxPrinterBase::GetPrintDialogData() const
371 {
372     return (wxPrintDialogData&) m_printDialogData;
373 }
374 
375 //----------------------------------------------------------------------------
376 // wxPrinter
377 //----------------------------------------------------------------------------
378 
IMPLEMENT_CLASS(wxPrinter,wxPrinterBase)379 IMPLEMENT_CLASS(wxPrinter, wxPrinterBase)
380 
381 wxPrinter::wxPrinter(wxPrintDialogData *data)
382 {
383     m_pimpl = wxPrintFactory::GetFactory()->CreatePrinter( data );
384 }
385 
~wxPrinter()386 wxPrinter::~wxPrinter()
387 {
388     delete m_pimpl;
389 }
390 
CreateAbortWindow(wxWindow * parent,wxPrintout * printout)391 wxWindow *wxPrinter::CreateAbortWindow(wxWindow *parent, wxPrintout *printout)
392 {
393     return m_pimpl->CreateAbortWindow( parent, printout );
394 }
395 
ReportError(wxWindow * parent,wxPrintout * printout,const wxString & message)396 void wxPrinter::ReportError(wxWindow *parent, wxPrintout *printout, const wxString& message)
397 {
398     m_pimpl->ReportError( parent, printout, message );
399 }
400 
Setup(wxWindow * parent)401 bool wxPrinter::Setup(wxWindow *parent)
402 {
403     return m_pimpl->Setup( parent );
404 }
405 
Print(wxWindow * parent,wxPrintout * printout,bool prompt)406 bool wxPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
407 {
408     return m_pimpl->Print( parent, printout, prompt );
409 }
410 
PrintDialog(wxWindow * parent)411 wxDC* wxPrinter::PrintDialog(wxWindow *parent)
412 {
413     return m_pimpl->PrintDialog( parent );
414 }
415 
GetPrintDialogData() const416 wxPrintDialogData& wxPrinter::GetPrintDialogData() const
417 {
418     return m_pimpl->GetPrintDialogData();
419 }
420 
421 // ---------------------------------------------------------------------------
422 // wxPrintDialogBase: the dialog for printing.
423 // ---------------------------------------------------------------------------
424 
IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase,wxDialog)425 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase, wxDialog)
426 
427 wxPrintDialogBase::wxPrintDialogBase(wxWindow *parent,
428                                      wxWindowID id,
429                                      const wxString &title,
430                                      const wxPoint &pos,
431                                      const wxSize &size,
432                                      long style)
433     : wxDialog( parent, id, title.empty() ? wxString(_("Print")) : title,
434                 pos, size, style )
435 {
436 }
437 
438 // ---------------------------------------------------------------------------
439 // wxPrintDialog: the dialog for printing
440 // ---------------------------------------------------------------------------
441 
IMPLEMENT_CLASS(wxPrintDialog,wxObject)442 IMPLEMENT_CLASS(wxPrintDialog, wxObject)
443 
444 wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintDialogData* data)
445 {
446     m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
447 }
448 
wxPrintDialog(wxWindow * parent,wxPrintData * data)449 wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintData* data)
450 {
451     m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
452 }
453 
~wxPrintDialog()454 wxPrintDialog::~wxPrintDialog()
455 {
456     delete m_pimpl;
457 }
458 
ShowModal()459 int wxPrintDialog::ShowModal()
460 {
461     return m_pimpl->ShowModal();
462 }
463 
GetPrintDialogData()464 wxPrintDialogData& wxPrintDialog::GetPrintDialogData()
465 {
466     return m_pimpl->GetPrintDialogData();
467 }
468 
GetPrintData()469 wxPrintData& wxPrintDialog::GetPrintData()
470 {
471     return m_pimpl->GetPrintData();
472 }
473 
GetPrintDC()474 wxDC *wxPrintDialog::GetPrintDC()
475 {
476     return m_pimpl->GetPrintDC();
477 }
478 
479 // ---------------------------------------------------------------------------
480 // wxPageSetupDialogBase: the page setup dialog
481 // ---------------------------------------------------------------------------
482 
IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase,wxDialog)483 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase, wxDialog)
484 
485 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow *parent,
486                                      wxWindowID id,
487                                      const wxString &title,
488                                      const wxPoint &pos,
489                                      const wxSize &size,
490                                      long style)
491     : wxDialog( parent, id, title.empty() ? wxString(_("Page setup")) : title,
492                 pos, size, style )
493 {
494 }
495 
496 // ---------------------------------------------------------------------------
497 // wxPageSetupDialog: the page setup dialog
498 // ---------------------------------------------------------------------------
499 
IMPLEMENT_CLASS(wxPageSetupDialog,wxObject)500 IMPLEMENT_CLASS(wxPageSetupDialog, wxObject)
501 
502 wxPageSetupDialog::wxPageSetupDialog(wxWindow *parent, wxPageSetupDialogData *data )
503 {
504     m_pimpl = wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent, data );
505 }
506 
~wxPageSetupDialog()507 wxPageSetupDialog::~wxPageSetupDialog()
508 {
509     delete m_pimpl;
510 }
511 
ShowModal()512 int wxPageSetupDialog::ShowModal()
513 {
514     return m_pimpl->ShowModal();
515 }
516 
GetPageSetupDialogData()517 wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupDialogData()
518 {
519     return m_pimpl->GetPageSetupDialogData();
520 }
521 
522 // old name
GetPageSetupData()523 wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupData()
524 {
525     return m_pimpl->GetPageSetupDialogData();
526 }
527 
528 //----------------------------------------------------------------------------
529 // wxPrintAbortDialog
530 //----------------------------------------------------------------------------
531 
BEGIN_EVENT_TABLE(wxPrintAbortDialog,wxDialog)532 BEGIN_EVENT_TABLE(wxPrintAbortDialog, wxDialog)
533     EVT_BUTTON(wxID_CANCEL, wxPrintAbortDialog::OnCancel)
534 END_EVENT_TABLE()
535 
536 void wxPrintAbortDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
537 {
538     wxPrinterBase::sm_abortIt = true;
539     wxPrinterBase::sm_abortWindow->Show(false);
540     wxPrinterBase::sm_abortWindow->Close(true);
541     wxPrinterBase::sm_abortWindow->Destroy();
542     wxPrinterBase::sm_abortWindow = (wxWindow *) NULL;
543 }
544 
545 //----------------------------------------------------------------------------
546 // wxPrintout
547 //----------------------------------------------------------------------------
548 
IMPLEMENT_ABSTRACT_CLASS(wxPrintout,wxObject)549 IMPLEMENT_ABSTRACT_CLASS(wxPrintout, wxObject)
550 
551 wxPrintout::wxPrintout(const wxString& title)
552 {
553     m_printoutTitle = title ;
554     m_printoutDC = (wxDC *) NULL;
555     m_pageWidthMM = 0;
556     m_pageHeightMM = 0;
557     m_pageWidthPixels = 0;
558     m_pageHeightPixels = 0;
559     m_PPIScreenX = 0;
560     m_PPIScreenY = 0;
561     m_PPIPrinterX = 0;
562     m_PPIPrinterY = 0;
563     m_isPreview = false;
564 }
565 
~wxPrintout()566 wxPrintout::~wxPrintout()
567 {
568 }
569 
OnBeginDocument(int WXUNUSED (startPage),int WXUNUSED (endPage))570 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage), int WXUNUSED(endPage))
571 {
572     return GetDC()->StartDoc(_("Printing ") + m_printoutTitle);
573 }
574 
OnEndDocument()575 void wxPrintout::OnEndDocument()
576 {
577     GetDC()->EndDoc();
578 }
579 
OnBeginPrinting()580 void wxPrintout::OnBeginPrinting()
581 {
582 }
583 
OnEndPrinting()584 void wxPrintout::OnEndPrinting()
585 {
586 }
587 
HasPage(int page)588 bool wxPrintout::HasPage(int page)
589 {
590     return (page == 1);
591 }
592 
GetPageInfo(int * minPage,int * maxPage,int * fromPage,int * toPage)593 void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toPage)
594 {
595     *minPage = 1;
596     *maxPage = 32000;
597     *fromPage = 1;
598     *toPage = 1;
599 }
600 
FitThisSizeToPaper(const wxSize & imageSize)601 void wxPrintout::FitThisSizeToPaper(const wxSize& imageSize)
602 {
603     // Set the DC scale and origin so that the given image size fits within the
604     // entire page and the origin is at the top left corner of the page. Note
605     // that with most printers, portions of the page will be non-printable. Use
606     // this if you're managing your own page margins.
607     if (!m_printoutDC) return;
608     wxRect paperRect = GetPaperRectPixels();
609     wxCoord pw, ph;
610     GetPageSizePixels(&pw, &ph);
611     wxCoord w, h;
612     m_printoutDC->GetSize(&w, &h);
613     float scaleX = ((float(paperRect.width) * w) / (float(pw) * imageSize.x));
614     float scaleY = ((float(paperRect.height) * h) / (float(ph) * imageSize.y));
615     float actualScale = wxMin(scaleX, scaleY);
616     m_printoutDC->SetUserScale(actualScale, actualScale);
617     m_printoutDC->SetDeviceOrigin(0, 0);
618     wxRect logicalPaperRect = GetLogicalPaperRect();
619     SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
620 }
621 
FitThisSizeToPage(const wxSize & imageSize)622 void wxPrintout::FitThisSizeToPage(const wxSize& imageSize)
623 {
624     // Set the DC scale and origin so that the given image size fits within the
625     // printable area of the page and the origin is at the top left corner of
626     // the printable area.
627     if (!m_printoutDC) return;
628     int w, h;
629     m_printoutDC->GetSize(&w, &h);
630     float scaleX = float(w) / imageSize.x;
631     float scaleY = float(h) / imageSize.y;
632     float actualScale = wxMin(scaleX, scaleY);
633     m_printoutDC->SetUserScale(actualScale, actualScale);
634     m_printoutDC->SetDeviceOrigin(0, 0);
635 }
636 
FitThisSizeToPageMargins(const wxSize & imageSize,const wxPageSetupDialogData & pageSetupData)637 void wxPrintout::FitThisSizeToPageMargins(const wxSize& imageSize, const wxPageSetupDialogData& pageSetupData)
638 {
639     // Set the DC scale and origin so that the given image size fits within the
640     // page margins defined in the given wxPageSetupDialogData object and the
641     // origin is at the top left corner of the page margins.
642     if (!m_printoutDC) return;
643     wxRect paperRect = GetPaperRectPixels();
644     wxCoord pw, ph;
645     GetPageSizePixels(&pw, &ph);
646     wxPoint topLeft = pageSetupData.GetMarginTopLeft();
647     wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
648     wxCoord mw, mh;
649     GetPageSizeMM(&mw, &mh);
650     float mmToDeviceX = float(pw) / mw;
651     float mmToDeviceY = float(ph) / mh;
652     wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x),
653         paperRect.y + wxRound(mmToDeviceY * topLeft.y),
654         paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
655         paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
656     wxCoord w, h;
657     m_printoutDC->GetSize(&w, &h);
658     float scaleX = (float(pageMarginsRect.width) * w) / (float(pw) * imageSize.x);
659     float scaleY = (float(pageMarginsRect.height) * h) / (float(ph) * imageSize.y);
660     float actualScale = wxMin(scaleX, scaleY);
661     m_printoutDC->SetUserScale(actualScale, actualScale);
662     m_printoutDC->SetDeviceOrigin(0, 0);
663     wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
664     SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
665 }
666 
MapScreenSizeToPaper()667 void wxPrintout::MapScreenSizeToPaper()
668 {
669     // Set the DC scale so that an image on the screen is the same size on the
670     // paper and the origin is at the top left of the paper. Note that with most
671     // printers, portions of the page will be cut off. Use this if you're
672     // managing your own page margins.
673     if (!m_printoutDC) return;
674     MapScreenSizeToPage();
675     wxRect logicalPaperRect = GetLogicalPaperRect();
676     SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
677 }
678 
MapScreenSizeToPage()679 void wxPrintout::MapScreenSizeToPage()
680 {
681     // Set the DC scale and origin so that an image on the screen is the same
682     // size on the paper and the origin is at the top left of the printable area.
683     if (!m_printoutDC) return;
684     int ppiScreenX, ppiScreenY;
685     GetPPIScreen(&ppiScreenX, &ppiScreenY);
686     int ppiPrinterX, ppiPrinterY;
687     GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
688     int w, h;
689     m_printoutDC->GetSize(&w, &h);
690     int pageSizePixelsX, pageSizePixelsY;
691     GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
692     float userScaleX = (float(ppiPrinterX) * w) / (float(ppiScreenX) * pageSizePixelsX);
693     float userScaleY = (float(ppiPrinterY) * h) / (float(ppiScreenY) * pageSizePixelsY);
694     m_printoutDC->SetUserScale(userScaleX, userScaleY);
695     m_printoutDC->SetDeviceOrigin(0, 0);
696 }
697 
MapScreenSizeToPageMargins(const wxPageSetupDialogData & pageSetupData)698 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData& pageSetupData)
699 {
700     // Set the DC scale so that an image on the screen is the same size on the
701     // paper and the origin is at the top left of the page margins defined by
702     // the given wxPageSetupDialogData object.
703     if (!m_printoutDC) return;
704     MapScreenSizeToPage();
705     wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
706     SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
707 }
708 
MapScreenSizeToDevice()709 void wxPrintout::MapScreenSizeToDevice()
710 {
711     // Set the DC scale so that a screen pixel is the same size as a device
712     // pixel and the origin is at the top left of the printable area.
713     if (!m_printoutDC) return;
714     int w, h;
715     m_printoutDC->GetSize(&w, &h);
716     int pageSizePixelsX, pageSizePixelsY;
717     GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
718     float userScaleX = float(w) / pageSizePixelsX;
719     float userScaleY = float(h) / pageSizePixelsY;
720     m_printoutDC->SetUserScale(userScaleX, userScaleY);
721     m_printoutDC->SetDeviceOrigin(0, 0);
722 }
723 
GetLogicalPaperRect() const724 wxRect wxPrintout::GetLogicalPaperRect() const
725 {
726     // Return the rectangle in logical units that corresponds to the paper
727     // rectangle.
728     wxRect paperRect = GetPaperRectPixels();
729     wxCoord pw, ph;
730     GetPageSizePixels(&pw, &ph);
731     wxCoord w, h;
732     m_printoutDC->GetSize(&w, &h);
733     if (w == pw && h == ph) {
734         // this DC matches the printed page, so no scaling
735         return wxRect(m_printoutDC->DeviceToLogicalX(paperRect.x),
736             m_printoutDC->DeviceToLogicalY(paperRect.y),
737             m_printoutDC->DeviceToLogicalXRel(paperRect.width),
738             m_printoutDC->DeviceToLogicalYRel(paperRect.height));
739     }
740     // This DC doesn't match the printed page, so we have to scale.
741     float scaleX = float(w) / pw;
742     float scaleY = float(h) / ph;
743     return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(paperRect.x * scaleX)),
744         m_printoutDC->DeviceToLogicalY(wxRound(paperRect.y * scaleY)),
745         m_printoutDC->DeviceToLogicalXRel(wxRound(paperRect.width * scaleX)),
746         m_printoutDC->DeviceToLogicalYRel(wxRound(paperRect.height * scaleY)));
747 }
748 
GetLogicalPageRect() const749 wxRect wxPrintout::GetLogicalPageRect() const
750 {
751     // Return the rectangle in logical units that corresponds to the printable
752     // area.
753     int w, h;
754     m_printoutDC->GetSize(&w, &h);
755     return wxRect(m_printoutDC->DeviceToLogicalX(0),
756         m_printoutDC->DeviceToLogicalY(0),
757         m_printoutDC->DeviceToLogicalXRel(w),
758         m_printoutDC->DeviceToLogicalYRel(h));
759 }
760 
GetLogicalPageMarginsRect(const wxPageSetupDialogData & pageSetupData) const761 wxRect wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData& pageSetupData) const
762 {
763     // Return the rectangle in logical units that corresponds to the region
764     // within the page margins as specified by the given wxPageSetupDialogData
765     // object.
766     wxRect paperRect = GetPaperRectPixels();
767     wxCoord pw, ph;
768     GetPageSizePixels(&pw, &ph);
769     wxPoint topLeft = pageSetupData.GetMarginTopLeft();
770     wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
771     wxCoord mw, mh;
772     GetPageSizeMM(&mw, &mh);
773     float mmToDeviceX = float(pw) / mw;
774     float mmToDeviceY = float(ph) / mh;
775     wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x),
776         paperRect.y + wxRound(mmToDeviceY * topLeft.y),
777         paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
778         paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
779     wxCoord w, h;
780     m_printoutDC->GetSize(&w, &h);
781     if (w == pw && h == ph) {
782         // this DC matches the printed page, so no scaling
783         return wxRect(m_printoutDC->DeviceToLogicalX(pageMarginsRect.x),
784             m_printoutDC->DeviceToLogicalY(pageMarginsRect.y),
785             m_printoutDC->DeviceToLogicalXRel(pageMarginsRect.width),
786             m_printoutDC->DeviceToLogicalYRel(pageMarginsRect.height));
787     }
788     // This DC doesn't match the printed page, so we have to scale.
789     float scaleX = float(w) / pw;
790     float scaleY = float(h) / ph;
791     return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(pageMarginsRect.x * scaleX)),
792         m_printoutDC->DeviceToLogicalY(wxRound(pageMarginsRect.y * scaleY)),
793         m_printoutDC->DeviceToLogicalXRel(wxRound(pageMarginsRect.width * scaleX)),
794         m_printoutDC->DeviceToLogicalYRel(wxRound(pageMarginsRect.height * scaleY)));
795 }
796 
SetLogicalOrigin(wxCoord x,wxCoord y)797 void wxPrintout::SetLogicalOrigin(wxCoord x, wxCoord y)
798 {
799     // Set the device origin by specifying a point in logical coordinates.
800     m_printoutDC->SetDeviceOrigin(m_printoutDC->LogicalToDeviceX(x),
801         m_printoutDC->LogicalToDeviceY(y));
802 }
803 
OffsetLogicalOrigin(wxCoord xoff,wxCoord yoff)804 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff, wxCoord yoff)
805 {
806     // Offset the device origin by a specified distance in device coordinates.
807     wxCoord x = m_printoutDC->LogicalToDeviceX(0);
808     wxCoord y = m_printoutDC->LogicalToDeviceY(0);
809     m_printoutDC->SetDeviceOrigin(x + m_printoutDC->LogicalToDeviceXRel(xoff),
810         y + m_printoutDC->LogicalToDeviceYRel(yoff));
811 }
812 
813 
814 //----------------------------------------------------------------------------
815 // wxPreviewCanvas
816 //----------------------------------------------------------------------------
817 
IMPLEMENT_CLASS(wxPreviewCanvas,wxWindow)818 IMPLEMENT_CLASS(wxPreviewCanvas, wxWindow)
819 
820 BEGIN_EVENT_TABLE(wxPreviewCanvas, wxScrolledWindow)
821     EVT_PAINT(wxPreviewCanvas::OnPaint)
822     EVT_CHAR(wxPreviewCanvas::OnChar)
823     EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged)
824 #if wxUSE_MOUSEWHEEL
825     EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel)
826 #endif
827 END_EVENT_TABLE()
828 
829 // VZ: the current code doesn't refresh properly without
830 //     wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
831 //     really horrible flicker when resizing the preview frame, but without
832 //     this style it simply doesn't work correctly at all...
833 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase *preview, wxWindow *parent,
834                                  const wxPoint& pos, const wxSize& size, long style, const wxString& name):
835 wxScrolledWindow(parent, wxID_ANY, pos, size, style | wxFULL_REPAINT_ON_RESIZE, name)
836 {
837     m_printPreview = preview;
838 #ifdef __WXMAC__
839     // The app workspace colour is always white, but we should have
840     // a contrast with the page.
841     wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
842 #elif defined(__WXGTK__)
843     wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
844 #else
845     wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
846 #endif
847     SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
848 
849     SetScrollbars(10, 10, 100, 100);
850 }
851 
~wxPreviewCanvas()852 wxPreviewCanvas::~wxPreviewCanvas()
853 {
854 }
855 
OnPaint(wxPaintEvent & WXUNUSED (event))856 void wxPreviewCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
857 {
858     wxPaintDC dc(this);
859     PrepareDC( dc );
860 
861 /*
862 #ifdef __WXGTK__
863     if (!GetUpdateRegion().IsEmpty())
864         dc.SetClippingRegion( GetUpdateRegion() );
865 #endif
866 */
867 
868     if (m_printPreview)
869     {
870         m_printPreview->PaintPage(this, dc);
871     }
872 }
873 
874 // Responds to colour changes, and passes event on to children.
OnSysColourChanged(wxSysColourChangedEvent & event)875 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent& event)
876 {
877 #ifdef __WXMAC__
878     // The app workspace colour is always white, but we should have
879     // a contrast with the page.
880     wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
881 #elif defined(__WXGTK__)
882     wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
883 #else
884     wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
885 #endif
886     SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
887     Refresh();
888 
889     // Propagate the event to the non-top-level children
890     wxWindow::OnSysColourChanged(event);
891 }
892 
OnChar(wxKeyEvent & event)893 void wxPreviewCanvas::OnChar(wxKeyEvent &event)
894 {
895     wxPreviewControlBar* controlBar = ((wxPreviewFrame*) GetParent())->GetControlBar();
896     if (event.GetKeyCode() == WXK_ESCAPE)
897     {
898         ((wxPreviewFrame*) GetParent())->Close(true);
899         return;
900     }
901     else if (event.GetKeyCode() == WXK_TAB)
902     {
903         controlBar->OnGoto();
904         return;
905     }
906     else if (event.GetKeyCode() == WXK_RETURN)
907     {
908         controlBar->OnPrint();
909         return;
910     }
911 
912     if (!event.ControlDown())
913     {
914         event.Skip();
915         return;
916     }
917 
918     switch(event.GetKeyCode())
919     {
920         case WXK_PAGEDOWN:
921             controlBar->OnNext(); break;
922         case WXK_PAGEUP:
923             controlBar->OnPrevious(); break;
924         case WXK_HOME:
925             controlBar->OnFirst(); break;
926         case WXK_END:
927             controlBar->OnLast(); break;
928         default:
929             event.Skip();
930     }
931 }
932 
933 #if wxUSE_MOUSEWHEEL
934 
OnMouseWheel(wxMouseEvent & event)935 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent& event)
936 {
937     wxPreviewControlBar *
938         controlBar = wxStaticCast(GetParent(), wxPreviewFrame)->GetControlBar();
939 
940     if ( controlBar )
941     {
942         if ( event.ControlDown() && event.GetWheelRotation() != 0 )
943         {
944             int currentZoom = controlBar->GetZoomControl();
945 
946             int delta;
947             if ( currentZoom < 100 )
948                 delta = 5;
949             else if ( currentZoom <= 120 )
950                 delta = 10;
951             else
952                 delta = 50;
953 
954             if ( event.GetWheelRotation() > 0 )
955                 delta = -delta;
956 
957             int newZoom = currentZoom + delta;
958             if ( newZoom < 10 )
959                 newZoom = 10;
960             if ( newZoom > 200 )
961                 newZoom = 200;
962             if ( newZoom != currentZoom )
963             {
964                 controlBar->SetZoomControl(newZoom);
965                 m_printPreview->SetZoom(newZoom);
966                 Refresh();
967             }
968             return;
969         }
970     }
971 
972     event.Skip();
973 }
974 
975 #endif // wxUSE_MOUSEWHEEL
976 
977 //----------------------------------------------------------------------------
978 // wxPreviewControlBar
979 //----------------------------------------------------------------------------
980 
IMPLEMENT_CLASS(wxPreviewControlBar,wxWindow)981 IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
982 
983 BEGIN_EVENT_TABLE(wxPreviewControlBar, wxPanel)
984     EVT_BUTTON(wxID_PREVIEW_CLOSE,    wxPreviewControlBar::OnWindowClose)
985     EVT_BUTTON(wxID_PREVIEW_PRINT,    wxPreviewControlBar::OnPrintButton)
986     EVT_BUTTON(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnPreviousButton)
987     EVT_BUTTON(wxID_PREVIEW_NEXT,     wxPreviewControlBar::OnNextButton)
988     EVT_BUTTON(wxID_PREVIEW_FIRST,    wxPreviewControlBar::OnFirstButton)
989     EVT_BUTTON(wxID_PREVIEW_LAST,     wxPreviewControlBar::OnLastButton)
990     EVT_BUTTON(wxID_PREVIEW_GOTO,     wxPreviewControlBar::OnGotoButton)
991     EVT_CHOICE(wxID_PREVIEW_ZOOM,     wxPreviewControlBar::OnZoom)
992     EVT_PAINT(wxPreviewControlBar::OnPaint)
993 END_EVENT_TABLE()
994 
995 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
996                                          wxWindow *parent, const wxPoint& pos, const wxSize& size,
997                                          long style, const wxString& name):
998 wxPanel(parent, wxID_ANY, pos, size, style, name)
999 {
1000     m_printPreview = preview;
1001     m_closeButton = (wxButton *) NULL;
1002     m_nextPageButton = (wxButton *) NULL;
1003     m_previousPageButton = (wxButton *) NULL;
1004     m_printButton = (wxButton *) NULL;
1005     m_zoomControl = (wxChoice *) NULL;
1006     m_buttonFlags = buttons;
1007 }
1008 
~wxPreviewControlBar()1009 wxPreviewControlBar::~wxPreviewControlBar()
1010 {
1011 }
1012 
OnPaint(wxPaintEvent & WXUNUSED (event))1013 void wxPreviewControlBar::OnPaint(wxPaintEvent& WXUNUSED(event))
1014 {
1015     wxPaintDC dc(this);
1016 
1017     int w, h;
1018     GetSize(&w, &h);
1019     dc.SetPen(*wxBLACK_PEN);
1020     dc.SetBrush(*wxTRANSPARENT_BRUSH);
1021     dc.DrawLine( 0, h-1, w, h-1 );
1022 }
1023 
OnWindowClose(wxCommandEvent & WXUNUSED (event))1024 void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
1025 {
1026     wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
1027     frame->Close(true);
1028 }
1029 
OnPrint(void)1030 void wxPreviewControlBar::OnPrint(void)
1031 {
1032     wxPrintPreviewBase *preview = GetPrintPreview();
1033     preview->Print(true);
1034 }
1035 
OnNext(void)1036 void wxPreviewControlBar::OnNext(void)
1037 {
1038     wxPrintPreviewBase *preview = GetPrintPreview();
1039     if (preview)
1040     {
1041         int currentPage = preview->GetCurrentPage();
1042         if ((preview->GetMaxPage() > 0) &&
1043             (currentPage < preview->GetMaxPage()) &&
1044             preview->GetPrintout()->HasPage(currentPage + 1))
1045         {
1046             preview->SetCurrentPage(currentPage + 1);
1047         }
1048     }
1049 }
1050 
OnPrevious(void)1051 void wxPreviewControlBar::OnPrevious(void)
1052 {
1053     wxPrintPreviewBase *preview = GetPrintPreview();
1054     if (preview)
1055     {
1056         int currentPage = preview->GetCurrentPage();
1057         if ((preview->GetMinPage() > 0) &&
1058             (currentPage > preview->GetMinPage()) &&
1059             preview->GetPrintout()->HasPage(currentPage - 1))
1060         {
1061             preview->SetCurrentPage(currentPage - 1);
1062         }
1063     }
1064 }
1065 
OnFirst(void)1066 void wxPreviewControlBar::OnFirst(void)
1067 {
1068     wxPrintPreviewBase *preview = GetPrintPreview();
1069     if (preview)
1070     {
1071         int currentPage = preview->GetMinPage();
1072         if (preview->GetPrintout()->HasPage(currentPage))
1073         {
1074             preview->SetCurrentPage(currentPage);
1075         }
1076     }
1077 }
1078 
OnLast(void)1079 void wxPreviewControlBar::OnLast(void)
1080 {
1081     wxPrintPreviewBase *preview = GetPrintPreview();
1082     if (preview)
1083     {
1084         int currentPage = preview->GetMaxPage();
1085         if (preview->GetPrintout()->HasPage(currentPage))
1086         {
1087             preview->SetCurrentPage(currentPage);
1088         }
1089     }
1090 }
1091 
OnGoto(void)1092 void wxPreviewControlBar::OnGoto(void)
1093 {
1094     wxPrintPreviewBase *preview = GetPrintPreview();
1095     if (preview)
1096     {
1097         long currentPage;
1098 
1099         if (preview->GetMinPage() > 0)
1100         {
1101             wxString strPrompt;
1102             wxString strPage;
1103 
1104             strPrompt.Printf( _("Enter a page number between %d and %d:"),
1105                 preview->GetMinPage(), preview->GetMaxPage());
1106             strPage.Printf( wxT("%d"), preview->GetCurrentPage() );
1107 
1108             strPage =
1109                 wxGetTextFromUser( strPrompt, _("Goto Page"), strPage, GetParent());
1110 
1111             if ( strPage.ToLong( &currentPage ) )
1112                 if (preview->GetPrintout()->HasPage(currentPage))
1113                 {
1114                     preview->SetCurrentPage(currentPage);
1115                 }
1116         }
1117     }
1118 }
1119 
OnZoom(wxCommandEvent & WXUNUSED (event))1120 void wxPreviewControlBar::OnZoom(wxCommandEvent& WXUNUSED(event))
1121 {
1122     int zoom = GetZoomControl();
1123     if (GetPrintPreview())
1124         GetPrintPreview()->SetZoom(zoom);
1125 }
1126 
CreateButtons()1127 void wxPreviewControlBar::CreateButtons()
1128 {
1129     SetSize(0, 0, 400, 40);
1130 
1131     wxBoxSizer *item0 = new wxBoxSizer( wxHORIZONTAL );
1132 
1133     m_closeButton = new wxButton( this, wxID_PREVIEW_CLOSE, _("&Close"), wxDefaultPosition, wxDefaultSize, 0 );
1134     item0->Add( m_closeButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1135 
1136     if (m_buttonFlags & wxPREVIEW_PRINT)
1137     {
1138         m_printButton = new wxButton( this, wxID_PREVIEW_PRINT, _("&Print..."), wxDefaultPosition, wxDefaultSize, 0 );
1139         item0->Add( m_printButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1140     }
1141 
1142     // Exact-fit buttons are too tiny on wxUniversal
1143     int navButtonStyle;
1144     wxSize navButtonSize;
1145 #ifdef __WXUNIVERSAL__
1146     navButtonStyle = 0;
1147     navButtonSize = wxSize(40, m_closeButton->GetSize().y);
1148 #else
1149     navButtonStyle = wxBU_EXACTFIT;
1150     navButtonSize = wxDefaultSize;
1151 #endif
1152 
1153     if (m_buttonFlags & wxPREVIEW_FIRST)
1154     {
1155         m_firstPageButton = new wxButton( this, wxID_PREVIEW_FIRST, _("|<<"), wxDefaultPosition, navButtonSize, navButtonStyle );
1156         item0->Add( m_firstPageButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1157     }
1158 
1159     if (m_buttonFlags & wxPREVIEW_PREVIOUS)
1160     {
1161         m_previousPageButton = new wxButton( this, wxID_PREVIEW_PREVIOUS, _("<<"), wxDefaultPosition, navButtonSize, navButtonStyle );
1162         item0->Add( m_previousPageButton, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 );
1163     }
1164 
1165     if (m_buttonFlags & wxPREVIEW_NEXT)
1166     {
1167         m_nextPageButton = new wxButton( this, wxID_PREVIEW_NEXT, _(">>"), wxDefaultPosition, navButtonSize, navButtonStyle );
1168         item0->Add( m_nextPageButton, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 );
1169     }
1170 
1171     if (m_buttonFlags & wxPREVIEW_LAST)
1172     {
1173         m_lastPageButton = new wxButton( this, wxID_PREVIEW_LAST, _(">>|"), wxDefaultPosition, navButtonSize, navButtonStyle );
1174         item0->Add( m_lastPageButton, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 );
1175     }
1176 
1177     if (m_buttonFlags & wxPREVIEW_GOTO)
1178     {
1179         m_gotoPageButton = new wxButton( this, wxID_PREVIEW_GOTO, _("&Goto..."), wxDefaultPosition, wxDefaultSize, 0 );
1180         item0->Add( m_gotoPageButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1181     }
1182 
1183     if (m_buttonFlags & wxPREVIEW_ZOOM)
1184     {
1185         wxString choices[] =
1186         {
1187             wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1188                 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1189                 wxT("120%"), wxT("150%"), wxT("200%")
1190         };
1191         int n = WXSIZEOF(choices);
1192 
1193         m_zoomControl = new wxChoice( this, wxID_PREVIEW_ZOOM, wxDefaultPosition, wxSize(70,wxDefaultCoord), n, choices, 0 );
1194         item0->Add( m_zoomControl, 0, wxALIGN_CENTRE|wxALL, 5 );
1195         SetZoomControl(m_printPreview->GetZoom());
1196     }
1197 
1198     SetSizer(item0);
1199     item0->Fit(this);
1200 }
1201 
SetZoomControl(int zoom)1202 void wxPreviewControlBar::SetZoomControl(int zoom)
1203 {
1204     if (m_zoomControl)
1205     {
1206         int n, count = m_zoomControl->GetCount();
1207         long val;
1208         for (n=0; n<count; n++)
1209         {
1210             if (m_zoomControl->GetString(n).BeforeFirst(wxT('%')).ToLong(&val) &&
1211                 (val >= long(zoom)))
1212             {
1213                 m_zoomControl->SetSelection(n);
1214                 return;
1215             }
1216         }
1217 
1218         m_zoomControl->SetSelection(count-1);
1219     }
1220 }
1221 
GetZoomControl()1222 int wxPreviewControlBar::GetZoomControl()
1223 {
1224     if (m_zoomControl && (m_zoomControl->GetStringSelection() != wxEmptyString))
1225     {
1226         long val;
1227         if (m_zoomControl->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val))
1228             return int(val);
1229     }
1230 
1231     return 0;
1232 }
1233 
1234 
1235 /*
1236 * Preview frame
1237 */
1238 
IMPLEMENT_CLASS(wxPreviewFrame,wxFrame)1239 IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
1240 
1241 BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
1242     EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
1243 END_EVENT_TABLE()
1244 
1245 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
1246                                const wxPoint& pos, const wxSize& size, long style, const wxString& name):
1247 wxFrame(parent, wxID_ANY, title, pos, size, style, name)
1248 {
1249     m_printPreview = preview;
1250     m_controlBar = NULL;
1251     m_previewCanvas = NULL;
1252     m_windowDisabler = NULL;
1253 
1254     // Give the application icon
1255 #ifdef __WXMSW__
1256     wxFrame* topFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
1257     if (topFrame)
1258         SetIcon(topFrame->GetIcon());
1259 #endif
1260 }
1261 
~wxPreviewFrame()1262 wxPreviewFrame::~wxPreviewFrame()
1263 {
1264 }
1265 
OnCloseWindow(wxCloseEvent & WXUNUSED (event))1266 void wxPreviewFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
1267 {
1268     if (m_windowDisabler)
1269         delete m_windowDisabler;
1270 
1271     // Need to delete the printout and the print preview
1272     wxPrintout *printout = m_printPreview->GetPrintout();
1273     if (printout)
1274     {
1275         delete printout;
1276         m_printPreview->SetPrintout(NULL);
1277         m_printPreview->SetCanvas(NULL);
1278         m_printPreview->SetFrame(NULL);
1279     }
1280     delete m_printPreview;
1281 
1282     Destroy();
1283 }
1284 
Initialize()1285 void wxPreviewFrame::Initialize()
1286 {
1287 #if wxUSE_STATUSBAR
1288     CreateStatusBar();
1289 #endif
1290     CreateCanvas();
1291     CreateControlBar();
1292 
1293     m_printPreview->SetCanvas(m_previewCanvas);
1294     m_printPreview->SetFrame(this);
1295 
1296     wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
1297 
1298     item0->Add( m_controlBar, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1299     item0->Add( m_previewCanvas, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1300 
1301     SetAutoLayout( true );
1302     SetSizer( item0 );
1303 
1304     m_windowDisabler = new wxWindowDisabler(this);
1305 
1306     Layout();
1307 
1308     m_printPreview->AdjustScrollbars(m_previewCanvas);
1309     m_previewCanvas->SetFocus();
1310     m_controlBar->SetFocus();
1311 }
1312 
CreateCanvas()1313 void wxPreviewFrame::CreateCanvas()
1314 {
1315     m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
1316 }
1317 
CreateControlBar()1318 void wxPreviewFrame::CreateControlBar()
1319 {
1320     long buttons = wxPREVIEW_DEFAULT;
1321     if (m_printPreview->GetPrintoutForPrinting())
1322         buttons |= wxPREVIEW_PRINT;
1323 
1324     m_controlBar = new wxPreviewControlBar(m_printPreview, buttons, this, wxPoint(0,0), wxSize(400, 40));
1325     m_controlBar->CreateButtons();
1326 }
1327 
1328 /*
1329 * Print preview
1330 */
1331 
IMPLEMENT_CLASS(wxPrintPreviewBase,wxObject)1332 IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
1333 
1334 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1335                                        wxPrintout *printoutForPrinting,
1336                                        wxPrintData *data)
1337 {
1338     if (data)
1339         m_printDialogData = (*data);
1340 
1341     Init(printout, printoutForPrinting);
1342 }
1343 
wxPrintPreviewBase(wxPrintout * printout,wxPrintout * printoutForPrinting,wxPrintDialogData * data)1344 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1345                                        wxPrintout *printoutForPrinting,
1346                                        wxPrintDialogData *data)
1347 {
1348     if (data)
1349         m_printDialogData = (*data);
1350 
1351     Init(printout, printoutForPrinting);
1352 }
1353 
Init(wxPrintout * printout,wxPrintout * printoutForPrinting)1354 void wxPrintPreviewBase::Init(wxPrintout *printout,
1355                               wxPrintout *printoutForPrinting)
1356 {
1357     m_isOk = true;
1358     m_previewPrintout = printout;
1359     if (m_previewPrintout)
1360         m_previewPrintout->SetIsPreview(true);
1361 
1362     m_printPrintout = printoutForPrinting;
1363 
1364     m_previewCanvas = NULL;
1365     m_previewFrame = NULL;
1366     m_previewBitmap = NULL;
1367     m_currentPage = 1;
1368     m_currentZoom = 70;
1369     m_topMargin = 40;
1370     m_leftMargin = 40;
1371     m_pageWidth = 0;
1372     m_pageHeight = 0;
1373     m_printingPrepared = false;
1374     m_minPage = 1;
1375     m_maxPage = 1;
1376 }
1377 
~wxPrintPreviewBase()1378 wxPrintPreviewBase::~wxPrintPreviewBase()
1379 {
1380     if (m_previewPrintout)
1381         delete m_previewPrintout;
1382     if (m_previewBitmap)
1383         delete m_previewBitmap;
1384     if (m_printPrintout)
1385         delete m_printPrintout;
1386 }
1387 
SetCurrentPage(int pageNum)1388 bool wxPrintPreviewBase::SetCurrentPage(int pageNum)
1389 {
1390     if (m_currentPage == pageNum)
1391         return true;
1392 
1393     m_currentPage = pageNum;
1394     if (m_previewBitmap)
1395     {
1396         delete m_previewBitmap;
1397         m_previewBitmap = NULL;
1398     }
1399 
1400     if (m_previewCanvas)
1401     {
1402         AdjustScrollbars(m_previewCanvas);
1403 
1404         if (!RenderPage(pageNum))
1405             return false;
1406         m_previewCanvas->Refresh();
1407         m_previewCanvas->SetFocus();
1408     }
1409     return true;
1410 }
1411 
GetCurrentPage() const1412 int wxPrintPreviewBase::GetCurrentPage() const
1413     { return m_currentPage; }
SetPrintout(wxPrintout * printout)1414 void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
1415     { m_previewPrintout = printout; }
GetPrintout() const1416 wxPrintout *wxPrintPreviewBase::GetPrintout() const
1417     { return m_previewPrintout; }
GetPrintoutForPrinting() const1418 wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
1419     { return m_printPrintout; }
SetFrame(wxFrame * frame)1420 void wxPrintPreviewBase::SetFrame(wxFrame *frame)
1421     { m_previewFrame = frame; }
SetCanvas(wxPreviewCanvas * canvas)1422 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
1423     { m_previewCanvas = canvas; }
GetFrame() const1424 wxFrame *wxPrintPreviewBase::GetFrame() const
1425     { return m_previewFrame; }
GetCanvas() const1426 wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
1427     { return m_previewCanvas; }
1428 
CalcRects(wxPreviewCanvas * canvas,wxRect & pageRect,wxRect & paperRect)1429 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas *canvas, wxRect& pageRect, wxRect& paperRect)
1430 {
1431     // Calculate the rectangles for the printable area of the page and the
1432     // entire paper as they appear on the canvas on-screen.
1433     int canvasWidth, canvasHeight;
1434     canvas->GetSize(&canvasWidth, &canvasHeight);
1435 
1436     float zoomScale = float(m_currentZoom) / 100;
1437     float screenPrintableWidth = zoomScale * m_pageWidth * m_previewScaleX;
1438     float screenPrintableHeight = zoomScale * m_pageHeight * m_previewScaleY;
1439 
1440     wxRect devicePaperRect = m_previewPrintout->GetPaperRectPixels();
1441     wxCoord devicePrintableWidth, devicePrintableHeight;
1442     m_previewPrintout->GetPageSizePixels(&devicePrintableWidth, &devicePrintableHeight);
1443     float scaleX = screenPrintableWidth / devicePrintableWidth;
1444     float scaleY = screenPrintableHeight / devicePrintableHeight;
1445     paperRect.width = wxCoord(scaleX * devicePaperRect.width);
1446     paperRect.height = wxCoord(scaleY * devicePaperRect.height);
1447 
1448     paperRect.x = wxCoord((canvasWidth - paperRect.width)/ 2.0);
1449     if (paperRect.x < m_leftMargin)
1450         paperRect.x = m_leftMargin;
1451     paperRect.y = wxCoord((canvasHeight - paperRect.height)/ 2.0);
1452     if (paperRect.y < m_topMargin)
1453         paperRect.y = m_topMargin;
1454 
1455     pageRect.x = paperRect.x - wxCoord(scaleX * devicePaperRect.x);
1456     pageRect.y = paperRect.y - wxCoord(scaleY * devicePaperRect.y);
1457     pageRect.width = wxCoord(screenPrintableWidth);
1458     pageRect.height = wxCoord(screenPrintableHeight);
1459 }
1460 
1461 
PaintPage(wxPreviewCanvas * canvas,wxDC & dc)1462 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
1463 {
1464     DrawBlankPage(canvas, dc);
1465 
1466     if (!m_previewBitmap)
1467         if (!RenderPage(m_currentPage))
1468             return false;
1469     if (!m_previewBitmap)
1470         return false;
1471     if (!canvas)
1472         return false;
1473 
1474     wxRect pageRect, paperRect;
1475     CalcRects(canvas, pageRect, paperRect);
1476     wxMemoryDC temp_dc;
1477     temp_dc.SelectObject(*m_previewBitmap);
1478 
1479     dc.Blit(pageRect.x, pageRect.y,
1480         m_previewBitmap->GetWidth(), m_previewBitmap->GetHeight(), &temp_dc, 0, 0);
1481 
1482     temp_dc.SelectObject(wxNullBitmap);
1483     return true;
1484 }
1485 
1486 // Adjusts the scrollbars for the current scale
AdjustScrollbars(wxPreviewCanvas * canvas)1487 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas *canvas)
1488 {
1489     if (!canvas)
1490         return ;
1491 
1492     wxRect pageRect, paperRect;
1493     CalcRects(canvas, pageRect, paperRect);
1494      int totalWidth = paperRect.width + 2 * m_leftMargin;
1495     int totalHeight = paperRect.height + 2 * m_topMargin;
1496     int scrollUnitsX = totalWidth / 10;
1497     int scrollUnitsY = totalHeight / 10;
1498     wxSize virtualSize = canvas->GetVirtualSize();
1499     if (virtualSize.GetWidth() != totalWidth || virtualSize.GetHeight() != totalHeight)
1500         canvas->SetScrollbars(10, 10, scrollUnitsX, scrollUnitsY, 0, 0, true);
1501 }
1502 
RenderPageIntoDC(wxDC & dc,int pageNum)1503 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC& dc, int pageNum)
1504 {
1505     m_previewPrintout->SetDC(&dc);
1506     m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
1507 
1508     // Need to delay OnPreparePrinting() until here, so we have enough
1509     // information.
1510     if (!m_printingPrepared)
1511     {
1512         m_previewPrintout->OnPreparePrinting();
1513         int selFrom, selTo;
1514         m_previewPrintout->GetPageInfo(&m_minPage, &m_maxPage, &selFrom, &selTo);
1515         m_printingPrepared = true;
1516     }
1517 
1518     m_previewPrintout->OnBeginPrinting();
1519 
1520     if (!m_previewPrintout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
1521     {
1522         wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK);
1523         return false;
1524     }
1525 
1526     m_previewPrintout->OnPrintPage(pageNum);
1527     m_previewPrintout->OnEndDocument();
1528     m_previewPrintout->OnEndPrinting();
1529 
1530     m_previewPrintout->SetDC(NULL);
1531 
1532     return true;
1533 }
1534 
RenderPageIntoBitmap(wxBitmap & bmp,int pageNum)1535 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap& bmp, int pageNum)
1536 {
1537 #if wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
1538     {
1539         if ( RenderPageIntoBitmapHQ(this,
1540                                     &wxPrintPreviewBase::RenderPageIntoDC,
1541                                     bmp, pageNum) )
1542         {
1543             return true;
1544         }
1545     }
1546 #endif // wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
1547 
1548     wxMemoryDC memoryDC;
1549     memoryDC.SelectObject(bmp);
1550     memoryDC.Clear();
1551 
1552     return RenderPageIntoDC(memoryDC, pageNum);
1553 }
1554 
RenderPage(int pageNum)1555 bool wxPrintPreviewBase::RenderPage(int pageNum)
1556 {
1557     wxBusyCursor busy;
1558 
1559     if (!m_previewCanvas)
1560     {
1561         wxFAIL_MSG(_T("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1562         return false;
1563     }
1564 
1565     wxRect pageRect, paperRect;
1566     CalcRects(m_previewCanvas, pageRect, paperRect);
1567 
1568     if (!m_previewBitmap)
1569     {
1570         m_previewBitmap = new wxBitmap(pageRect.width, pageRect.height);
1571 
1572         if (!m_previewBitmap || !m_previewBitmap->Ok())
1573         {
1574             if (m_previewBitmap) {
1575                 delete m_previewBitmap;
1576                 m_previewBitmap = NULL;
1577             }
1578             wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
1579             return false;
1580         }
1581     }
1582 
1583     if ( !RenderPageIntoBitmap(*m_previewBitmap, pageNum) )
1584     {
1585         wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK);
1586 
1587         delete m_previewBitmap;
1588         m_previewBitmap = NULL;
1589         return false;
1590     }
1591 
1592 #if wxUSE_STATUSBAR
1593     wxString status;
1594     if (m_maxPage != 0)
1595         status = wxString::Format(_("Page %d of %d"), pageNum, m_maxPage);
1596     else
1597         status = wxString::Format(_("Page %d"), pageNum);
1598 
1599     if (m_previewFrame)
1600         m_previewFrame->SetStatusText(status);
1601 #endif
1602 
1603     return true;
1604 }
1605 
DrawBlankPage(wxPreviewCanvas * canvas,wxDC & dc)1606 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
1607 {
1608     wxRect pageRect, paperRect;
1609 
1610     CalcRects(canvas, pageRect, paperRect);
1611 
1612     // Draw shadow, allowing for 1-pixel border AROUND the actual paper
1613     wxCoord shadowOffset = 4;
1614 
1615     dc.SetPen(*wxBLACK_PEN);
1616     dc.SetBrush(*wxBLACK_BRUSH);
1617     dc.DrawRectangle(paperRect.x + shadowOffset, paperRect.y + paperRect.height + 1,
1618         paperRect.width, shadowOffset);
1619 
1620     dc.DrawRectangle(paperRect.x + paperRect.width, paperRect.y + shadowOffset,
1621         shadowOffset, paperRect.height);
1622 
1623     // Draw blank page allowing for 1-pixel border AROUND the actual paper
1624     dc.SetPen(*wxBLACK_PEN);
1625     dc.SetBrush(*wxWHITE_BRUSH);
1626     dc.DrawRectangle(paperRect.x - 2, paperRect.y - 1,
1627         paperRect.width + 3, paperRect.height + 2);
1628 
1629     return true;
1630 }
1631 
SetZoom(int percent)1632 void wxPrintPreviewBase::SetZoom(int percent)
1633 {
1634     if (m_currentZoom == percent)
1635         return;
1636 
1637     m_currentZoom = percent;
1638     if (m_previewBitmap)
1639     {
1640         delete m_previewBitmap;
1641         m_previewBitmap = NULL;
1642     }
1643 
1644     if (m_previewCanvas)
1645     {
1646         AdjustScrollbars(m_previewCanvas);
1647         RenderPage(m_currentPage);
1648         ((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
1649         m_previewCanvas->ClearBackground();
1650         m_previewCanvas->Refresh();
1651         m_previewCanvas->SetFocus();
1652     }
1653 }
1654 
GetPrintDialogData()1655 wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
1656 {
1657     return m_printDialogData;
1658 }
1659 
GetZoom() const1660 int wxPrintPreviewBase::GetZoom() const
1661 { return m_currentZoom; }
GetMaxPage() const1662 int wxPrintPreviewBase::GetMaxPage() const
1663 { return m_maxPage; }
GetMinPage() const1664 int wxPrintPreviewBase::GetMinPage() const
1665 { return m_minPage; }
IsOk() const1666 bool wxPrintPreviewBase::IsOk() const
1667 { return m_isOk; }
SetOk(bool ok)1668 void wxPrintPreviewBase::SetOk(bool ok)
1669 { m_isOk = ok; }
1670 
1671 //----------------------------------------------------------------------------
1672 // wxPrintPreview
1673 //----------------------------------------------------------------------------
1674 
IMPLEMENT_CLASS(wxPrintPreview,wxPrintPreviewBase)1675 IMPLEMENT_CLASS(wxPrintPreview, wxPrintPreviewBase)
1676 
1677 wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1678                    wxPrintout *printoutForPrinting,
1679                    wxPrintDialogData *data) :
1680     wxPrintPreviewBase( printout, printoutForPrinting, data )
1681 {
1682     m_pimpl = wxPrintFactory::GetFactory()->
1683         CreatePrintPreview( printout, printoutForPrinting, data );
1684 }
1685 
wxPrintPreview(wxPrintout * printout,wxPrintout * printoutForPrinting,wxPrintData * data)1686 wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1687                    wxPrintout *printoutForPrinting,
1688                    wxPrintData *data ) :
1689     wxPrintPreviewBase( printout, printoutForPrinting, data )
1690 {
1691     m_pimpl = wxPrintFactory::GetFactory()->
1692         CreatePrintPreview( printout, printoutForPrinting, data );
1693 }
1694 
~wxPrintPreview()1695 wxPrintPreview::~wxPrintPreview()
1696 {
1697     delete m_pimpl;
1698 
1699     // don't delete twice
1700     m_printPrintout = NULL;
1701     m_previewPrintout = NULL;
1702     m_previewBitmap = NULL;
1703 }
1704 
SetCurrentPage(int pageNum)1705 bool wxPrintPreview::SetCurrentPage(int pageNum)
1706 {
1707     return m_pimpl->SetCurrentPage( pageNum );
1708 }
1709 
GetCurrentPage() const1710 int wxPrintPreview::GetCurrentPage() const
1711 {
1712     return m_pimpl->GetCurrentPage();
1713 }
1714 
SetPrintout(wxPrintout * printout)1715 void wxPrintPreview::SetPrintout(wxPrintout *printout)
1716 {
1717     m_pimpl->SetPrintout( printout );
1718 }
1719 
GetPrintout() const1720 wxPrintout *wxPrintPreview::GetPrintout() const
1721 {
1722     return m_pimpl->GetPrintout();
1723 }
1724 
GetPrintoutForPrinting() const1725 wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
1726 {
1727     return m_pimpl->GetPrintoutForPrinting();
1728 }
1729 
SetFrame(wxFrame * frame)1730 void wxPrintPreview::SetFrame(wxFrame *frame)
1731 {
1732     m_pimpl->SetFrame( frame );
1733 }
1734 
SetCanvas(wxPreviewCanvas * canvas)1735 void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
1736 {
1737     m_pimpl->SetCanvas( canvas );
1738 }
1739 
GetFrame() const1740 wxFrame *wxPrintPreview::GetFrame() const
1741 {
1742     return m_pimpl->GetFrame();
1743 }
1744 
GetCanvas() const1745 wxPreviewCanvas *wxPrintPreview::GetCanvas() const
1746 {
1747     return m_pimpl->GetCanvas();
1748 }
1749 
PaintPage(wxPreviewCanvas * canvas,wxDC & dc)1750 bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
1751 {
1752     return m_pimpl->PaintPage( canvas, dc );
1753 }
1754 
DrawBlankPage(wxPreviewCanvas * canvas,wxDC & dc)1755 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
1756 {
1757     return m_pimpl->DrawBlankPage( canvas, dc );
1758 }
1759 
AdjustScrollbars(wxPreviewCanvas * canvas)1760 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas *canvas)
1761 {
1762     m_pimpl->AdjustScrollbars( canvas );
1763 }
1764 
RenderPage(int pageNum)1765 bool wxPrintPreview::RenderPage(int pageNum)
1766 {
1767     return m_pimpl->RenderPage( pageNum );
1768 }
1769 
SetZoom(int percent)1770 void wxPrintPreview::SetZoom(int percent)
1771 {
1772     m_pimpl->SetZoom( percent );
1773 }
1774 
GetZoom() const1775 int wxPrintPreview::GetZoom() const
1776 {
1777     return m_pimpl->GetZoom();
1778 }
1779 
GetPrintDialogData()1780 wxPrintDialogData& wxPrintPreview::GetPrintDialogData()
1781 {
1782     return m_pimpl->GetPrintDialogData();
1783 }
1784 
GetMaxPage() const1785 int wxPrintPreview::GetMaxPage() const
1786 {
1787     return m_pimpl->GetMaxPage();
1788 }
1789 
GetMinPage() const1790 int wxPrintPreview::GetMinPage() const
1791 {
1792     return m_pimpl->GetMinPage();
1793 }
1794 
IsOk() const1795 bool wxPrintPreview::IsOk() const
1796 {
1797     return m_pimpl->Ok();
1798 }
1799 
SetOk(bool ok)1800 void wxPrintPreview::SetOk(bool ok)
1801 {
1802     m_pimpl->SetOk( ok );
1803 }
1804 
Print(bool interactive)1805 bool wxPrintPreview::Print(bool interactive)
1806 {
1807     return m_pimpl->Print( interactive );
1808 }
1809 
DetermineScaling()1810 void wxPrintPreview::DetermineScaling()
1811 {
1812     m_pimpl->DetermineScaling();
1813 }
1814 
1815 //----------------------------------------------------------------------------
1816 // experimental backport of high-quality preview on Windows
1817 //----------------------------------------------------------------------------
1818 
1819 #if wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
RenderPageIntoBitmapHQ(wxPrintPreviewBase * preview,RenderPageIntoDCFunc RenderPageIntoDC,wxBitmap & bmp,int pageNum)1820 static bool RenderPageIntoBitmapHQ(wxPrintPreviewBase *preview,
1821                                    RenderPageIntoDCFunc RenderPageIntoDC,
1822                                    wxBitmap& bmp, int pageNum)
1823 {
1824     // The preview, as implemented in wxPrintPreviewBase (and as used prior to
1825     // wx3) is inexact: it uses screen DC, which has much lower resolution and
1826     // has other properties different from printer DC, so the preview is not
1827     // quite right.
1828     //
1829     // To make matters worse, if the application depends heavily on
1830     // GetTextExtent() or does text layout itself, the output in preview and on
1831     // paper can be very different. In particular, wxHtmlEasyPrinting is
1832     // affected and the preview can be easily off by several pages.
1833     //
1834     // To fix this, we render the preview into high-resolution enhanced
1835     // metafile with properties identical to the printer DC. This guarantees
1836     // metrics correctness while still being fast.
1837 
1838 
1839     // print the preview into a metafile:
1840     wxPrinterDC printerDC(preview->GetPrintDialogData().GetPrintData());
1841     wxEnhMetaFileDC metaDC(printerDC,
1842                            wxEmptyString,
1843                            printerDC.GetSize().x, printerDC.GetSize().y);
1844 
1845     if ( !(preview->*RenderPageIntoDC)(metaDC, pageNum) )
1846         return false;
1847 
1848     wxEnhMetaFile *metafile = metaDC.Close();
1849     if ( !metafile )
1850         return false;
1851 
1852     // now render the metafile:
1853     wxMemoryDC bmpDC;
1854     bmpDC.SelectObject(bmp);
1855     bmpDC.Clear();
1856 
1857     wxRect outRect(0, 0, bmp.GetWidth(), bmp.GetHeight());
1858     metafile->Play(&bmpDC, &outRect);
1859 
1860 
1861     delete metafile;
1862 
1863     // TODO: we should keep the metafile and reuse it when changing zoom level
1864 
1865     return true;
1866 }
1867 #endif // wxUSE_HIGH_QUALITY_PREVIEW_IN_WXMSW
1868 
1869 #endif // wxUSE_PRINTING_ARCHITECTURE
1870