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