1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/prntbase.cpp
3 // Purpose: Printing framework base class implementation
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
19 #if wxUSE_PRINTING_ARCHITECTURE
21 #include "wx/dcprint.h"
24 #if defined(__WXMSW__)
25 #include "wx/msw/wrapcdlg.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"
41 #include "wx/textdlg.h"
43 #include "wx/module.h"
46 #include "wx/prntbase.h"
47 #include "wx/printdlg.h"
49 #include "wx/dcprint.h"
50 #include "wx/artprov.h"
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"
66 #include "wx/generic/prntdlgg.h"
76 //----------------------------------------------------------------------------
78 //----------------------------------------------------------------------------
80 wxPrintFactory
*wxPrintFactory::m_factory
= NULL
;
82 void wxPrintFactory::SetPrintFactory( wxPrintFactory
*factory
)
84 if (wxPrintFactory::m_factory
)
85 delete wxPrintFactory::m_factory
;
87 wxPrintFactory::m_factory
= factory
;
90 wxPrintFactory
*wxPrintFactory::GetFactory()
92 if (!wxPrintFactory::m_factory
)
93 wxPrintFactory::m_factory
= new wxNativePrintFactory
;
95 return wxPrintFactory::m_factory
;
98 //----------------------------------------------------------------------------
99 // wxNativePrintFactory
100 //----------------------------------------------------------------------------
102 wxPrinterBase
*wxNativePrintFactory::CreatePrinter( wxPrintDialogData
*data
)
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
);
111 return new wxPostScriptPrinter( data
);
115 wxPrintPreviewBase
*wxNativePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
116 wxPrintout
*printout
, wxPrintDialogData
*data
)
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
);
125 return new wxPostScriptPrintPreview( preview
, printout
, data
);
129 wxPrintPreviewBase
*wxNativePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
130 wxPrintout
*printout
, wxPrintData
*data
)
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
);
139 return new wxPostScriptPrintPreview( preview
, printout
, data
);
143 wxPrintDialogBase
*wxNativePrintFactory::CreatePrintDialog( wxWindow
*parent
,
144 wxPrintDialogData
*data
)
146 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
147 return new wxWindowsPrintDialog( parent
, data
);
148 #elif defined(__WXMAC__)
149 return new wxMacPrintDialog( parent
, data
);
151 return new wxGenericPrintDialog( parent
, data
);
155 wxPrintDialogBase
*wxNativePrintFactory::CreatePrintDialog( wxWindow
*parent
,
158 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
159 return new wxWindowsPrintDialog( parent
, data
);
160 #elif defined(__WXMAC__)
161 return new wxMacPrintDialog( parent
, data
);
163 return new wxGenericPrintDialog( parent
, data
);
167 wxPageSetupDialogBase
*wxNativePrintFactory::CreatePageSetupDialog( wxWindow
*parent
,
168 wxPageSetupDialogData
*data
)
170 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
171 return new wxWindowsPageSetupDialog( parent
, data
);
172 #elif defined(__WXMAC__)
173 return new wxMacPageSetupDialog( parent
, data
);
175 return new wxGenericPageSetupDialog( parent
, data
);
179 bool wxNativePrintFactory::HasPrintSetupDialog()
181 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
183 #elif defined(__WXMAC__)
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.
195 wxDialog
*wxNativePrintFactory::CreatePrintSetupDialog( wxWindow
*parent
,
198 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
202 #elif defined(__WXMAC__)
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
);
215 wxDCImpl
* wxNativePrintFactory::CreatePrinterDCImpl( wxPrinterDC
*owner
, const wxPrintData
& data
)
217 #if defined(__WXGTK__) || defined(__WXMOTIF__) || ( defined(__WXUNIVERSAL__) && !defined(__WXMAC__) )
218 return new wxPostScriptDCImpl( owner
, data
);
220 return new wxPrinterDCImpl( owner
, data
);
224 bool wxNativePrintFactory::HasOwnPrintToFile()
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.
233 bool wxNativePrintFactory::HasPrinterLine()
235 // Only relevant for PostScript for now
239 wxString
wxNativePrintFactory::CreatePrinterLine()
241 // Only relevant for PostScript for now
243 // We should query "lpstat -d" here
244 return _("Generic PostScript");
247 bool wxNativePrintFactory::HasStatusLine()
249 // Only relevant for PostScript for now
253 wxString
wxNativePrintFactory::CreateStatusLine()
255 // Only relevant for PostScript for now
257 // We should query "lpstat -r" or "lpstat -p" here
261 wxPrintNativeDataBase
*wxNativePrintFactory::CreatePrintNativeData()
263 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
264 return new wxWindowsPrintNativeData
;
265 #elif defined(__WXMAC__)
266 return wxOSXCreatePrintData();
268 return new wxPostScriptPrintNativeData
;
272 //----------------------------------------------------------------------------
273 // wxPrintNativeDataBase
274 //----------------------------------------------------------------------------
276 IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase
, wxObject
)
278 wxPrintNativeDataBase::wxPrintNativeDataBase()
283 //----------------------------------------------------------------------------
284 // wxPrintFactoryModule
285 //----------------------------------------------------------------------------
287 class wxPrintFactoryModule
: public wxModule
290 wxPrintFactoryModule() {}
291 bool OnInit() { return true; }
292 void OnExit() { wxPrintFactory::SetPrintFactory( NULL
); }
295 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule
)
298 IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule
, wxModule
)
300 //----------------------------------------------------------------------------
302 //----------------------------------------------------------------------------
304 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
306 wxPrinterBase::wxPrinterBase(wxPrintDialogData
*data
)
308 m_currentPrintout
= NULL
;
309 sm_abortWindow
= NULL
;
312 m_printDialogData
= (*data
);
313 sm_lastError
= wxPRINTER_NO_ERROR
;
316 wxWindow
*wxPrinterBase::sm_abortWindow
= NULL
;
317 bool wxPrinterBase::sm_abortIt
= false;
318 wxPrinterError
wxPrinterBase::sm_lastError
= wxPRINTER_NO_ERROR
;
320 wxPrinterBase::~wxPrinterBase()
324 wxPrintAbortDialog
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
* printout
)
326 return new wxPrintAbortDialog(parent
, printout
->GetTitle());
329 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), const wxString
& message
)
331 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
334 wxPrintDialogData
& wxPrinterBase::GetPrintDialogData() const
336 return (wxPrintDialogData
&) m_printDialogData
;
339 //----------------------------------------------------------------------------
341 //----------------------------------------------------------------------------
343 IMPLEMENT_CLASS(wxPrinter
, wxPrinterBase
)
345 wxPrinter::wxPrinter(wxPrintDialogData
*data
)
347 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrinter( data
);
350 wxPrinter::~wxPrinter()
355 wxPrintAbortDialog
*wxPrinter::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*printout
)
357 return m_pimpl
->CreateAbortWindow( parent
, printout
);
360 void wxPrinter::ReportError(wxWindow
*parent
, wxPrintout
*printout
, const wxString
& message
)
362 m_pimpl
->ReportError( parent
, printout
, message
);
365 bool wxPrinter::Setup(wxWindow
*parent
)
367 return m_pimpl
->Setup( parent
);
370 bool wxPrinter::Print(wxWindow
*parent
, wxPrintout
*printout
, bool prompt
)
372 if ( !prompt
&& m_printDialogData
.GetToPage() == 0 )
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
);
380 wxPrintDialogData
& pdd
= m_pimpl
->GetPrintDialogData();
381 pdd
.SetFromPage(minPage
);
382 pdd
.SetToPage(maxPage
);
385 return m_pimpl
->Print( parent
, printout
, prompt
);
388 wxDC
* wxPrinter::PrintDialog(wxWindow
*parent
)
390 return m_pimpl
->PrintDialog( parent
);
393 wxPrintDialogData
& wxPrinter::GetPrintDialogData() const
395 return m_pimpl
->GetPrintDialogData();
398 // ---------------------------------------------------------------------------
399 // wxPrintDialogBase: the dialog for printing.
400 // ---------------------------------------------------------------------------
402 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase
, wxDialog
)
404 wxPrintDialogBase::wxPrintDialogBase(wxWindow
*parent
,
406 const wxString
&title
,
410 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Print")) : title
,
415 // ---------------------------------------------------------------------------
416 // wxPrintDialog: the dialog for printing
417 // ---------------------------------------------------------------------------
419 IMPLEMENT_CLASS(wxPrintDialog
, wxObject
)
421 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintDialogData
* data
)
423 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
426 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintData
* data
)
428 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
431 wxPrintDialog::~wxPrintDialog()
436 int wxPrintDialog::ShowModal()
438 return m_pimpl
->ShowModal();
441 wxPrintDialogData
& wxPrintDialog::GetPrintDialogData()
443 return m_pimpl
->GetPrintDialogData();
446 wxPrintData
& wxPrintDialog::GetPrintData()
448 return m_pimpl
->GetPrintData();
451 wxDC
*wxPrintDialog::GetPrintDC()
453 return m_pimpl
->GetPrintDC();
456 // ---------------------------------------------------------------------------
457 // wxPageSetupDialogBase: the page setup dialog
458 // ---------------------------------------------------------------------------
460 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase
, wxDialog
)
462 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow
*parent
,
464 const wxString
&title
,
468 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Page setup")) : title
,
473 // ---------------------------------------------------------------------------
474 // wxPageSetupDialog: the page setup dialog
475 // ---------------------------------------------------------------------------
477 IMPLEMENT_CLASS(wxPageSetupDialog
, wxObject
)
479 wxPageSetupDialog::wxPageSetupDialog(wxWindow
*parent
, wxPageSetupDialogData
*data
)
481 m_pimpl
= wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent
, data
);
484 wxPageSetupDialog::~wxPageSetupDialog()
489 int wxPageSetupDialog::ShowModal()
491 return m_pimpl
->ShowModal();
494 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupDialogData()
496 return m_pimpl
->GetPageSetupDialogData();
500 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupData()
502 return m_pimpl
->GetPageSetupDialogData();
505 //----------------------------------------------------------------------------
506 // wxPrintAbortDialog
507 //----------------------------------------------------------------------------
509 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
510 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
513 wxPrintAbortDialog::wxPrintAbortDialog(wxWindow
*parent
,
514 const wxString
& documentTitle
,
518 const wxString
& name
)
519 : wxDialog(parent
, wxID_ANY
, _("Printing"), pos
, size
, style
, name
)
521 wxBoxSizer
*button_sizer
= new wxBoxSizer(wxVERTICAL
);
522 button_sizer
->Add(new wxStaticText(this, wxID_ANY
, _("Please wait while printing\n") + documentTitle
), 0, wxALL
, 10 );
523 button_sizer
->Add(new wxButton(this, wxID_CANCEL
, wxT("Cancel") ), 0, wxALL
| wxALIGN_CENTER
, 10);
526 SetSizer(button_sizer
);
528 button_sizer
->Fit(this);
529 button_sizer
->SetSizeHints(this);
532 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
534 wxPrinterBase::sm_abortIt
= true;
535 wxPrinterBase::sm_abortWindow
->Show(false);
536 wxPrinterBase::sm_abortWindow
->Close(true);
537 wxPrinterBase::sm_abortWindow
->Destroy();
538 wxPrinterBase::sm_abortWindow
= NULL
;
541 //----------------------------------------------------------------------------
543 //----------------------------------------------------------------------------
545 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
547 wxPrintout::wxPrintout(const wxString
& title
)
549 m_printoutTitle
= title
;
553 m_pageWidthPixels
= 0;
554 m_pageHeightPixels
= 0;
562 wxPrintout::~wxPrintout()
566 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
568 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle
);
571 void wxPrintout::OnEndDocument()
576 void wxPrintout::OnBeginPrinting()
580 void wxPrintout::OnEndPrinting()
584 bool wxPrintout::HasPage(int page
)
589 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
597 void wxPrintout::FitThisSizeToPaper(const wxSize
& imageSize
)
599 // Set the DC scale and origin so that the given image size fits within the
600 // entire page and the origin is at the top left corner of the page. Note
601 // that with most printers, portions of the page will be non-printable. Use
602 // this if you're managing your own page margins.
603 if (!m_printoutDC
) return;
604 wxRect paperRect
= GetPaperRectPixels();
606 GetPageSizePixels(&pw
, &ph
);
608 m_printoutDC
->GetSize(&w
, &h
);
609 float scaleX
= ((float(paperRect
.width
) * w
) / (float(pw
) * imageSize
.x
));
610 float scaleY
= ((float(paperRect
.height
) * h
) / (float(ph
) * imageSize
.y
));
611 float actualScale
= wxMin(scaleX
, scaleY
);
612 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
613 m_printoutDC
->SetDeviceOrigin(0, 0);
614 wxRect logicalPaperRect
= GetLogicalPaperRect();
615 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
618 void wxPrintout::FitThisSizeToPage(const wxSize
& imageSize
)
620 // Set the DC scale and origin so that the given image size fits within the
621 // printable area of the page and the origin is at the top left corner of
622 // the printable area.
623 if (!m_printoutDC
) return;
625 m_printoutDC
->GetSize(&w
, &h
);
626 float scaleX
= float(w
) / imageSize
.x
;
627 float scaleY
= float(h
) / imageSize
.y
;
628 float actualScale
= wxMin(scaleX
, scaleY
);
629 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
630 m_printoutDC
->SetDeviceOrigin(0, 0);
633 void wxPrintout::FitThisSizeToPageMargins(const wxSize
& imageSize
, const wxPageSetupDialogData
& pageSetupData
)
635 // Set the DC scale and origin so that the given image size fits within the
636 // page margins defined in the given wxPageSetupDialogData object and the
637 // origin is at the top left corner of the page margins.
638 if (!m_printoutDC
) return;
639 wxRect paperRect
= GetPaperRectPixels();
641 GetPageSizePixels(&pw
, &ph
);
642 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
643 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
645 GetPageSizeMM(&mw
, &mh
);
646 float mmToDeviceX
= float(pw
) / mw
;
647 float mmToDeviceY
= float(ph
) / mh
;
648 wxRect
pageMarginsRect(paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
649 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
650 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
651 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
653 m_printoutDC
->GetSize(&w
, &h
);
654 float scaleX
= (float(pageMarginsRect
.width
) * w
) / (float(pw
) * imageSize
.x
);
655 float scaleY
= (float(pageMarginsRect
.height
) * h
) / (float(ph
) * imageSize
.y
);
656 float actualScale
= wxMin(scaleX
, scaleY
);
657 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
658 m_printoutDC
->SetDeviceOrigin(0, 0);
659 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
660 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
663 void wxPrintout::MapScreenSizeToPaper()
665 // Set the DC scale so that an image on the screen is the same size on the
666 // paper and the origin is at the top left of the paper. Note that with most
667 // printers, portions of the page will be cut off. Use this if you're
668 // managing your own page margins.
669 if (!m_printoutDC
) return;
670 MapScreenSizeToPage();
671 wxRect logicalPaperRect
= GetLogicalPaperRect();
672 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
675 void wxPrintout::MapScreenSizeToPage()
677 // Set the DC scale and origin so that an image on the screen is the same
678 // size on the paper and the origin is at the top left of the printable area.
679 if (!m_printoutDC
) return;
680 int ppiScreenX
, ppiScreenY
;
681 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
682 int ppiPrinterX
, ppiPrinterY
;
683 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
685 m_printoutDC
->GetSize(&w
, &h
);
686 int pageSizePixelsX
, pageSizePixelsY
;
687 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
688 float userScaleX
= (float(ppiPrinterX
) * w
) / (float(ppiScreenX
) * pageSizePixelsX
);
689 float userScaleY
= (float(ppiPrinterY
) * h
) / (float(ppiScreenY
) * pageSizePixelsY
);
690 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
691 m_printoutDC
->SetDeviceOrigin(0, 0);
694 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData
& pageSetupData
)
696 // Set the DC scale so that an image on the screen is the same size on the
697 // paper and the origin is at the top left of the page margins defined by
698 // the given wxPageSetupDialogData object.
699 if (!m_printoutDC
) return;
700 MapScreenSizeToPage();
701 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
702 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
705 void wxPrintout::MapScreenSizeToDevice()
707 // Set the DC scale so that a screen pixel is the same size as a device
708 // pixel and the origin is at the top left of the printable area.
709 if (!m_printoutDC
) return;
711 m_printoutDC
->GetSize(&w
, &h
);
712 int pageSizePixelsX
, pageSizePixelsY
;
713 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
714 float userScaleX
= float(w
) / pageSizePixelsX
;
715 float userScaleY
= float(h
) / pageSizePixelsY
;
716 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
717 m_printoutDC
->SetDeviceOrigin(0, 0);
720 wxRect
wxPrintout::GetLogicalPaperRect() const
722 // Return the rectangle in logical units that corresponds to the paper
724 wxRect paperRect
= GetPaperRectPixels();
726 GetPageSizePixels(&pw
, &ph
);
728 m_printoutDC
->GetSize(&w
, &h
);
729 if (w
== pw
&& h
== ph
) {
730 // this DC matches the printed page, so no scaling
731 return wxRect(m_printoutDC
->DeviceToLogicalX(paperRect
.x
),
732 m_printoutDC
->DeviceToLogicalY(paperRect
.y
),
733 m_printoutDC
->DeviceToLogicalXRel(paperRect
.width
),
734 m_printoutDC
->DeviceToLogicalYRel(paperRect
.height
));
736 // This DC doesn't match the printed page, so we have to scale.
737 float scaleX
= float(w
) / pw
;
738 float scaleY
= float(h
) / ph
;
739 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(paperRect
.x
* scaleX
)),
740 m_printoutDC
->DeviceToLogicalY(wxRound(paperRect
.y
* scaleY
)),
741 m_printoutDC
->DeviceToLogicalXRel(wxRound(paperRect
.width
* scaleX
)),
742 m_printoutDC
->DeviceToLogicalYRel(wxRound(paperRect
.height
* scaleY
)));
745 wxRect
wxPrintout::GetLogicalPageRect() const
747 // Return the rectangle in logical units that corresponds to the printable
750 m_printoutDC
->GetSize(&w
, &h
);
751 return wxRect(m_printoutDC
->DeviceToLogicalX(0),
752 m_printoutDC
->DeviceToLogicalY(0),
753 m_printoutDC
->DeviceToLogicalXRel(w
),
754 m_printoutDC
->DeviceToLogicalYRel(h
));
757 wxRect
wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData
& pageSetupData
) const
759 // Return the rectangle in logical units that corresponds to the region
760 // within the page margins as specified by the given wxPageSetupDialogData
763 // We get the paper size in device units and the margins in mm,
764 // so we need to calculate the conversion with this trick
766 GetPageSizePixels(&pw
, &ph
);
768 GetPageSizeMM(&mw
, &mh
);
769 float mmToDeviceX
= float(pw
) / mw
;
770 float mmToDeviceY
= float(ph
) / mh
;
772 // paper size in device units
773 wxRect paperRect
= GetPaperRectPixels();
776 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
777 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
779 // calculate margins in device units
780 wxRect
pageMarginsRect(
781 paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
782 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
783 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
784 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
787 m_printoutDC
->GetSize(&w
, &h
);
788 if (w
== pw
&& h
== ph
)
790 // this DC matches the printed page, so no scaling
792 m_printoutDC
->DeviceToLogicalX(pageMarginsRect
.x
),
793 m_printoutDC
->DeviceToLogicalY(pageMarginsRect
.y
),
794 m_printoutDC
->DeviceToLogicalXRel(pageMarginsRect
.width
),
795 m_printoutDC
->DeviceToLogicalYRel(pageMarginsRect
.height
));
798 // This DC doesn't match the printed page, so we have to scale.
799 float scaleX
= float(w
) / pw
;
800 float scaleY
= float(h
) / ph
;
801 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(pageMarginsRect
.x
* scaleX
)),
802 m_printoutDC
->DeviceToLogicalY(wxRound(pageMarginsRect
.y
* scaleY
)),
803 m_printoutDC
->DeviceToLogicalXRel(wxRound(pageMarginsRect
.width
* scaleX
)),
804 m_printoutDC
->DeviceToLogicalYRel(wxRound(pageMarginsRect
.height
* scaleY
)));
807 void wxPrintout::SetLogicalOrigin(wxCoord x
, wxCoord y
)
809 // Set the device origin by specifying a point in logical coordinates.
810 m_printoutDC
->SetDeviceOrigin(
811 m_printoutDC
->LogicalToDeviceX(x
),
812 m_printoutDC
->LogicalToDeviceY(y
) );
815 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff
, wxCoord yoff
)
817 // Offset the device origin by a specified distance in device coordinates.
818 wxPoint dev_org
= m_printoutDC
->GetDeviceOrigin();
819 m_printoutDC
->SetDeviceOrigin(
820 dev_org
.x
+ m_printoutDC
->LogicalToDeviceXRel(xoff
),
821 dev_org
.y
+ m_printoutDC
->LogicalToDeviceYRel(yoff
) );
825 //----------------------------------------------------------------------------
827 //----------------------------------------------------------------------------
829 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
831 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
832 EVT_PAINT(wxPreviewCanvas::OnPaint
)
833 EVT_CHAR(wxPreviewCanvas::OnChar
)
834 EVT_IDLE(wxPreviewCanvas::OnIdle
)
835 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
837 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel
)
841 // VZ: the current code doesn't refresh properly without
842 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
843 // really horrible flicker when resizing the preview frame, but without
844 // this style it simply doesn't work correctly at all...
845 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
846 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
847 wxScrolledWindow(parent
, wxID_ANY
, pos
, size
, style
| wxFULL_REPAINT_ON_RESIZE
, name
)
849 m_printPreview
= preview
;
851 // The app workspace colour is always white, but we should have
852 // a contrast with the page.
853 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
854 #elif defined(__WXGTK__)
855 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
857 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
859 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
861 SetScrollbars(10, 10, 100, 100);
864 wxPreviewCanvas::~wxPreviewCanvas()
868 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
875 if (!GetUpdateRegion().IsEmpty())
876 dc.SetClippingRegion( GetUpdateRegion() );
882 m_printPreview
->PaintPage(this, dc
);
886 void wxPreviewCanvas::OnIdle(wxIdleEvent
& event
)
890 // prevent UpdatePageRendering() from being called recursively:
891 static bool s_inIdle
= false;
896 if ( m_printPreview
)
898 if ( m_printPreview
->UpdatePageRendering() )
905 // Responds to colour changes, and passes event on to children.
906 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
909 // The app workspace colour is always white, but we should have
910 // a contrast with the page.
911 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
912 #elif defined(__WXGTK__)
913 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
915 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
917 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
920 // Propagate the event to the non-top-level children
921 wxWindow::OnSysColourChanged(event
);
924 void wxPreviewCanvas::OnChar(wxKeyEvent
&event
)
926 wxPreviewControlBar
* controlBar
= ((wxPreviewFrame
*) GetParent())->GetControlBar();
927 switch (event
.GetKeyCode())
930 controlBar
->OnPrint();
935 controlBar
->DoZoomIn();
938 case WXK_NUMPAD_SUBTRACT
:
940 controlBar
->DoZoomOut();
944 if (!event
.ControlDown())
950 switch(event
.GetKeyCode())
953 controlBar
->OnNext(); break;
955 controlBar
->OnPrevious(); break;
957 controlBar
->OnFirst(); break;
959 controlBar
->OnLast(); break;
967 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent
& event
)
969 wxPreviewControlBar
*
970 controlBar
= wxStaticCast(GetParent(), wxPreviewFrame
)->GetControlBar();
974 if ( event
.ControlDown() && event
.GetWheelRotation() != 0 )
976 int currentZoom
= controlBar
->GetZoomControl();
979 if ( currentZoom
< 100 )
981 else if ( currentZoom
<= 120 )
986 if ( event
.GetWheelRotation() > 0 )
989 int newZoom
= currentZoom
+ delta
;
994 if ( newZoom
!= currentZoom
)
996 controlBar
->SetZoomControl(newZoom
);
997 m_printPreview
->SetZoom(newZoom
);
1007 #endif // wxUSE_MOUSEWHEEL
1012 // This is by the controls in the print preview as the maximal (and hence
1013 // longest) page number we may have to display.
1014 enum { MAX_PAGE_NUMBER
= 99999 };
1016 } // anonymous namespace
1018 // ----------------------------------------------------------------------------
1019 // wxPrintPageMaxCtrl
1020 // ----------------------------------------------------------------------------
1022 // A simple static control showing the maximal number of pages.
1023 class wxPrintPageMaxCtrl
: public wxStaticText
1026 wxPrintPageMaxCtrl(wxWindow
*parent
)
1034 parent
->GetTextExtent(MaxAsString(MAX_PAGE_NUMBER
)).x
,
1037 wxST_NO_AUTORESIZE
| wxALIGN_CENTRE
1042 // Set the maximal page to display once we really know what it is.
1043 void SetMaxPage(int maxPage
)
1045 SetLabel(MaxAsString(maxPage
));
1049 static wxString
MaxAsString(int maxPage
)
1051 return wxString::Format("/ %d", maxPage
);
1054 wxDECLARE_NO_COPY_CLASS(wxPrintPageMaxCtrl
);
1057 // ----------------------------------------------------------------------------
1058 // wxPrintPageTextCtrl
1059 // ----------------------------------------------------------------------------
1061 // This text control contains the page number in the specified interval.
1063 // Invalid pages are not accepted and the control contents is validated when it
1064 // loses focus. Conversely, if the user changes the page to another valid one
1065 // or presses Enter, OnGotoPage() method of the preview object will be called.
1066 class wxPrintPageTextCtrl
: public wxTextCtrl
1069 wxPrintPageTextCtrl(wxPreviewControlBar
*preview
)
1070 : wxTextCtrl(preview
,
1074 // We use hardcoded maximal page number for the width
1075 // instead of fitting it to the values we can show because
1076 // the control looks uncomfortably narrow if the real page
1077 // number is just one or two digits.
1080 preview
->GetTextExtent(PageAsString(MAX_PAGE_NUMBER
)).x
,
1084 #if wxUSE_VALIDATORS
1085 , wxTextValidator(wxFILTER_DIGITS
)
1086 #endif // wxUSE_VALIDATORS
1094 Connect(wxEVT_KILL_FOCUS
,
1095 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus
));
1096 Connect(wxEVT_COMMAND_TEXT_ENTER
,
1097 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter
));
1100 // Update the pages range, must be called after OnPreparePrinting() as
1101 // these values are not known before.
1102 void SetPageInfo(int minPage
, int maxPage
)
1104 m_minPage
= minPage
;
1105 m_maxPage
= maxPage
;
1107 // Show the first page by default.
1108 SetPageNumber(minPage
);
1111 // Helpers to conveniently set or get the current page number. Return value
1112 // is 0 if the current controls contents is invalid.
1113 void SetPageNumber(int page
)
1115 wxASSERT( IsValidPage(page
) );
1117 SetValue(PageAsString(page
));
1120 int GetPageNumber() const
1123 if ( !GetValue().ToLong(&value
) || !IsValidPage(value
) )
1126 // Cast is safe because the value is less than (int) m_maxPage.
1127 return static_cast<int>(value
);
1131 static wxString
PageAsString(int page
)
1133 return wxString::Format("%d", page
);
1136 bool IsValidPage(int page
) const
1138 return page
>= m_minPage
&& page
<= m_maxPage
;
1143 const int page
= GetPageNumber();
1148 if ( page
!= m_page
)
1150 // We have a valid page, remember it.
1153 // And notify the owner about the change.
1154 m_preview
->OnGotoPage();
1156 //else: Nothing really changed.
1161 void OnKillFocus(wxFocusEvent
& event
)
1163 if ( !DoChangePage() )
1165 // The current contents is invalid so reset it back to the last
1166 // known good page index.
1167 SetPageNumber(m_page
);
1173 void OnTextEnter(wxCommandEvent
& WXUNUSED(event
))
1179 wxPreviewControlBar
* const m_preview
;
1184 // This is the last valid page value that we had, we revert to it if an
1185 // invalid page is entered.
1188 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl
);
1191 //----------------------------------------------------------------------------
1192 // wxPreviewControlBar
1193 //----------------------------------------------------------------------------
1195 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
1197 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
1198 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
1199 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrintButton
)
1200 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
1201 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
1202 EVT_BUTTON(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnFirstButton
)
1203 EVT_BUTTON(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnLastButton
)
1204 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnZoomInButton
)
1205 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnZoomOutButton
)
1207 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnUpdatePreviousButton
)
1208 EVT_UPDATE_UI(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnUpdateNextButton
)
1209 EVT_UPDATE_UI(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnUpdateFirstButton
)
1210 EVT_UPDATE_UI(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnUpdateLastButton
)
1211 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnUpdateZoomInButton
)
1212 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnUpdateZoomOutButton
)
1214 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoomChoice
)
1215 EVT_PAINT(wxPreviewControlBar::OnPaint
)
1219 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
1220 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
1221 long style
, const wxString
& name
):
1222 wxPanel(parent
, wxID_ANY
, pos
, size
, style
, name
)
1224 m_printPreview
= preview
;
1225 m_closeButton
= NULL
;
1226 m_zoomControl
= NULL
;
1227 m_currentPageText
= NULL
;
1228 m_maxPageText
= NULL
;
1229 m_buttonFlags
= buttons
;
1232 wxPreviewControlBar::~wxPreviewControlBar()
1236 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1242 dc
.SetPen(*wxBLACK_PEN
);
1243 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1244 dc
.DrawLine( 0, h
-1, w
, h
-1 );
1247 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
1249 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
1253 void wxPreviewControlBar::OnPrint(void)
1255 wxPrintPreviewBase
*preview
= GetPrintPreview();
1256 preview
->Print(true);
1259 void wxPreviewControlBar::OnNext()
1261 if ( IsNextEnabled() )
1262 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1265 void wxPreviewControlBar::OnPrevious()
1267 if ( IsPreviousEnabled() )
1268 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1271 void wxPreviewControlBar::OnFirst()
1273 if ( IsFirstEnabled() )
1274 DoGotoPage(GetPrintPreview()->GetMinPage());
1277 void wxPreviewControlBar::OnLast()
1279 if ( IsLastEnabled() )
1280 DoGotoPage(GetPrintPreview()->GetMaxPage());
1283 bool wxPreviewControlBar::IsNextEnabled() const
1285 wxPrintPreviewBase
*preview
= GetPrintPreview();
1289 const int currentPage
= preview
->GetCurrentPage();
1290 return currentPage
< preview
->GetMaxPage() &&
1291 preview
->GetPrintout()->HasPage(currentPage
+ 1);
1294 bool wxPreviewControlBar::IsPreviousEnabled() const
1296 wxPrintPreviewBase
*preview
= GetPrintPreview();
1300 const int currentPage
= preview
->GetCurrentPage();
1301 return currentPage
> preview
->GetMinPage() &&
1302 preview
->GetPrintout()->HasPage(currentPage
- 1);
1305 bool wxPreviewControlBar::IsFirstEnabled() const
1307 wxPrintPreviewBase
*preview
= GetPrintPreview();
1311 return preview
->GetPrintout()->HasPage(preview
->GetMinPage());
1314 bool wxPreviewControlBar::IsLastEnabled() const
1316 wxPrintPreviewBase
*preview
= GetPrintPreview();
1320 return preview
->GetPrintout()->HasPage(preview
->GetMaxPage());
1323 void wxPreviewControlBar::DoGotoPage(int page
)
1325 wxPrintPreviewBase
*preview
= GetPrintPreview();
1326 wxCHECK_RET( preview
, "Shouldn't be called if there is no preview." );
1328 preview
->SetCurrentPage(page
);
1330 if ( m_currentPageText
)
1331 m_currentPageText
->SetPageNumber(page
);
1334 void wxPreviewControlBar::OnGotoPage()
1336 wxPrintPreviewBase
*preview
= GetPrintPreview();
1339 if (preview
->GetMinPage() > 0)
1341 long currentPage
= m_currentPageText
->GetPageNumber();
1344 if (preview
->GetPrintout()->HasPage(currentPage
))
1346 preview
->SetCurrentPage(currentPage
);
1353 void wxPreviewControlBar::DoZoom()
1355 int zoom
= GetZoomControl();
1356 if (GetPrintPreview())
1357 GetPrintPreview()->SetZoom(zoom
);
1360 bool wxPreviewControlBar::IsZoomInEnabled() const
1362 if ( !m_zoomControl
)
1365 const unsigned sel
= m_zoomControl
->GetSelection();
1366 return sel
< m_zoomControl
->GetCount() - 1;
1369 bool wxPreviewControlBar::IsZoomOutEnabled() const
1371 return m_zoomControl
&& m_zoomControl
->GetSelection() > 0;
1374 void wxPreviewControlBar::DoZoomIn()
1376 if (IsZoomInEnabled())
1378 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() + 1);
1383 void wxPreviewControlBar::DoZoomOut()
1385 if (IsZoomOutEnabled())
1387 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() - 1);
1395 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1396 // sequentially to it in the simplest way possible.
1397 class SizerWithButtons
1400 // Constructor creates the sizer that will hold the buttons and stores the
1401 // parent that will be used for their creation.
1402 SizerWithButtons(wxWindow
*parent
)
1403 : m_sizer(new wxBoxSizer(wxHORIZONTAL
)),
1407 m_needsSeparator
= false;
1410 // Destructor associates the sizer with the parent window.
1413 m_parent
->SetSizer(m_sizer
);
1414 m_sizer
->Fit(m_parent
);
1418 // Add an arbitrary window to the sizer.
1419 void Add(wxWindow
*win
)
1421 if ( m_needsSeparator
)
1423 m_needsSeparator
= false;
1425 m_sizer
->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1428 m_hasContents
= true;
1431 wxSizerFlags().Border(wxLEFT
| wxTOP
| wxBOTTOM
).Center());
1434 // Add a button with the specified id, bitmap and tooltip.
1435 void AddButton(wxWindowID btnId
,
1436 const wxArtID
& artId
,
1437 const wxString
& tooltip
)
1439 // We don't use (smaller) images inside a button with a text label but
1440 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1441 // wxART_BUTTON here.
1442 wxBitmap bmp
= wxArtProvider::GetBitmap(artId
, wxART_TOOLBAR
);
1443 wxBitmapButton
* const btn
= new wxBitmapButton(m_parent
, btnId
, bmp
);
1444 btn
->SetToolTip(tooltip
);
1449 // Add a control at the right end of the window. This should be called last
1450 // as everything else added after it will be added on the right side too.
1451 void AddAtEnd(wxWindow
*win
)
1453 m_sizer
->AddStretchSpacer();
1455 wxSizerFlags().Border(wxTOP
| wxBOTTOM
| wxRIGHT
).Center());
1458 // Indicates the end of a group of buttons, a separator will be added after
1462 if ( m_hasContents
)
1464 m_needsSeparator
= true;
1465 m_hasContents
= false;
1470 wxSizer
* const m_sizer
;
1471 wxWindow
* const m_parent
;
1473 // If true, we have some controls since the last group beginning. This is
1474 // used to avoid inserting two consecutive separators if EndOfGroup() is
1478 // If true, a separator should be inserted before adding the next button.
1479 bool m_needsSeparator
;
1481 wxDECLARE_NO_COPY_CLASS(SizerWithButtons
);
1484 } // anonymous namespace
1486 void wxPreviewControlBar::CreateButtons()
1488 SizerWithButtons
sizer(this);
1490 // Print button group (a single button).
1491 if (m_buttonFlags
& wxPREVIEW_PRINT
)
1493 sizer
.AddButton(wxID_PREVIEW_PRINT
, wxART_PRINT
, _("Print"));
1497 // Page selection buttons group.
1498 if (m_buttonFlags
& wxPREVIEW_FIRST
)
1500 sizer
.AddButton(wxID_PREVIEW_FIRST
, wxART_GOTO_FIRST
, _("First page"));
1503 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
1505 sizer
.AddButton(wxID_PREVIEW_PREVIOUS
, wxART_GO_BACK
, _("Previous page"));
1508 if (m_buttonFlags
& wxPREVIEW_GOTO
)
1510 m_currentPageText
= new wxPrintPageTextCtrl(this);
1511 sizer
.Add(m_currentPageText
);
1513 m_maxPageText
= new wxPrintPageMaxCtrl(this);
1514 sizer
.Add(m_maxPageText
);
1517 if (m_buttonFlags
& wxPREVIEW_NEXT
)
1519 sizer
.AddButton(wxID_PREVIEW_NEXT
, wxART_GO_FORWARD
, _("Next page"));
1522 if (m_buttonFlags
& wxPREVIEW_LAST
)
1524 sizer
.AddButton(wxID_PREVIEW_LAST
, wxART_GOTO_LAST
, _("Last page"));
1529 // Zoom controls group.
1530 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
1532 sizer
.AddButton(wxID_PREVIEW_ZOOM_OUT
, wxART_MINUS
, _("Zoom Out"));
1534 wxString choices
[] =
1536 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1537 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1538 wxT("120%"), wxT("150%"), wxT("200%")
1540 int n
= WXSIZEOF(choices
);
1542 m_zoomControl
= new wxChoice( this, wxID_PREVIEW_ZOOM
, wxDefaultPosition
, wxSize(70,wxDefaultCoord
), n
, choices
, 0 );
1543 sizer
.Add(m_zoomControl
);
1544 SetZoomControl(m_printPreview
->GetZoom());
1546 sizer
.AddButton(wxID_PREVIEW_ZOOM_IN
, wxART_PLUS
, _("Zoom In"));
1551 // Close button group (single button again).
1552 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("&Close"));
1553 sizer
.AddAtEnd(m_closeButton
);
1556 void wxPreviewControlBar::SetPageInfo(int minPage
, int maxPage
)
1558 if ( m_currentPageText
)
1559 m_currentPageText
->SetPageInfo(minPage
, maxPage
);
1561 if ( m_maxPageText
)
1562 m_maxPageText
->SetMaxPage(maxPage
);
1565 void wxPreviewControlBar::SetZoomControl(int zoom
)
1569 int n
, count
= m_zoomControl
->GetCount();
1571 for (n
=0; n
<count
; n
++)
1573 if (m_zoomControl
->GetString(n
).BeforeFirst(wxT('%')).ToLong(&val
) &&
1574 (val
>= long(zoom
)))
1576 m_zoomControl
->SetSelection(n
);
1581 m_zoomControl
->SetSelection(count
-1);
1585 int wxPreviewControlBar::GetZoomControl()
1587 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxEmptyString
))
1590 if (m_zoomControl
->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val
))
1602 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
1604 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
1605 EVT_CHAR_HOOK(wxPreviewFrame::OnChar
)
1606 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
1609 void wxPreviewFrame::OnChar(wxKeyEvent
&event
)
1611 if ( event
.GetKeyCode() == WXK_ESCAPE
)
1621 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxWindow
*parent
, const wxString
& title
,
1622 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
1623 wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
, name
)
1625 m_printPreview
= preview
;
1626 m_controlBar
= NULL
;
1627 m_previewCanvas
= NULL
;
1628 m_windowDisabler
= NULL
;
1629 m_modalityKind
= wxPreviewFrame_NonModal
;
1631 // Give the application icon
1633 wxFrame
* topFrame
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
1635 SetIcons(topFrame
->GetIcons());
1639 wxPreviewFrame::~wxPreviewFrame()
1641 wxPrintout
*printout
= m_printPreview
->GetPrintout();
1645 m_printPreview
->SetPrintout(NULL
);
1646 m_printPreview
->SetCanvas(NULL
);
1647 m_printPreview
->SetFrame(NULL
);
1650 m_previewCanvas
->SetPreview(NULL
);
1651 delete m_printPreview
;
1654 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
1656 // Reenable any windows we disabled by undoing whatever we did in our
1658 switch ( m_modalityKind
)
1660 case wxPreviewFrame_AppModal
:
1661 delete m_windowDisabler
;
1662 m_windowDisabler
= NULL
;
1665 case wxPreviewFrame_WindowModal
:
1667 GetParent()->Enable();
1670 case wxPreviewFrame_NonModal
:
1677 void wxPreviewFrame::InitializeWithModality(wxPreviewFrameModalityKind kind
)
1685 m_printPreview
->SetCanvas(m_previewCanvas
);
1686 m_printPreview
->SetFrame(this);
1688 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
1690 item0
->Add( m_controlBar
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1691 item0
->Add( m_previewCanvas
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1693 SetAutoLayout( true );
1696 m_modalityKind
= kind
;
1697 switch ( m_modalityKind
)
1699 case wxPreviewFrame_AppModal
:
1700 // Disable everything.
1701 m_windowDisabler
= new wxWindowDisabler( this );
1704 case wxPreviewFrame_WindowModal
:
1705 // Disable our parent if we have one.
1707 GetParent()->Disable();
1710 case wxPreviewFrame_NonModal
:
1711 // Nothing to do, we don't need to disable any windows.
1715 if ( m_modalityKind
!= wxPreviewFrame_NonModal
)
1717 // Behave like modal dialogs, don't show in taskbar. This implies
1718 // removing the minimize box, because minimizing windows without
1719 // taskbar entry is confusing.
1720 SetWindowStyle((GetWindowStyle() & ~wxMINIMIZE_BOX
) | wxFRAME_NO_TASKBAR
);
1725 m_printPreview
->AdjustScrollbars(m_previewCanvas
);
1726 m_previewCanvas
->SetFocus();
1727 m_controlBar
->SetFocus();
1730 void wxPreviewFrame::CreateCanvas()
1732 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
1735 void wxPreviewFrame::CreateControlBar()
1737 long buttons
= wxPREVIEW_DEFAULT
;
1738 if (m_printPreview
->GetPrintoutForPrinting())
1739 buttons
|= wxPREVIEW_PRINT
;
1741 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this);
1742 m_controlBar
->CreateButtons();
1749 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
1751 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1752 wxPrintout
*printoutForPrinting
,
1756 m_printDialogData
= (*data
);
1758 Init(printout
, printoutForPrinting
);
1761 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1762 wxPrintout
*printoutForPrinting
,
1763 wxPrintDialogData
*data
)
1766 m_printDialogData
= (*data
);
1768 Init(printout
, printoutForPrinting
);
1771 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
1772 wxPrintout
*printoutForPrinting
)
1775 m_previewPrintout
= printout
;
1776 if (m_previewPrintout
)
1777 m_previewPrintout
->SetPreview(static_cast<wxPrintPreview
*>(this));
1779 m_printPrintout
= printoutForPrinting
;
1781 m_previewCanvas
= NULL
;
1782 m_previewFrame
= NULL
;
1783 m_previewBitmap
= NULL
;
1784 m_previewFailed
= false;
1788 m_leftMargin
= 2*wxSizerFlags::GetDefaultBorder();
1791 m_printingPrepared
= false;
1796 wxPrintPreviewBase::~wxPrintPreviewBase()
1798 if (m_previewPrintout
)
1799 delete m_previewPrintout
;
1800 if (m_previewBitmap
)
1801 delete m_previewBitmap
;
1802 if (m_printPrintout
)
1803 delete m_printPrintout
;
1806 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
1808 if (m_currentPage
== pageNum
)
1811 m_currentPage
= pageNum
;
1813 InvalidatePreviewBitmap();
1815 if (m_previewCanvas
)
1817 AdjustScrollbars(m_previewCanvas
);
1819 m_previewCanvas
->Refresh();
1820 m_previewCanvas
->SetFocus();
1825 int wxPrintPreviewBase::GetCurrentPage() const
1826 { return m_currentPage
; }
1827 void wxPrintPreviewBase::SetPrintout(wxPrintout
*printout
)
1828 { m_previewPrintout
= printout
; }
1829 wxPrintout
*wxPrintPreviewBase::GetPrintout() const
1830 { return m_previewPrintout
; }
1831 wxPrintout
*wxPrintPreviewBase::GetPrintoutForPrinting() const
1832 { return m_printPrintout
; }
1833 void wxPrintPreviewBase::SetFrame(wxFrame
*frame
)
1834 { m_previewFrame
= frame
; }
1835 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas
*canvas
)
1836 { m_previewCanvas
= canvas
; }
1837 wxFrame
*wxPrintPreviewBase::GetFrame() const
1838 { return m_previewFrame
; }
1839 wxPreviewCanvas
*wxPrintPreviewBase::GetCanvas() const
1840 { return m_previewCanvas
; }
1842 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas
*canvas
, wxRect
& pageRect
, wxRect
& paperRect
)
1844 // Calculate the rectangles for the printable area of the page and the
1845 // entire paper as they appear on the canvas on-screen.
1846 int canvasWidth
, canvasHeight
;
1847 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
1849 float zoomScale
= float(m_currentZoom
) / 100;
1850 float screenPrintableWidth
= zoomScale
* m_pageWidth
* m_previewScaleX
;
1851 float screenPrintableHeight
= zoomScale
* m_pageHeight
* m_previewScaleY
;
1853 wxRect devicePaperRect
= m_previewPrintout
->GetPaperRectPixels();
1854 wxCoord devicePrintableWidth
, devicePrintableHeight
;
1855 m_previewPrintout
->GetPageSizePixels(&devicePrintableWidth
, &devicePrintableHeight
);
1856 float scaleX
= screenPrintableWidth
/ devicePrintableWidth
;
1857 float scaleY
= screenPrintableHeight
/ devicePrintableHeight
;
1858 paperRect
.width
= wxCoord(scaleX
* devicePaperRect
.width
);
1859 paperRect
.height
= wxCoord(scaleY
* devicePaperRect
.height
);
1861 paperRect
.x
= wxCoord((canvasWidth
- paperRect
.width
)/ 2.0);
1862 if (paperRect
.x
< m_leftMargin
)
1863 paperRect
.x
= m_leftMargin
;
1864 paperRect
.y
= wxCoord((canvasHeight
- paperRect
.height
)/ 2.0);
1865 if (paperRect
.y
< m_topMargin
)
1866 paperRect
.y
= m_topMargin
;
1868 pageRect
.x
= paperRect
.x
- wxCoord(scaleX
* devicePaperRect
.x
);
1869 pageRect
.y
= paperRect
.y
- wxCoord(scaleY
* devicePaperRect
.y
);
1870 pageRect
.width
= wxCoord(screenPrintableWidth
);
1871 pageRect
.height
= wxCoord(screenPrintableHeight
);
1875 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1877 wxDELETE(m_previewBitmap
);
1878 // if there was a problem with rendering the preview, try again now
1879 // that it changed in some way (less memory may be needed, for example):
1880 m_previewFailed
= false;
1883 bool wxPrintPreviewBase::UpdatePageRendering()
1885 if ( m_previewBitmap
)
1888 if ( m_previewFailed
)
1891 if ( !RenderPage(m_currentPage
) )
1893 m_previewFailed
= true; // don't waste time failing again
1900 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1902 DrawBlankPage(canvas
, dc
);
1904 if (!m_previewBitmap
)
1909 wxRect pageRect
, paperRect
;
1910 CalcRects(canvas
, pageRect
, paperRect
);
1912 temp_dc
.SelectObject(*m_previewBitmap
);
1914 dc
.Blit(pageRect
.x
, pageRect
.y
,
1915 m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
1917 temp_dc
.SelectObject(wxNullBitmap
);
1921 // Adjusts the scrollbars for the current scale
1922 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas
*canvas
)
1927 wxRect pageRect
, paperRect
;
1928 CalcRects(canvas
, pageRect
, paperRect
);
1929 int totalWidth
= paperRect
.width
+ 2 * m_leftMargin
;
1930 int totalHeight
= paperRect
.height
+ 2 * m_topMargin
;
1931 int scrollUnitsX
= totalWidth
/ 10;
1932 int scrollUnitsY
= totalHeight
/ 10;
1933 wxSize virtualSize
= canvas
->GetVirtualSize();
1934 if (virtualSize
.GetWidth() != totalWidth
|| virtualSize
.GetHeight() != totalHeight
)
1935 canvas
->SetScrollbars(10, 10, scrollUnitsX
, scrollUnitsY
, 0, 0, true);
1938 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC
& dc
, int pageNum
)
1940 m_previewPrintout
->SetDC(&dc
);
1941 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
1943 // Need to delay OnPreparePrinting() until here, so we have enough
1944 // information and a wxDC.
1945 if (!m_printingPrepared
)
1947 m_printingPrepared
= true;
1949 m_previewPrintout
->OnPreparePrinting();
1951 m_previewPrintout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
1953 // Update the wxPreviewControlBar page range display.
1954 if ( m_previewFrame
)
1956 wxPreviewControlBar
* const
1957 controlBar
= ((wxPreviewFrame
*)m_previewFrame
)->GetControlBar();
1959 controlBar
->SetPageInfo(m_minPage
, m_maxPage
);
1963 m_previewPrintout
->OnBeginPrinting();
1965 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
1967 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
1971 m_previewPrintout
->OnPrintPage(pageNum
);
1972 m_previewPrintout
->OnEndDocument();
1973 m_previewPrintout
->OnEndPrinting();
1975 m_previewPrintout
->SetDC(NULL
);
1980 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap
& bmp
, int pageNum
)
1982 wxMemoryDC memoryDC
;
1983 memoryDC
.SelectObject(bmp
);
1986 return RenderPageIntoDC(memoryDC
, pageNum
);
1989 bool wxPrintPreviewBase::RenderPage(int pageNum
)
1993 if (!m_previewCanvas
)
1995 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1999 wxRect pageRect
, paperRect
;
2000 CalcRects(m_previewCanvas
, pageRect
, paperRect
);
2002 if (!m_previewBitmap
)
2004 m_previewBitmap
= new wxBitmap(pageRect
.width
, pageRect
.height
);
2006 if (!m_previewBitmap
|| !m_previewBitmap
->IsOk())
2008 InvalidatePreviewBitmap();
2009 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2014 if ( !RenderPageIntoBitmap(*m_previewBitmap
, pageNum
) )
2016 InvalidatePreviewBitmap();
2017 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2024 status
= wxString::Format(_("Page %d of %d"), pageNum
, m_maxPage
);
2026 status
= wxString::Format(_("Page %d"), pageNum
);
2029 m_previewFrame
->SetStatusText(status
);
2035 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2037 wxRect pageRect
, paperRect
;
2039 CalcRects(canvas
, pageRect
, paperRect
);
2041 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
2042 wxCoord shadowOffset
= 4;
2044 dc
.SetPen(*wxBLACK_PEN
);
2045 dc
.SetBrush(*wxBLACK_BRUSH
);
2046 dc
.DrawRectangle(paperRect
.x
+ shadowOffset
, paperRect
.y
+ paperRect
.height
+ 1,
2047 paperRect
.width
, shadowOffset
);
2049 dc
.DrawRectangle(paperRect
.x
+ paperRect
.width
, paperRect
.y
+ shadowOffset
,
2050 shadowOffset
, paperRect
.height
);
2052 // Draw blank page allowing for 1-pixel border AROUND the actual paper
2053 dc
.SetPen(*wxBLACK_PEN
);
2054 dc
.SetBrush(*wxWHITE_BRUSH
);
2055 dc
.DrawRectangle(paperRect
.x
- 2, paperRect
.y
- 1,
2056 paperRect
.width
+ 3, paperRect
.height
+ 2);
2061 void wxPrintPreviewBase::SetZoom(int percent
)
2063 if (m_currentZoom
== percent
)
2066 m_currentZoom
= percent
;
2068 InvalidatePreviewBitmap();
2070 if (m_previewCanvas
)
2072 AdjustScrollbars(m_previewCanvas
);
2073 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
2074 m_previewCanvas
->ClearBackground();
2075 m_previewCanvas
->Refresh();
2076 m_previewCanvas
->SetFocus();
2080 wxPrintDialogData
& wxPrintPreviewBase::GetPrintDialogData()
2082 return m_printDialogData
;
2085 int wxPrintPreviewBase::GetZoom() const
2086 { return m_currentZoom
; }
2087 int wxPrintPreviewBase::GetMaxPage() const
2088 { return m_maxPage
; }
2089 int wxPrintPreviewBase::GetMinPage() const
2090 { return m_minPage
; }
2091 bool wxPrintPreviewBase::IsOk() const
2093 void wxPrintPreviewBase::SetOk(bool ok
)
2096 //----------------------------------------------------------------------------
2098 //----------------------------------------------------------------------------
2100 IMPLEMENT_CLASS(wxPrintPreview
, wxPrintPreviewBase
)
2102 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2103 wxPrintout
*printoutForPrinting
,
2104 wxPrintDialogData
*data
) :
2105 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2107 m_pimpl
= wxPrintFactory::GetFactory()->
2108 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2111 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2112 wxPrintout
*printoutForPrinting
,
2113 wxPrintData
*data
) :
2114 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2116 m_pimpl
= wxPrintFactory::GetFactory()->
2117 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2120 wxPrintPreview::~wxPrintPreview()
2124 // don't delete twice
2125 m_printPrintout
= NULL
;
2126 m_previewPrintout
= NULL
;
2127 m_previewBitmap
= NULL
;
2130 bool wxPrintPreview::SetCurrentPage(int pageNum
)
2132 return m_pimpl
->SetCurrentPage( pageNum
);
2135 int wxPrintPreview::GetCurrentPage() const
2137 return m_pimpl
->GetCurrentPage();
2140 void wxPrintPreview::SetPrintout(wxPrintout
*printout
)
2142 m_pimpl
->SetPrintout( printout
);
2145 wxPrintout
*wxPrintPreview::GetPrintout() const
2147 return m_pimpl
->GetPrintout();
2150 wxPrintout
*wxPrintPreview::GetPrintoutForPrinting() const
2152 return m_pimpl
->GetPrintoutForPrinting();
2155 void wxPrintPreview::SetFrame(wxFrame
*frame
)
2157 m_pimpl
->SetFrame( frame
);
2160 void wxPrintPreview::SetCanvas(wxPreviewCanvas
*canvas
)
2162 m_pimpl
->SetCanvas( canvas
);
2165 wxFrame
*wxPrintPreview::GetFrame() const
2167 return m_pimpl
->GetFrame();
2170 wxPreviewCanvas
*wxPrintPreview::GetCanvas() const
2172 return m_pimpl
->GetCanvas();
2175 bool wxPrintPreview::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2177 return m_pimpl
->PaintPage( canvas
, dc
);
2180 bool wxPrintPreview::UpdatePageRendering()
2182 return m_pimpl
->UpdatePageRendering();
2185 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2187 return m_pimpl
->DrawBlankPage( canvas
, dc
);
2190 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas
*canvas
)
2192 m_pimpl
->AdjustScrollbars( canvas
);
2195 bool wxPrintPreview::RenderPage(int pageNum
)
2197 return m_pimpl
->RenderPage( pageNum
);
2200 void wxPrintPreview::SetZoom(int percent
)
2202 m_pimpl
->SetZoom( percent
);
2205 int wxPrintPreview::GetZoom() const
2207 return m_pimpl
->GetZoom();
2210 wxPrintDialogData
& wxPrintPreview::GetPrintDialogData()
2212 return m_pimpl
->GetPrintDialogData();
2215 int wxPrintPreview::GetMaxPage() const
2217 return m_pimpl
->GetMaxPage();
2220 int wxPrintPreview::GetMinPage() const
2222 return m_pimpl
->GetMinPage();
2225 bool wxPrintPreview::IsOk() const
2227 return m_pimpl
->IsOk();
2230 void wxPrintPreview::SetOk(bool ok
)
2232 m_pimpl
->SetOk( ok
);
2235 bool wxPrintPreview::Print(bool interactive
)
2237 return m_pimpl
->Print( interactive
);
2240 void wxPrintPreview::DetermineScaling()
2242 m_pimpl
->DetermineScaling();
2245 #endif // wxUSE_PRINTING_ARCHITECTURE