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 wxWindow
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
* printout
)
326 wxPrintAbortDialog
*dialog
= new wxPrintAbortDialog(parent
, _("Printing ") , wxDefaultPosition
, wxDefaultSize
, wxDEFAULT_DIALOG_STYLE
);
328 wxBoxSizer
*button_sizer
= new wxBoxSizer( wxVERTICAL
);
329 button_sizer
->Add( new wxStaticText(dialog
, wxID_ANY
, _("Please wait while printing\n") + printout
->GetTitle() ), 0, wxALL
, 10 );
330 button_sizer
->Add( new wxButton( dialog
, wxID_CANCEL
, wxT("Cancel") ), 0, wxALL
| wxALIGN_CENTER
, 10 );
332 dialog
->SetAutoLayout( true );
333 dialog
->SetSizer( button_sizer
);
335 button_sizer
->Fit(dialog
);
336 button_sizer
->SetSizeHints (dialog
) ;
341 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), const wxString
& message
)
343 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
346 wxPrintDialogData
& wxPrinterBase::GetPrintDialogData() const
348 return (wxPrintDialogData
&) m_printDialogData
;
351 //----------------------------------------------------------------------------
353 //----------------------------------------------------------------------------
355 IMPLEMENT_CLASS(wxPrinter
, wxPrinterBase
)
357 wxPrinter::wxPrinter(wxPrintDialogData
*data
)
359 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrinter( data
);
362 wxPrinter::~wxPrinter()
367 wxWindow
*wxPrinter::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*printout
)
369 return m_pimpl
->CreateAbortWindow( parent
, printout
);
372 void wxPrinter::ReportError(wxWindow
*parent
, wxPrintout
*printout
, const wxString
& message
)
374 m_pimpl
->ReportError( parent
, printout
, message
);
377 bool wxPrinter::Setup(wxWindow
*parent
)
379 return m_pimpl
->Setup( parent
);
382 bool wxPrinter::Print(wxWindow
*parent
, wxPrintout
*printout
, bool prompt
)
384 if ( !prompt
&& m_printDialogData
.GetToPage() == 0 )
386 // If the dialog is not shown, set the pages range to print everything
387 // by default (as otherwise we wouldn't print anything at all which is
388 // certainly not a reasonable default behaviour).
389 int minPage
, maxPage
, selFrom
, selTo
;
390 printout
->GetPageInfo(&minPage
, &maxPage
, &selFrom
, &selTo
);
392 wxPrintDialogData
& pdd
= m_pimpl
->GetPrintDialogData();
393 pdd
.SetFromPage(minPage
);
394 pdd
.SetToPage(maxPage
);
397 return m_pimpl
->Print( parent
, printout
, prompt
);
400 wxDC
* wxPrinter::PrintDialog(wxWindow
*parent
)
402 return m_pimpl
->PrintDialog( parent
);
405 wxPrintDialogData
& wxPrinter::GetPrintDialogData() const
407 return m_pimpl
->GetPrintDialogData();
410 // ---------------------------------------------------------------------------
411 // wxPrintDialogBase: the dialog for printing.
412 // ---------------------------------------------------------------------------
414 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase
, wxDialog
)
416 wxPrintDialogBase::wxPrintDialogBase(wxWindow
*parent
,
418 const wxString
&title
,
422 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Print")) : title
,
427 // ---------------------------------------------------------------------------
428 // wxPrintDialog: the dialog for printing
429 // ---------------------------------------------------------------------------
431 IMPLEMENT_CLASS(wxPrintDialog
, wxObject
)
433 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintDialogData
* data
)
435 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
438 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintData
* data
)
440 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
443 wxPrintDialog::~wxPrintDialog()
448 int wxPrintDialog::ShowModal()
450 return m_pimpl
->ShowModal();
453 wxPrintDialogData
& wxPrintDialog::GetPrintDialogData()
455 return m_pimpl
->GetPrintDialogData();
458 wxPrintData
& wxPrintDialog::GetPrintData()
460 return m_pimpl
->GetPrintData();
463 wxDC
*wxPrintDialog::GetPrintDC()
465 return m_pimpl
->GetPrintDC();
468 // ---------------------------------------------------------------------------
469 // wxPageSetupDialogBase: the page setup dialog
470 // ---------------------------------------------------------------------------
472 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase
, wxDialog
)
474 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow
*parent
,
476 const wxString
&title
,
480 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Page setup")) : title
,
485 // ---------------------------------------------------------------------------
486 // wxPageSetupDialog: the page setup dialog
487 // ---------------------------------------------------------------------------
489 IMPLEMENT_CLASS(wxPageSetupDialog
, wxObject
)
491 wxPageSetupDialog::wxPageSetupDialog(wxWindow
*parent
, wxPageSetupDialogData
*data
)
493 m_pimpl
= wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent
, data
);
496 wxPageSetupDialog::~wxPageSetupDialog()
501 int wxPageSetupDialog::ShowModal()
503 return m_pimpl
->ShowModal();
506 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupDialogData()
508 return m_pimpl
->GetPageSetupDialogData();
512 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupData()
514 return m_pimpl
->GetPageSetupDialogData();
517 //----------------------------------------------------------------------------
518 // wxPrintAbortDialog
519 //----------------------------------------------------------------------------
521 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
522 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
525 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
527 wxPrinterBase::sm_abortIt
= true;
528 wxPrinterBase::sm_abortWindow
->Show(false);
529 wxPrinterBase::sm_abortWindow
->Close(true);
530 wxPrinterBase::sm_abortWindow
->Destroy();
531 wxPrinterBase::sm_abortWindow
= NULL
;
534 //----------------------------------------------------------------------------
536 //----------------------------------------------------------------------------
538 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
540 wxPrintout::wxPrintout(const wxString
& title
)
542 m_printoutTitle
= title
;
546 m_pageWidthPixels
= 0;
547 m_pageHeightPixels
= 0;
555 wxPrintout::~wxPrintout()
559 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
561 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle
);
564 void wxPrintout::OnEndDocument()
569 void wxPrintout::OnBeginPrinting()
573 void wxPrintout::OnEndPrinting()
577 bool wxPrintout::HasPage(int page
)
582 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
590 void wxPrintout::FitThisSizeToPaper(const wxSize
& imageSize
)
592 // Set the DC scale and origin so that the given image size fits within the
593 // entire page and the origin is at the top left corner of the page. Note
594 // that with most printers, portions of the page will be non-printable. Use
595 // this if you're managing your own page margins.
596 if (!m_printoutDC
) return;
597 wxRect paperRect
= GetPaperRectPixels();
599 GetPageSizePixels(&pw
, &ph
);
601 m_printoutDC
->GetSize(&w
, &h
);
602 float scaleX
= ((float(paperRect
.width
) * w
) / (float(pw
) * imageSize
.x
));
603 float scaleY
= ((float(paperRect
.height
) * h
) / (float(ph
) * imageSize
.y
));
604 float actualScale
= wxMin(scaleX
, scaleY
);
605 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
606 m_printoutDC
->SetDeviceOrigin(0, 0);
607 wxRect logicalPaperRect
= GetLogicalPaperRect();
608 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
611 void wxPrintout::FitThisSizeToPage(const wxSize
& imageSize
)
613 // Set the DC scale and origin so that the given image size fits within the
614 // printable area of the page and the origin is at the top left corner of
615 // the printable area.
616 if (!m_printoutDC
) return;
618 m_printoutDC
->GetSize(&w
, &h
);
619 float scaleX
= float(w
) / imageSize
.x
;
620 float scaleY
= float(h
) / imageSize
.y
;
621 float actualScale
= wxMin(scaleX
, scaleY
);
622 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
623 m_printoutDC
->SetDeviceOrigin(0, 0);
626 void wxPrintout::FitThisSizeToPageMargins(const wxSize
& imageSize
, const wxPageSetupDialogData
& pageSetupData
)
628 // Set the DC scale and origin so that the given image size fits within the
629 // page margins defined in the given wxPageSetupDialogData object and the
630 // origin is at the top left corner of the page margins.
631 if (!m_printoutDC
) return;
632 wxRect paperRect
= GetPaperRectPixels();
634 GetPageSizePixels(&pw
, &ph
);
635 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
636 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
638 GetPageSizeMM(&mw
, &mh
);
639 float mmToDeviceX
= float(pw
) / mw
;
640 float mmToDeviceY
= float(ph
) / mh
;
641 wxRect
pageMarginsRect(paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
642 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
643 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
644 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
646 m_printoutDC
->GetSize(&w
, &h
);
647 float scaleX
= (float(pageMarginsRect
.width
) * w
) / (float(pw
) * imageSize
.x
);
648 float scaleY
= (float(pageMarginsRect
.height
) * h
) / (float(ph
) * imageSize
.y
);
649 float actualScale
= wxMin(scaleX
, scaleY
);
650 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
651 m_printoutDC
->SetDeviceOrigin(0, 0);
652 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
653 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
656 void wxPrintout::MapScreenSizeToPaper()
658 // Set the DC scale so that an image on the screen is the same size on the
659 // paper and the origin is at the top left of the paper. Note that with most
660 // printers, portions of the page will be cut off. Use this if you're
661 // managing your own page margins.
662 if (!m_printoutDC
) return;
663 MapScreenSizeToPage();
664 wxRect logicalPaperRect
= GetLogicalPaperRect();
665 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
668 void wxPrintout::MapScreenSizeToPage()
670 // Set the DC scale and origin so that an image on the screen is the same
671 // size on the paper and the origin is at the top left of the printable area.
672 if (!m_printoutDC
) return;
673 int ppiScreenX
, ppiScreenY
;
674 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
675 int ppiPrinterX
, ppiPrinterY
;
676 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
678 m_printoutDC
->GetSize(&w
, &h
);
679 int pageSizePixelsX
, pageSizePixelsY
;
680 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
681 float userScaleX
= (float(ppiPrinterX
) * w
) / (float(ppiScreenX
) * pageSizePixelsX
);
682 float userScaleY
= (float(ppiPrinterY
) * h
) / (float(ppiScreenY
) * pageSizePixelsY
);
683 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
684 m_printoutDC
->SetDeviceOrigin(0, 0);
687 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData
& pageSetupData
)
689 // Set the DC scale so that an image on the screen is the same size on the
690 // paper and the origin is at the top left of the page margins defined by
691 // the given wxPageSetupDialogData object.
692 if (!m_printoutDC
) return;
693 MapScreenSizeToPage();
694 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
695 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
698 void wxPrintout::MapScreenSizeToDevice()
700 // Set the DC scale so that a screen pixel is the same size as a device
701 // pixel and the origin is at the top left of the printable area.
702 if (!m_printoutDC
) return;
704 m_printoutDC
->GetSize(&w
, &h
);
705 int pageSizePixelsX
, pageSizePixelsY
;
706 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
707 float userScaleX
= float(w
) / pageSizePixelsX
;
708 float userScaleY
= float(h
) / pageSizePixelsY
;
709 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
710 m_printoutDC
->SetDeviceOrigin(0, 0);
713 wxRect
wxPrintout::GetLogicalPaperRect() const
715 // Return the rectangle in logical units that corresponds to the paper
717 wxRect paperRect
= GetPaperRectPixels();
719 GetPageSizePixels(&pw
, &ph
);
721 m_printoutDC
->GetSize(&w
, &h
);
722 if (w
== pw
&& h
== ph
) {
723 // this DC matches the printed page, so no scaling
724 return wxRect(m_printoutDC
->DeviceToLogicalX(paperRect
.x
),
725 m_printoutDC
->DeviceToLogicalY(paperRect
.y
),
726 m_printoutDC
->DeviceToLogicalXRel(paperRect
.width
),
727 m_printoutDC
->DeviceToLogicalYRel(paperRect
.height
));
729 // This DC doesn't match the printed page, so we have to scale.
730 float scaleX
= float(w
) / pw
;
731 float scaleY
= float(h
) / ph
;
732 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(paperRect
.x
* scaleX
)),
733 m_printoutDC
->DeviceToLogicalY(wxRound(paperRect
.y
* scaleY
)),
734 m_printoutDC
->DeviceToLogicalXRel(wxRound(paperRect
.width
* scaleX
)),
735 m_printoutDC
->DeviceToLogicalYRel(wxRound(paperRect
.height
* scaleY
)));
738 wxRect
wxPrintout::GetLogicalPageRect() const
740 // Return the rectangle in logical units that corresponds to the printable
743 m_printoutDC
->GetSize(&w
, &h
);
744 return wxRect(m_printoutDC
->DeviceToLogicalX(0),
745 m_printoutDC
->DeviceToLogicalY(0),
746 m_printoutDC
->DeviceToLogicalXRel(w
),
747 m_printoutDC
->DeviceToLogicalYRel(h
));
750 wxRect
wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData
& pageSetupData
) const
752 // Return the rectangle in logical units that corresponds to the region
753 // within the page margins as specified by the given wxPageSetupDialogData
756 // We get the paper size in device units and the margins in mm,
757 // so we need to calculate the conversion with this trick
759 GetPageSizePixels(&pw
, &ph
);
761 GetPageSizeMM(&mw
, &mh
);
762 float mmToDeviceX
= float(pw
) / mw
;
763 float mmToDeviceY
= float(ph
) / mh
;
765 // paper size in device units
766 wxRect paperRect
= GetPaperRectPixels();
769 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
770 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
772 // calculate margins in device units
773 wxRect
pageMarginsRect(
774 paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
775 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
776 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
777 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
780 m_printoutDC
->GetSize(&w
, &h
);
781 if (w
== pw
&& h
== ph
)
783 // this DC matches the printed page, so no scaling
785 m_printoutDC
->DeviceToLogicalX(pageMarginsRect
.x
),
786 m_printoutDC
->DeviceToLogicalY(pageMarginsRect
.y
),
787 m_printoutDC
->DeviceToLogicalXRel(pageMarginsRect
.width
),
788 m_printoutDC
->DeviceToLogicalYRel(pageMarginsRect
.height
));
791 // This DC doesn't match the printed page, so we have to scale.
792 float scaleX
= float(w
) / pw
;
793 float scaleY
= float(h
) / ph
;
794 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(pageMarginsRect
.x
* scaleX
)),
795 m_printoutDC
->DeviceToLogicalY(wxRound(pageMarginsRect
.y
* scaleY
)),
796 m_printoutDC
->DeviceToLogicalXRel(wxRound(pageMarginsRect
.width
* scaleX
)),
797 m_printoutDC
->DeviceToLogicalYRel(wxRound(pageMarginsRect
.height
* scaleY
)));
800 void wxPrintout::SetLogicalOrigin(wxCoord x
, wxCoord y
)
802 // Set the device origin by specifying a point in logical coordinates.
803 m_printoutDC
->SetDeviceOrigin(
804 m_printoutDC
->LogicalToDeviceX(x
),
805 m_printoutDC
->LogicalToDeviceY(y
) );
808 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff
, wxCoord yoff
)
810 // Offset the device origin by a specified distance in device coordinates.
811 wxPoint dev_org
= m_printoutDC
->GetDeviceOrigin();
812 m_printoutDC
->SetDeviceOrigin(
813 dev_org
.x
+ m_printoutDC
->LogicalToDeviceXRel(xoff
),
814 dev_org
.y
+ m_printoutDC
->LogicalToDeviceYRel(yoff
) );
818 //----------------------------------------------------------------------------
820 //----------------------------------------------------------------------------
822 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
824 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
825 EVT_PAINT(wxPreviewCanvas::OnPaint
)
826 EVT_CHAR(wxPreviewCanvas::OnChar
)
827 EVT_IDLE(wxPreviewCanvas::OnIdle
)
828 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
830 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel
)
834 // VZ: the current code doesn't refresh properly without
835 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
836 // really horrible flicker when resizing the preview frame, but without
837 // this style it simply doesn't work correctly at all...
838 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
839 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
840 wxScrolledWindow(parent
, wxID_ANY
, pos
, size
, style
| wxFULL_REPAINT_ON_RESIZE
, name
)
842 m_printPreview
= preview
;
844 // The app workspace colour is always white, but we should have
845 // a contrast with the page.
846 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
847 #elif defined(__WXGTK__)
848 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
850 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
852 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
854 SetScrollbars(10, 10, 100, 100);
857 wxPreviewCanvas::~wxPreviewCanvas()
861 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
868 if (!GetUpdateRegion().IsEmpty())
869 dc.SetClippingRegion( GetUpdateRegion() );
875 m_printPreview
->PaintPage(this, dc
);
879 void wxPreviewCanvas::OnIdle(wxIdleEvent
& event
)
883 // prevent UpdatePageRendering() from being called recursively:
884 static bool s_inIdle
= false;
889 if ( m_printPreview
)
891 if ( m_printPreview
->UpdatePageRendering() )
898 // Responds to colour changes, and passes event on to children.
899 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
902 // The app workspace colour is always white, but we should have
903 // a contrast with the page.
904 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
905 #elif defined(__WXGTK__)
906 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
908 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
910 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
913 // Propagate the event to the non-top-level children
914 wxWindow::OnSysColourChanged(event
);
917 void wxPreviewCanvas::OnChar(wxKeyEvent
&event
)
919 wxPreviewControlBar
* controlBar
= ((wxPreviewFrame
*) GetParent())->GetControlBar();
920 switch (event
.GetKeyCode())
923 controlBar
->OnPrint();
928 controlBar
->DoZoomIn();
931 case WXK_NUMPAD_SUBTRACT
:
933 controlBar
->DoZoomOut();
937 if (!event
.ControlDown())
943 switch(event
.GetKeyCode())
946 controlBar
->OnNext(); break;
948 controlBar
->OnPrevious(); break;
950 controlBar
->OnFirst(); break;
952 controlBar
->OnLast(); break;
960 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent
& event
)
962 wxPreviewControlBar
*
963 controlBar
= wxStaticCast(GetParent(), wxPreviewFrame
)->GetControlBar();
967 if ( event
.ControlDown() && event
.GetWheelRotation() != 0 )
969 int currentZoom
= controlBar
->GetZoomControl();
972 if ( currentZoom
< 100 )
974 else if ( currentZoom
<= 120 )
979 if ( event
.GetWheelRotation() > 0 )
982 int newZoom
= currentZoom
+ delta
;
987 if ( newZoom
!= currentZoom
)
989 controlBar
->SetZoomControl(newZoom
);
990 m_printPreview
->SetZoom(newZoom
);
1000 #endif // wxUSE_MOUSEWHEEL
1005 // This is by the controls in the print preview as the maximal (and hence
1006 // longest) page number we may have to display.
1007 enum { MAX_PAGE_NUMBER
= 99999 };
1009 } // anonymous namespace
1011 // ----------------------------------------------------------------------------
1012 // wxPrintPageMaxCtrl
1013 // ----------------------------------------------------------------------------
1015 // A simple static control showing the maximal number of pages.
1016 class wxPrintPageMaxCtrl
: public wxStaticText
1019 wxPrintPageMaxCtrl(wxWindow
*parent
)
1027 parent
->GetTextExtent(MaxAsString(MAX_PAGE_NUMBER
)).x
,
1030 wxST_NO_AUTORESIZE
| wxALIGN_CENTRE
1035 // Set the maximal page to display once we really know what it is.
1036 void SetMaxPage(int maxPage
)
1038 SetLabel(MaxAsString(maxPage
));
1042 static wxString
MaxAsString(int maxPage
)
1044 return wxString::Format("/ %d", maxPage
);
1047 wxDECLARE_NO_COPY_CLASS(wxPrintPageMaxCtrl
);
1050 // ----------------------------------------------------------------------------
1051 // wxPrintPageTextCtrl
1052 // ----------------------------------------------------------------------------
1054 // This text control contains the page number in the specified interval.
1056 // Invalid pages are not accepted and the control contents is validated when it
1057 // loses focus. Conversely, if the user changes the page to another valid one
1058 // or presses Enter, OnGotoPage() method of the preview object will be called.
1059 class wxPrintPageTextCtrl
: public wxTextCtrl
1062 wxPrintPageTextCtrl(wxPreviewControlBar
*preview
)
1063 : wxTextCtrl(preview
,
1067 // We use hardcoded maximal page number for the width
1068 // instead of fitting it to the values we can show because
1069 // the control looks uncomfortably narrow if the real page
1070 // number is just one or two digits.
1073 preview
->GetTextExtent(PageAsString(MAX_PAGE_NUMBER
)).x
,
1077 #if wxUSE_VALIDATORS
1078 , wxTextValidator(wxFILTER_DIGITS
)
1079 #endif // wxUSE_VALIDATORS
1087 Connect(wxEVT_KILL_FOCUS
,
1088 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus
));
1089 Connect(wxEVT_COMMAND_TEXT_ENTER
,
1090 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter
));
1093 // Update the pages range, must be called after OnPreparePrinting() as
1094 // these values are not known before.
1095 void SetPageInfo(int minPage
, int maxPage
)
1097 m_minPage
= minPage
;
1098 m_maxPage
= maxPage
;
1100 // Show the first page by default.
1101 SetPageNumber(minPage
);
1104 // Helpers to conveniently set or get the current page number. Return value
1105 // is 0 if the current controls contents is invalid.
1106 void SetPageNumber(int page
)
1108 wxASSERT( IsValidPage(page
) );
1110 SetValue(PageAsString(page
));
1113 int GetPageNumber() const
1116 if ( !GetValue().ToLong(&value
) || !IsValidPage(value
) )
1119 // Cast is safe because the value is less than (int) m_maxPage.
1120 return static_cast<int>(value
);
1124 static wxString
PageAsString(int page
)
1126 return wxString::Format("%d", page
);
1129 bool IsValidPage(int page
) const
1131 return page
>= m_minPage
&& page
<= m_maxPage
;
1136 const int page
= GetPageNumber();
1141 if ( page
!= m_page
)
1143 // We have a valid page, remember it.
1146 // And notify the owner about the change.
1147 m_preview
->OnGotoPage();
1149 //else: Nothing really changed.
1154 void OnKillFocus(wxFocusEvent
& event
)
1156 if ( !DoChangePage() )
1158 // The current contents is invalid so reset it back to the last
1159 // known good page index.
1160 SetPageNumber(m_page
);
1166 void OnTextEnter(wxCommandEvent
& WXUNUSED(event
))
1172 wxPreviewControlBar
* const m_preview
;
1177 // This is the last valid page value that we had, we revert to it if an
1178 // invalid page is entered.
1181 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl
);
1184 //----------------------------------------------------------------------------
1185 // wxPreviewControlBar
1186 //----------------------------------------------------------------------------
1188 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
1190 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
1191 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
1192 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrintButton
)
1193 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
1194 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
1195 EVT_BUTTON(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnFirstButton
)
1196 EVT_BUTTON(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnLastButton
)
1197 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnZoomInButton
)
1198 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnZoomOutButton
)
1200 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnUpdatePreviousButton
)
1201 EVT_UPDATE_UI(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnUpdateNextButton
)
1202 EVT_UPDATE_UI(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnUpdateFirstButton
)
1203 EVT_UPDATE_UI(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnUpdateLastButton
)
1204 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnUpdateZoomInButton
)
1205 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnUpdateZoomOutButton
)
1207 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoomChoice
)
1208 EVT_PAINT(wxPreviewControlBar::OnPaint
)
1212 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
1213 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
1214 long style
, const wxString
& name
):
1215 wxPanel(parent
, wxID_ANY
, pos
, size
, style
, name
)
1217 m_printPreview
= preview
;
1218 m_closeButton
= NULL
;
1219 m_zoomControl
= NULL
;
1220 m_currentPageText
= NULL
;
1221 m_maxPageText
= NULL
;
1222 m_buttonFlags
= buttons
;
1225 wxPreviewControlBar::~wxPreviewControlBar()
1229 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1235 dc
.SetPen(*wxBLACK_PEN
);
1236 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1237 dc
.DrawLine( 0, h
-1, w
, h
-1 );
1240 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
1242 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
1246 void wxPreviewControlBar::OnPrint(void)
1248 wxPrintPreviewBase
*preview
= GetPrintPreview();
1249 preview
->Print(true);
1252 void wxPreviewControlBar::OnNext()
1254 if ( IsNextEnabled() )
1255 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1258 void wxPreviewControlBar::OnPrevious()
1260 if ( IsPreviousEnabled() )
1261 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1264 void wxPreviewControlBar::OnFirst()
1266 if ( IsFirstEnabled() )
1267 DoGotoPage(GetPrintPreview()->GetMinPage());
1270 void wxPreviewControlBar::OnLast()
1272 if ( IsLastEnabled() )
1273 DoGotoPage(GetPrintPreview()->GetMaxPage());
1276 bool wxPreviewControlBar::IsNextEnabled() const
1278 wxPrintPreviewBase
*preview
= GetPrintPreview();
1282 const int currentPage
= preview
->GetCurrentPage();
1283 return currentPage
< preview
->GetMaxPage() &&
1284 preview
->GetPrintout()->HasPage(currentPage
+ 1);
1287 bool wxPreviewControlBar::IsPreviousEnabled() const
1289 wxPrintPreviewBase
*preview
= GetPrintPreview();
1293 const int currentPage
= preview
->GetCurrentPage();
1294 return currentPage
> preview
->GetMinPage() &&
1295 preview
->GetPrintout()->HasPage(currentPage
- 1);
1298 bool wxPreviewControlBar::IsFirstEnabled() const
1300 wxPrintPreviewBase
*preview
= GetPrintPreview();
1304 return preview
->GetPrintout()->HasPage(preview
->GetMinPage());
1307 bool wxPreviewControlBar::IsLastEnabled() const
1309 wxPrintPreviewBase
*preview
= GetPrintPreview();
1313 return preview
->GetPrintout()->HasPage(preview
->GetMaxPage());
1316 void wxPreviewControlBar::DoGotoPage(int page
)
1318 wxPrintPreviewBase
*preview
= GetPrintPreview();
1319 wxCHECK_RET( preview
, "Shouldn't be called if there is no preview." );
1321 preview
->SetCurrentPage(page
);
1323 if ( m_currentPageText
)
1324 m_currentPageText
->SetPageNumber(page
);
1327 void wxPreviewControlBar::OnGotoPage()
1329 wxPrintPreviewBase
*preview
= GetPrintPreview();
1332 if (preview
->GetMinPage() > 0)
1334 long currentPage
= m_currentPageText
->GetPageNumber();
1337 if (preview
->GetPrintout()->HasPage(currentPage
))
1339 preview
->SetCurrentPage(currentPage
);
1346 void wxPreviewControlBar::DoZoom()
1348 int zoom
= GetZoomControl();
1349 if (GetPrintPreview())
1350 GetPrintPreview()->SetZoom(zoom
);
1353 bool wxPreviewControlBar::IsZoomInEnabled() const
1355 if ( !m_zoomControl
)
1358 const unsigned sel
= m_zoomControl
->GetSelection();
1359 return sel
< m_zoomControl
->GetCount() - 1;
1362 bool wxPreviewControlBar::IsZoomOutEnabled() const
1364 return m_zoomControl
&& m_zoomControl
->GetSelection() > 0;
1367 void wxPreviewControlBar::DoZoomIn()
1369 if (IsZoomInEnabled())
1371 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() + 1);
1376 void wxPreviewControlBar::DoZoomOut()
1378 if (IsZoomOutEnabled())
1380 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() - 1);
1388 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1389 // sequentially to it in the simplest way possible.
1390 class SizerWithButtons
1393 // Constructor creates the sizer that will hold the buttons and stores the
1394 // parent that will be used for their creation.
1395 SizerWithButtons(wxWindow
*parent
)
1396 : m_sizer(new wxBoxSizer(wxHORIZONTAL
)),
1400 m_needsSeparator
= false;
1403 // Destructor associates the sizer with the parent window.
1406 m_parent
->SetSizer(m_sizer
);
1407 m_sizer
->Fit(m_parent
);
1411 // Add an arbitrary window to the sizer.
1412 void Add(wxWindow
*win
)
1414 if ( m_needsSeparator
)
1416 m_needsSeparator
= false;
1418 m_sizer
->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1421 m_hasContents
= true;
1424 wxSizerFlags().Border(wxLEFT
| wxTOP
| wxBOTTOM
).Center());
1427 // Add a button with the specified id, bitmap and tooltip.
1428 void AddButton(wxWindowID btnId
,
1429 const wxArtID
& artId
,
1430 const wxString
& tooltip
)
1432 // We don't use (smaller) images inside a button with a text label but
1433 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1434 // wxART_BUTTON here.
1435 wxBitmap bmp
= wxArtProvider::GetBitmap(artId
, wxART_TOOLBAR
);
1436 wxBitmapButton
* const btn
= new wxBitmapButton(m_parent
, btnId
, bmp
);
1437 btn
->SetToolTip(tooltip
);
1442 // Add a control at the right end of the window. This should be called last
1443 // as everything else added after it will be added on the right side too.
1444 void AddAtEnd(wxWindow
*win
)
1446 m_sizer
->AddStretchSpacer();
1448 wxSizerFlags().Border(wxTOP
| wxBOTTOM
| wxRIGHT
).Center());
1451 // Indicates the end of a group of buttons, a separator will be added after
1455 if ( m_hasContents
)
1457 m_needsSeparator
= true;
1458 m_hasContents
= false;
1463 wxSizer
* const m_sizer
;
1464 wxWindow
* const m_parent
;
1466 // If true, we have some controls since the last group beginning. This is
1467 // used to avoid inserting two consecutive separators if EndOfGroup() is
1471 // If true, a separator should be inserted before adding the next button.
1472 bool m_needsSeparator
;
1474 wxDECLARE_NO_COPY_CLASS(SizerWithButtons
);
1477 } // anonymous namespace
1479 void wxPreviewControlBar::CreateButtons()
1481 SizerWithButtons
sizer(this);
1483 // Print button group (a single button).
1484 if (m_buttonFlags
& wxPREVIEW_PRINT
)
1486 sizer
.AddButton(wxID_PREVIEW_PRINT
, wxART_PRINT
, _("Print"));
1490 // Page selection buttons group.
1491 if (m_buttonFlags
& wxPREVIEW_FIRST
)
1493 sizer
.AddButton(wxID_PREVIEW_FIRST
, wxART_GOTO_FIRST
, _("First page"));
1496 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
1498 sizer
.AddButton(wxID_PREVIEW_PREVIOUS
, wxART_GO_BACK
, _("Previous page"));
1501 if (m_buttonFlags
& wxPREVIEW_GOTO
)
1503 m_currentPageText
= new wxPrintPageTextCtrl(this);
1504 sizer
.Add(m_currentPageText
);
1506 m_maxPageText
= new wxPrintPageMaxCtrl(this);
1507 sizer
.Add(m_maxPageText
);
1510 if (m_buttonFlags
& wxPREVIEW_NEXT
)
1512 sizer
.AddButton(wxID_PREVIEW_NEXT
, wxART_GO_FORWARD
, _("Next page"));
1515 if (m_buttonFlags
& wxPREVIEW_LAST
)
1517 sizer
.AddButton(wxID_PREVIEW_LAST
, wxART_GOTO_LAST
, _("Last page"));
1522 // Zoom controls group.
1523 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
1525 sizer
.AddButton(wxID_PREVIEW_ZOOM_OUT
, wxART_MINUS
, _("Zoom Out"));
1527 wxString choices
[] =
1529 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1530 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1531 wxT("120%"), wxT("150%"), wxT("200%")
1533 int n
= WXSIZEOF(choices
);
1535 m_zoomControl
= new wxChoice( this, wxID_PREVIEW_ZOOM
, wxDefaultPosition
, wxSize(70,wxDefaultCoord
), n
, choices
, 0 );
1536 sizer
.Add(m_zoomControl
);
1537 SetZoomControl(m_printPreview
->GetZoom());
1539 sizer
.AddButton(wxID_PREVIEW_ZOOM_IN
, wxART_PLUS
, _("Zoom In"));
1544 // Close button group (single button again).
1545 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("&Close"));
1546 sizer
.AddAtEnd(m_closeButton
);
1549 void wxPreviewControlBar::SetPageInfo(int minPage
, int maxPage
)
1551 if ( m_currentPageText
)
1552 m_currentPageText
->SetPageInfo(minPage
, maxPage
);
1554 if ( m_maxPageText
)
1555 m_maxPageText
->SetMaxPage(maxPage
);
1558 void wxPreviewControlBar::SetZoomControl(int zoom
)
1562 int n
, count
= m_zoomControl
->GetCount();
1564 for (n
=0; n
<count
; n
++)
1566 if (m_zoomControl
->GetString(n
).BeforeFirst(wxT('%')).ToLong(&val
) &&
1567 (val
>= long(zoom
)))
1569 m_zoomControl
->SetSelection(n
);
1574 m_zoomControl
->SetSelection(count
-1);
1578 int wxPreviewControlBar::GetZoomControl()
1580 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxEmptyString
))
1583 if (m_zoomControl
->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val
))
1595 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
1597 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
1598 EVT_CHAR_HOOK(wxPreviewFrame::OnChar
)
1599 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
1602 void wxPreviewFrame::OnChar(wxKeyEvent
&event
)
1604 if ( event
.GetKeyCode() == WXK_ESCAPE
)
1614 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxWindow
*parent
, const wxString
& title
,
1615 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
1616 wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
, name
)
1618 m_printPreview
= preview
;
1619 m_controlBar
= NULL
;
1620 m_previewCanvas
= NULL
;
1621 m_windowDisabler
= NULL
;
1622 m_modalityKind
= wxPreviewFrame_NonModal
;
1624 // Give the application icon
1626 wxFrame
* topFrame
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
1628 SetIcons(topFrame
->GetIcons());
1632 wxPreviewFrame::~wxPreviewFrame()
1634 wxPrintout
*printout
= m_printPreview
->GetPrintout();
1638 m_printPreview
->SetPrintout(NULL
);
1639 m_printPreview
->SetCanvas(NULL
);
1640 m_printPreview
->SetFrame(NULL
);
1643 m_previewCanvas
->SetPreview(NULL
);
1644 delete m_printPreview
;
1647 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
1649 // Reenable any windows we disabled by undoing whatever we did in our
1651 switch ( m_modalityKind
)
1653 case wxPreviewFrame_AppModal
:
1654 delete m_windowDisabler
;
1655 m_windowDisabler
= NULL
;
1658 case wxPreviewFrame_WindowModal
:
1660 GetParent()->Enable();
1663 case wxPreviewFrame_NonModal
:
1670 void wxPreviewFrame::Initialize(wxPreviewFrameModalityKind kind
)
1678 m_printPreview
->SetCanvas(m_previewCanvas
);
1679 m_printPreview
->SetFrame(this);
1681 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
1683 item0
->Add( m_controlBar
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1684 item0
->Add( m_previewCanvas
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1686 SetAutoLayout( true );
1689 m_modalityKind
= kind
;
1690 switch ( m_modalityKind
)
1692 case wxPreviewFrame_AppModal
:
1693 // Disable everything.
1694 m_windowDisabler
= new wxWindowDisabler( this );
1697 case wxPreviewFrame_WindowModal
:
1698 // Disable our parent if we have one.
1700 GetParent()->Disable();
1703 case wxPreviewFrame_NonModal
:
1704 // Nothing to do, we don't need to disable any windows.
1711 m_printPreview
->AdjustScrollbars(m_previewCanvas
);
1712 m_previewCanvas
->SetFocus();
1713 m_controlBar
->SetFocus();
1716 void wxPreviewFrame::CreateCanvas()
1718 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
1721 void wxPreviewFrame::CreateControlBar()
1723 long buttons
= wxPREVIEW_DEFAULT
;
1724 if (m_printPreview
->GetPrintoutForPrinting())
1725 buttons
|= wxPREVIEW_PRINT
;
1727 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this);
1728 m_controlBar
->CreateButtons();
1735 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
1737 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1738 wxPrintout
*printoutForPrinting
,
1742 m_printDialogData
= (*data
);
1744 Init(printout
, printoutForPrinting
);
1747 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1748 wxPrintout
*printoutForPrinting
,
1749 wxPrintDialogData
*data
)
1752 m_printDialogData
= (*data
);
1754 Init(printout
, printoutForPrinting
);
1757 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
1758 wxPrintout
*printoutForPrinting
)
1761 m_previewPrintout
= printout
;
1762 if (m_previewPrintout
)
1763 m_previewPrintout
->SetPreview(static_cast<wxPrintPreview
*>(this));
1765 m_printPrintout
= printoutForPrinting
;
1767 m_previewCanvas
= NULL
;
1768 m_previewFrame
= NULL
;
1769 m_previewBitmap
= NULL
;
1770 m_previewFailed
= false;
1774 m_leftMargin
= 2*wxSizerFlags::GetDefaultBorder();
1777 m_printingPrepared
= false;
1782 wxPrintPreviewBase::~wxPrintPreviewBase()
1784 if (m_previewPrintout
)
1785 delete m_previewPrintout
;
1786 if (m_previewBitmap
)
1787 delete m_previewBitmap
;
1788 if (m_printPrintout
)
1789 delete m_printPrintout
;
1792 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
1794 if (m_currentPage
== pageNum
)
1797 m_currentPage
= pageNum
;
1799 InvalidatePreviewBitmap();
1801 if (m_previewCanvas
)
1803 AdjustScrollbars(m_previewCanvas
);
1805 m_previewCanvas
->Refresh();
1806 m_previewCanvas
->SetFocus();
1811 int wxPrintPreviewBase::GetCurrentPage() const
1812 { return m_currentPage
; }
1813 void wxPrintPreviewBase::SetPrintout(wxPrintout
*printout
)
1814 { m_previewPrintout
= printout
; }
1815 wxPrintout
*wxPrintPreviewBase::GetPrintout() const
1816 { return m_previewPrintout
; }
1817 wxPrintout
*wxPrintPreviewBase::GetPrintoutForPrinting() const
1818 { return m_printPrintout
; }
1819 void wxPrintPreviewBase::SetFrame(wxFrame
*frame
)
1820 { m_previewFrame
= frame
; }
1821 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas
*canvas
)
1822 { m_previewCanvas
= canvas
; }
1823 wxFrame
*wxPrintPreviewBase::GetFrame() const
1824 { return m_previewFrame
; }
1825 wxPreviewCanvas
*wxPrintPreviewBase::GetCanvas() const
1826 { return m_previewCanvas
; }
1828 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas
*canvas
, wxRect
& pageRect
, wxRect
& paperRect
)
1830 // Calculate the rectangles for the printable area of the page and the
1831 // entire paper as they appear on the canvas on-screen.
1832 int canvasWidth
, canvasHeight
;
1833 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
1835 float zoomScale
= float(m_currentZoom
) / 100;
1836 float screenPrintableWidth
= zoomScale
* m_pageWidth
* m_previewScaleX
;
1837 float screenPrintableHeight
= zoomScale
* m_pageHeight
* m_previewScaleY
;
1839 wxRect devicePaperRect
= m_previewPrintout
->GetPaperRectPixels();
1840 wxCoord devicePrintableWidth
, devicePrintableHeight
;
1841 m_previewPrintout
->GetPageSizePixels(&devicePrintableWidth
, &devicePrintableHeight
);
1842 float scaleX
= screenPrintableWidth
/ devicePrintableWidth
;
1843 float scaleY
= screenPrintableHeight
/ devicePrintableHeight
;
1844 paperRect
.width
= wxCoord(scaleX
* devicePaperRect
.width
);
1845 paperRect
.height
= wxCoord(scaleY
* devicePaperRect
.height
);
1847 paperRect
.x
= wxCoord((canvasWidth
- paperRect
.width
)/ 2.0);
1848 if (paperRect
.x
< m_leftMargin
)
1849 paperRect
.x
= m_leftMargin
;
1850 paperRect
.y
= wxCoord((canvasHeight
- paperRect
.height
)/ 2.0);
1851 if (paperRect
.y
< m_topMargin
)
1852 paperRect
.y
= m_topMargin
;
1854 pageRect
.x
= paperRect
.x
- wxCoord(scaleX
* devicePaperRect
.x
);
1855 pageRect
.y
= paperRect
.y
- wxCoord(scaleY
* devicePaperRect
.y
);
1856 pageRect
.width
= wxCoord(screenPrintableWidth
);
1857 pageRect
.height
= wxCoord(screenPrintableHeight
);
1861 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1863 wxDELETE(m_previewBitmap
);
1864 // if there was a problem with rendering the preview, try again now
1865 // that it changed in some way (less memory may be needed, for example):
1866 m_previewFailed
= false;
1869 bool wxPrintPreviewBase::UpdatePageRendering()
1871 if ( m_previewBitmap
)
1874 if ( m_previewFailed
)
1877 if ( !RenderPage(m_currentPage
) )
1879 m_previewFailed
= true; // don't waste time failing again
1886 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1888 DrawBlankPage(canvas
, dc
);
1890 if (!m_previewBitmap
)
1895 wxRect pageRect
, paperRect
;
1896 CalcRects(canvas
, pageRect
, paperRect
);
1898 temp_dc
.SelectObject(*m_previewBitmap
);
1900 dc
.Blit(pageRect
.x
, pageRect
.y
,
1901 m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
1903 temp_dc
.SelectObject(wxNullBitmap
);
1907 // Adjusts the scrollbars for the current scale
1908 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas
*canvas
)
1913 wxRect pageRect
, paperRect
;
1914 CalcRects(canvas
, pageRect
, paperRect
);
1915 int totalWidth
= paperRect
.width
+ 2 * m_leftMargin
;
1916 int totalHeight
= paperRect
.height
+ 2 * m_topMargin
;
1917 int scrollUnitsX
= totalWidth
/ 10;
1918 int scrollUnitsY
= totalHeight
/ 10;
1919 wxSize virtualSize
= canvas
->GetVirtualSize();
1920 if (virtualSize
.GetWidth() != totalWidth
|| virtualSize
.GetHeight() != totalHeight
)
1921 canvas
->SetScrollbars(10, 10, scrollUnitsX
, scrollUnitsY
, 0, 0, true);
1924 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC
& dc
, int pageNum
)
1926 m_previewPrintout
->SetDC(&dc
);
1927 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
1929 // Need to delay OnPreparePrinting() until here, so we have enough
1930 // information and a wxDC.
1931 if (!m_printingPrepared
)
1933 m_printingPrepared
= true;
1935 m_previewPrintout
->OnPreparePrinting();
1937 m_previewPrintout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
1939 // Update the wxPreviewControlBar page range display.
1940 if ( m_previewFrame
)
1942 wxPreviewControlBar
* const
1943 controlBar
= ((wxPreviewFrame
*)m_previewFrame
)->GetControlBar();
1945 controlBar
->SetPageInfo(m_minPage
, m_maxPage
);
1949 m_previewPrintout
->OnBeginPrinting();
1951 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
1953 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
1957 m_previewPrintout
->OnPrintPage(pageNum
);
1958 m_previewPrintout
->OnEndDocument();
1959 m_previewPrintout
->OnEndPrinting();
1961 m_previewPrintout
->SetDC(NULL
);
1966 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap
& bmp
, int pageNum
)
1968 wxMemoryDC memoryDC
;
1969 memoryDC
.SelectObject(bmp
);
1972 return RenderPageIntoDC(memoryDC
, pageNum
);
1975 bool wxPrintPreviewBase::RenderPage(int pageNum
)
1979 if (!m_previewCanvas
)
1981 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1985 wxRect pageRect
, paperRect
;
1986 CalcRects(m_previewCanvas
, pageRect
, paperRect
);
1988 if (!m_previewBitmap
)
1990 m_previewBitmap
= new wxBitmap(pageRect
.width
, pageRect
.height
);
1992 if (!m_previewBitmap
|| !m_previewBitmap
->IsOk())
1994 InvalidatePreviewBitmap();
1995 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2000 if ( !RenderPageIntoBitmap(*m_previewBitmap
, pageNum
) )
2002 InvalidatePreviewBitmap();
2003 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2010 status
= wxString::Format(_("Page %d of %d"), pageNum
, m_maxPage
);
2012 status
= wxString::Format(_("Page %d"), pageNum
);
2015 m_previewFrame
->SetStatusText(status
);
2021 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2023 wxRect pageRect
, paperRect
;
2025 CalcRects(canvas
, pageRect
, paperRect
);
2027 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
2028 wxCoord shadowOffset
= 4;
2030 dc
.SetPen(*wxBLACK_PEN
);
2031 dc
.SetBrush(*wxBLACK_BRUSH
);
2032 dc
.DrawRectangle(paperRect
.x
+ shadowOffset
, paperRect
.y
+ paperRect
.height
+ 1,
2033 paperRect
.width
, shadowOffset
);
2035 dc
.DrawRectangle(paperRect
.x
+ paperRect
.width
, paperRect
.y
+ shadowOffset
,
2036 shadowOffset
, paperRect
.height
);
2038 // Draw blank page allowing for 1-pixel border AROUND the actual paper
2039 dc
.SetPen(*wxBLACK_PEN
);
2040 dc
.SetBrush(*wxWHITE_BRUSH
);
2041 dc
.DrawRectangle(paperRect
.x
- 2, paperRect
.y
- 1,
2042 paperRect
.width
+ 3, paperRect
.height
+ 2);
2047 void wxPrintPreviewBase::SetZoom(int percent
)
2049 if (m_currentZoom
== percent
)
2052 m_currentZoom
= percent
;
2054 InvalidatePreviewBitmap();
2056 if (m_previewCanvas
)
2058 AdjustScrollbars(m_previewCanvas
);
2059 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
2060 m_previewCanvas
->ClearBackground();
2061 m_previewCanvas
->Refresh();
2062 m_previewCanvas
->SetFocus();
2066 wxPrintDialogData
& wxPrintPreviewBase::GetPrintDialogData()
2068 return m_printDialogData
;
2071 int wxPrintPreviewBase::GetZoom() const
2072 { return m_currentZoom
; }
2073 int wxPrintPreviewBase::GetMaxPage() const
2074 { return m_maxPage
; }
2075 int wxPrintPreviewBase::GetMinPage() const
2076 { return m_minPage
; }
2077 bool wxPrintPreviewBase::IsOk() const
2079 void wxPrintPreviewBase::SetOk(bool ok
)
2082 //----------------------------------------------------------------------------
2084 //----------------------------------------------------------------------------
2086 IMPLEMENT_CLASS(wxPrintPreview
, wxPrintPreviewBase
)
2088 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2089 wxPrintout
*printoutForPrinting
,
2090 wxPrintDialogData
*data
) :
2091 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2093 m_pimpl
= wxPrintFactory::GetFactory()->
2094 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2097 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2098 wxPrintout
*printoutForPrinting
,
2099 wxPrintData
*data
) :
2100 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2102 m_pimpl
= wxPrintFactory::GetFactory()->
2103 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2106 wxPrintPreview::~wxPrintPreview()
2110 // don't delete twice
2111 m_printPrintout
= NULL
;
2112 m_previewPrintout
= NULL
;
2113 m_previewBitmap
= NULL
;
2116 bool wxPrintPreview::SetCurrentPage(int pageNum
)
2118 return m_pimpl
->SetCurrentPage( pageNum
);
2121 int wxPrintPreview::GetCurrentPage() const
2123 return m_pimpl
->GetCurrentPage();
2126 void wxPrintPreview::SetPrintout(wxPrintout
*printout
)
2128 m_pimpl
->SetPrintout( printout
);
2131 wxPrintout
*wxPrintPreview::GetPrintout() const
2133 return m_pimpl
->GetPrintout();
2136 wxPrintout
*wxPrintPreview::GetPrintoutForPrinting() const
2138 return m_pimpl
->GetPrintoutForPrinting();
2141 void wxPrintPreview::SetFrame(wxFrame
*frame
)
2143 m_pimpl
->SetFrame( frame
);
2146 void wxPrintPreview::SetCanvas(wxPreviewCanvas
*canvas
)
2148 m_pimpl
->SetCanvas( canvas
);
2151 wxFrame
*wxPrintPreview::GetFrame() const
2153 return m_pimpl
->GetFrame();
2156 wxPreviewCanvas
*wxPrintPreview::GetCanvas() const
2158 return m_pimpl
->GetCanvas();
2161 bool wxPrintPreview::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2163 return m_pimpl
->PaintPage( canvas
, dc
);
2166 bool wxPrintPreview::UpdatePageRendering()
2168 return m_pimpl
->UpdatePageRendering();
2171 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2173 return m_pimpl
->DrawBlankPage( canvas
, dc
);
2176 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas
*canvas
)
2178 m_pimpl
->AdjustScrollbars( canvas
);
2181 bool wxPrintPreview::RenderPage(int pageNum
)
2183 return m_pimpl
->RenderPage( pageNum
);
2186 void wxPrintPreview::SetZoom(int percent
)
2188 m_pimpl
->SetZoom( percent
);
2191 int wxPrintPreview::GetZoom() const
2193 return m_pimpl
->GetZoom();
2196 wxPrintDialogData
& wxPrintPreview::GetPrintDialogData()
2198 return m_pimpl
->GetPrintDialogData();
2201 int wxPrintPreview::GetMaxPage() const
2203 return m_pimpl
->GetMaxPage();
2206 int wxPrintPreview::GetMinPage() const
2208 return m_pimpl
->GetMinPage();
2211 bool wxPrintPreview::IsOk() const
2213 return m_pimpl
->IsOk();
2216 void wxPrintPreview::SetOk(bool ok
)
2218 m_pimpl
->SetOk( ok
);
2221 bool wxPrintPreview::Print(bool interactive
)
2223 return m_pimpl
->Print( interactive
);
2226 void wxPrintPreview::DetermineScaling()
2228 m_pimpl
->DetermineScaling();
2231 #endif // wxUSE_PRINTING_ARCHITECTURE