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