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