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/settings.h"
36 #include "wx/dcmemory.h"
37 #include "wx/dcclient.h"
38 #include "wx/stattext.h"
40 #include "wx/textdlg.h"
42 #include "wx/module.h"
45 #include "wx/prntbase.h"
46 #include "wx/printdlg.h"
48 #include "wx/dcprint.h"
49 #include "wx/artprov.h"
54 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
55 #include "wx/msw/printdlg.h"
56 #include "wx/msw/dcprint.h"
57 #elif defined(__WXMAC__)
58 #include "wx/osx/printdlg.h"
59 #include "wx/osx/private/print.h"
60 #include "wx/osx/dcprint.h"
61 #elif defined(__WXPM__)
62 #include "wx/os2/dcprint.h"
63 #include "wx/generic/prntdlgg.h"
65 #include "wx/generic/prntdlgg.h"
75 //----------------------------------------------------------------------------
77 //----------------------------------------------------------------------------
79 wxPrintFactory
*wxPrintFactory::m_factory
= NULL
;
81 void wxPrintFactory::SetPrintFactory( wxPrintFactory
*factory
)
83 if (wxPrintFactory::m_factory
)
84 delete wxPrintFactory::m_factory
;
86 wxPrintFactory::m_factory
= factory
;
89 wxPrintFactory
*wxPrintFactory::GetFactory()
91 if (!wxPrintFactory::m_factory
)
92 wxPrintFactory::m_factory
= new wxNativePrintFactory
;
94 return wxPrintFactory::m_factory
;
97 //----------------------------------------------------------------------------
98 // wxNativePrintFactory
99 //----------------------------------------------------------------------------
101 wxPrinterBase
*wxNativePrintFactory::CreatePrinter( wxPrintDialogData
*data
)
103 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
104 return new wxWindowsPrinter( data
);
105 #elif defined(__WXMAC__)
106 return new wxMacPrinter( data
);
107 #elif defined(__WXPM__)
108 return new wxOS2Printer( data
);
110 return new wxPostScriptPrinter( data
);
114 wxPrintPreviewBase
*wxNativePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
115 wxPrintout
*printout
, wxPrintDialogData
*data
)
117 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
118 return new wxWindowsPrintPreview( preview
, printout
, data
);
119 #elif defined(__WXMAC__)
120 return new wxMacPrintPreview( preview
, printout
, data
);
121 #elif defined(__WXPM__)
122 return new wxOS2PrintPreview( preview
, printout
, data
);
124 return new wxPostScriptPrintPreview( preview
, printout
, data
);
128 wxPrintPreviewBase
*wxNativePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
129 wxPrintout
*printout
, wxPrintData
*data
)
131 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
132 return new wxWindowsPrintPreview( preview
, printout
, data
);
133 #elif defined(__WXMAC__)
134 return new wxMacPrintPreview( preview
, printout
, data
);
135 #elif defined(__WXPM__)
136 return new wxOS2PrintPreview( preview
, printout
, data
);
138 return new wxPostScriptPrintPreview( preview
, printout
, data
);
142 wxPrintDialogBase
*wxNativePrintFactory::CreatePrintDialog( wxWindow
*parent
,
143 wxPrintDialogData
*data
)
145 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
146 return new wxWindowsPrintDialog( parent
, data
);
147 #elif defined(__WXMAC__)
148 return new wxMacPrintDialog( parent
, data
);
150 return new wxGenericPrintDialog( parent
, data
);
154 wxPrintDialogBase
*wxNativePrintFactory::CreatePrintDialog( wxWindow
*parent
,
157 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
158 return new wxWindowsPrintDialog( parent
, data
);
159 #elif defined(__WXMAC__)
160 return new wxMacPrintDialog( parent
, data
);
162 return new wxGenericPrintDialog( parent
, data
);
166 wxPageSetupDialogBase
*wxNativePrintFactory::CreatePageSetupDialog( wxWindow
*parent
,
167 wxPageSetupDialogData
*data
)
169 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
170 return new wxWindowsPageSetupDialog( parent
, data
);
171 #elif defined(__WXMAC__)
172 return new wxMacPageSetupDialog( parent
, data
);
174 return new wxGenericPageSetupDialog( parent
, data
);
178 bool wxNativePrintFactory::HasPrintSetupDialog()
180 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
182 #elif defined(__WXMAC__)
185 // Only here do we need to provide the print setup
186 // dialog ourselves, the other platforms either have
187 // none, don't make it accessible or let you configure
188 // the printer from the wxPrintDialog anyway.
194 wxDialog
*wxNativePrintFactory::CreatePrintSetupDialog( wxWindow
*parent
,
197 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
201 #elif defined(__WXMAC__)
206 // Only here do we need to provide the print setup
207 // dialog ourselves, the other platforms either have
208 // none, don't make it accessible or let you configure
209 // the printer from the wxPrintDialog anyway.
210 return new wxGenericPrintSetupDialog( parent
, data
);
214 wxDCImpl
* wxNativePrintFactory::CreatePrinterDCImpl( wxPrinterDC
*owner
, const wxPrintData
& data
)
216 #if defined(__WXGTK__) || defined(__WXMOTIF__) || ( defined(__WXUNIVERSAL__) && !defined(__WXMAC__) )
217 return new wxPostScriptDCImpl( owner
, data
);
219 return new wxPrinterDCImpl( owner
, data
);
223 bool wxNativePrintFactory::HasOwnPrintToFile()
225 // Only relevant for PostScript and here the
226 // setup dialog provides no "print to file"
227 // option. In the GNOME setup dialog, the
228 // setup dialog has its own print to file.
232 bool wxNativePrintFactory::HasPrinterLine()
234 // Only relevant for PostScript for now
238 wxString
wxNativePrintFactory::CreatePrinterLine()
240 // Only relevant for PostScript for now
242 // We should query "lpstat -d" here
243 return _("Generic PostScript");
246 bool wxNativePrintFactory::HasStatusLine()
248 // Only relevant for PostScript for now
252 wxString
wxNativePrintFactory::CreateStatusLine()
254 // Only relevant for PostScript for now
256 // We should query "lpstat -r" or "lpstat -p" here
260 wxPrintNativeDataBase
*wxNativePrintFactory::CreatePrintNativeData()
262 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
263 return new wxWindowsPrintNativeData
;
264 #elif defined(__WXMAC__)
265 return wxOSXCreatePrintData();
267 return new wxPostScriptPrintNativeData
;
271 //----------------------------------------------------------------------------
272 // wxPrintNativeDataBase
273 //----------------------------------------------------------------------------
275 IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase
, wxObject
)
277 wxPrintNativeDataBase::wxPrintNativeDataBase()
282 //----------------------------------------------------------------------------
283 // wxPrintFactoryModule
284 //----------------------------------------------------------------------------
286 class wxPrintFactoryModule
: public wxModule
289 wxPrintFactoryModule() {}
290 bool OnInit() { return true; }
291 void OnExit() { wxPrintFactory::SetPrintFactory( NULL
); }
294 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule
)
297 IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule
, wxModule
)
299 //----------------------------------------------------------------------------
301 //----------------------------------------------------------------------------
303 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
305 wxPrinterBase::wxPrinterBase(wxPrintDialogData
*data
)
307 m_currentPrintout
= NULL
;
308 sm_abortWindow
= NULL
;
311 m_printDialogData
= (*data
);
312 sm_lastError
= wxPRINTER_NO_ERROR
;
315 wxWindow
*wxPrinterBase::sm_abortWindow
= NULL
;
316 bool wxPrinterBase::sm_abortIt
= false;
317 wxPrinterError
wxPrinterBase::sm_lastError
= wxPRINTER_NO_ERROR
;
319 wxPrinterBase::~wxPrinterBase()
323 wxWindow
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
* printout
)
325 wxPrintAbortDialog
*dialog
= new wxPrintAbortDialog(parent
, _("Printing ") , wxDefaultPosition
, wxDefaultSize
, wxDEFAULT_DIALOG_STYLE
);
327 wxBoxSizer
*button_sizer
= new wxBoxSizer( wxVERTICAL
);
328 button_sizer
->Add( new wxStaticText(dialog
, wxID_ANY
, _("Please wait while printing\n") + printout
->GetTitle() ), 0, wxALL
, 10 );
329 button_sizer
->Add( new wxButton( dialog
, wxID_CANCEL
, wxT("Cancel") ), 0, wxALL
| wxALIGN_CENTER
, 10 );
331 dialog
->SetAutoLayout( true );
332 dialog
->SetSizer( button_sizer
);
334 button_sizer
->Fit(dialog
);
335 button_sizer
->SetSizeHints (dialog
) ;
340 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), const wxString
& message
)
342 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
345 wxPrintDialogData
& wxPrinterBase::GetPrintDialogData() const
347 return (wxPrintDialogData
&) m_printDialogData
;
350 //----------------------------------------------------------------------------
352 //----------------------------------------------------------------------------
354 IMPLEMENT_CLASS(wxPrinter
, wxPrinterBase
)
356 wxPrinter::wxPrinter(wxPrintDialogData
*data
)
358 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrinter( data
);
361 wxPrinter::~wxPrinter()
366 wxWindow
*wxPrinter::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*printout
)
368 return m_pimpl
->CreateAbortWindow( parent
, printout
);
371 void wxPrinter::ReportError(wxWindow
*parent
, wxPrintout
*printout
, const wxString
& message
)
373 m_pimpl
->ReportError( parent
, printout
, message
);
376 bool wxPrinter::Setup(wxWindow
*parent
)
378 return m_pimpl
->Setup( parent
);
381 bool wxPrinter::Print(wxWindow
*parent
, wxPrintout
*printout
, bool prompt
)
383 return m_pimpl
->Print( parent
, printout
, prompt
);
386 wxDC
* wxPrinter::PrintDialog(wxWindow
*parent
)
388 return m_pimpl
->PrintDialog( parent
);
391 wxPrintDialogData
& wxPrinter::GetPrintDialogData() const
393 return m_pimpl
->GetPrintDialogData();
396 // ---------------------------------------------------------------------------
397 // wxPrintDialogBase: the dialog for printing.
398 // ---------------------------------------------------------------------------
400 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase
, wxDialog
)
402 wxPrintDialogBase::wxPrintDialogBase(wxWindow
*parent
,
404 const wxString
&title
,
408 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Print")) : title
,
413 // ---------------------------------------------------------------------------
414 // wxPrintDialog: the dialog for printing
415 // ---------------------------------------------------------------------------
417 IMPLEMENT_CLASS(wxPrintDialog
, wxObject
)
419 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintDialogData
* data
)
421 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
424 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintData
* data
)
426 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
429 wxPrintDialog::~wxPrintDialog()
434 int wxPrintDialog::ShowModal()
436 return m_pimpl
->ShowModal();
439 wxPrintDialogData
& wxPrintDialog::GetPrintDialogData()
441 return m_pimpl
->GetPrintDialogData();
444 wxPrintData
& wxPrintDialog::GetPrintData()
446 return m_pimpl
->GetPrintData();
449 wxDC
*wxPrintDialog::GetPrintDC()
451 return m_pimpl
->GetPrintDC();
454 // ---------------------------------------------------------------------------
455 // wxPageSetupDialogBase: the page setup dialog
456 // ---------------------------------------------------------------------------
458 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase
, wxDialog
)
460 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow
*parent
,
462 const wxString
&title
,
466 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Page setup")) : title
,
471 // ---------------------------------------------------------------------------
472 // wxPageSetupDialog: the page setup dialog
473 // ---------------------------------------------------------------------------
475 IMPLEMENT_CLASS(wxPageSetupDialog
, wxObject
)
477 wxPageSetupDialog::wxPageSetupDialog(wxWindow
*parent
, wxPageSetupDialogData
*data
)
479 m_pimpl
= wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent
, data
);
482 wxPageSetupDialog::~wxPageSetupDialog()
487 int wxPageSetupDialog::ShowModal()
489 return m_pimpl
->ShowModal();
492 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupDialogData()
494 return m_pimpl
->GetPageSetupDialogData();
498 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupData()
500 return m_pimpl
->GetPageSetupDialogData();
503 //----------------------------------------------------------------------------
504 // wxPrintAbortDialog
505 //----------------------------------------------------------------------------
507 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
508 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
511 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
513 wxPrinterBase::sm_abortIt
= true;
514 wxPrinterBase::sm_abortWindow
->Show(false);
515 wxPrinterBase::sm_abortWindow
->Close(true);
516 wxPrinterBase::sm_abortWindow
->Destroy();
517 wxPrinterBase::sm_abortWindow
= NULL
;
520 //----------------------------------------------------------------------------
522 //----------------------------------------------------------------------------
524 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
526 wxPrintout::wxPrintout(const wxString
& title
)
528 m_printoutTitle
= title
;
532 m_pageWidthPixels
= 0;
533 m_pageHeightPixels
= 0;
541 wxPrintout::~wxPrintout()
545 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
547 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle
);
550 void wxPrintout::OnEndDocument()
555 void wxPrintout::OnBeginPrinting()
559 void wxPrintout::OnEndPrinting()
563 bool wxPrintout::HasPage(int page
)
568 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
576 void wxPrintout::FitThisSizeToPaper(const wxSize
& imageSize
)
578 // Set the DC scale and origin so that the given image size fits within the
579 // entire page and the origin is at the top left corner of the page. Note
580 // that with most printers, portions of the page will be non-printable. Use
581 // this if you're managing your own page margins.
582 if (!m_printoutDC
) return;
583 wxRect paperRect
= GetPaperRectPixels();
585 GetPageSizePixels(&pw
, &ph
);
587 m_printoutDC
->GetSize(&w
, &h
);
588 float scaleX
= ((float(paperRect
.width
) * w
) / (float(pw
) * imageSize
.x
));
589 float scaleY
= ((float(paperRect
.height
) * h
) / (float(ph
) * imageSize
.y
));
590 float actualScale
= wxMin(scaleX
, scaleY
);
591 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
592 m_printoutDC
->SetDeviceOrigin(0, 0);
593 wxRect logicalPaperRect
= GetLogicalPaperRect();
594 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
597 void wxPrintout::FitThisSizeToPage(const wxSize
& imageSize
)
599 // Set the DC scale and origin so that the given image size fits within the
600 // printable area of the page and the origin is at the top left corner of
601 // the printable area.
602 if (!m_printoutDC
) return;
604 m_printoutDC
->GetSize(&w
, &h
);
605 float scaleX
= float(w
) / imageSize
.x
;
606 float scaleY
= float(h
) / imageSize
.y
;
607 float actualScale
= wxMin(scaleX
, scaleY
);
608 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
609 m_printoutDC
->SetDeviceOrigin(0, 0);
612 void wxPrintout::FitThisSizeToPageMargins(const wxSize
& imageSize
, const wxPageSetupDialogData
& pageSetupData
)
614 // Set the DC scale and origin so that the given image size fits within the
615 // page margins defined in the given wxPageSetupDialogData object and the
616 // origin is at the top left corner of the page margins.
617 if (!m_printoutDC
) return;
618 wxRect paperRect
= GetPaperRectPixels();
620 GetPageSizePixels(&pw
, &ph
);
621 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
622 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
624 GetPageSizeMM(&mw
, &mh
);
625 float mmToDeviceX
= float(pw
) / mw
;
626 float mmToDeviceY
= float(ph
) / mh
;
627 wxRect
pageMarginsRect(paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
628 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
629 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
630 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
632 m_printoutDC
->GetSize(&w
, &h
);
633 float scaleX
= (float(pageMarginsRect
.width
) * w
) / (float(pw
) * imageSize
.x
);
634 float scaleY
= (float(pageMarginsRect
.height
) * h
) / (float(ph
) * imageSize
.y
);
635 float actualScale
= wxMin(scaleX
, scaleY
);
636 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
637 m_printoutDC
->SetDeviceOrigin(0, 0);
638 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
639 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
642 void wxPrintout::MapScreenSizeToPaper()
644 // Set the DC scale so that an image on the screen is the same size on the
645 // paper and the origin is at the top left of the paper. Note that with most
646 // printers, portions of the page will be cut off. Use this if you're
647 // managing your own page margins.
648 if (!m_printoutDC
) return;
649 MapScreenSizeToPage();
650 wxRect logicalPaperRect
= GetLogicalPaperRect();
651 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
654 void wxPrintout::MapScreenSizeToPage()
656 // Set the DC scale and origin so that an image on the screen is the same
657 // size on the paper and the origin is at the top left of the printable area.
658 if (!m_printoutDC
) return;
659 int ppiScreenX
, ppiScreenY
;
660 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
661 int ppiPrinterX
, ppiPrinterY
;
662 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
664 m_printoutDC
->GetSize(&w
, &h
);
665 int pageSizePixelsX
, pageSizePixelsY
;
666 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
667 float userScaleX
= (float(ppiPrinterX
) * w
) / (float(ppiScreenX
) * pageSizePixelsX
);
668 float userScaleY
= (float(ppiPrinterY
) * h
) / (float(ppiScreenY
) * pageSizePixelsY
);
669 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
670 m_printoutDC
->SetDeviceOrigin(0, 0);
673 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData
& pageSetupData
)
675 // Set the DC scale so that an image on the screen is the same size on the
676 // paper and the origin is at the top left of the page margins defined by
677 // the given wxPageSetupDialogData object.
678 if (!m_printoutDC
) return;
679 MapScreenSizeToPage();
680 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
681 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
684 void wxPrintout::MapScreenSizeToDevice()
686 // Set the DC scale so that a screen pixel is the same size as a device
687 // pixel and the origin is at the top left of the printable area.
688 if (!m_printoutDC
) return;
690 m_printoutDC
->GetSize(&w
, &h
);
691 int pageSizePixelsX
, pageSizePixelsY
;
692 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
693 float userScaleX
= float(w
) / pageSizePixelsX
;
694 float userScaleY
= float(h
) / pageSizePixelsY
;
695 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
696 m_printoutDC
->SetDeviceOrigin(0, 0);
699 wxRect
wxPrintout::GetLogicalPaperRect() const
701 // Return the rectangle in logical units that corresponds to the paper
703 wxRect paperRect
= GetPaperRectPixels();
705 GetPageSizePixels(&pw
, &ph
);
707 m_printoutDC
->GetSize(&w
, &h
);
708 if (w
== pw
&& h
== ph
) {
709 // this DC matches the printed page, so no scaling
710 return wxRect(m_printoutDC
->DeviceToLogicalX(paperRect
.x
),
711 m_printoutDC
->DeviceToLogicalY(paperRect
.y
),
712 m_printoutDC
->DeviceToLogicalXRel(paperRect
.width
),
713 m_printoutDC
->DeviceToLogicalYRel(paperRect
.height
));
715 // This DC doesn't match the printed page, so we have to scale.
716 float scaleX
= float(w
) / pw
;
717 float scaleY
= float(h
) / ph
;
718 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(paperRect
.x
* scaleX
)),
719 m_printoutDC
->DeviceToLogicalY(wxRound(paperRect
.y
* scaleY
)),
720 m_printoutDC
->DeviceToLogicalXRel(wxRound(paperRect
.width
* scaleX
)),
721 m_printoutDC
->DeviceToLogicalYRel(wxRound(paperRect
.height
* scaleY
)));
724 wxRect
wxPrintout::GetLogicalPageRect() const
726 // Return the rectangle in logical units that corresponds to the printable
729 m_printoutDC
->GetSize(&w
, &h
);
730 return wxRect(m_printoutDC
->DeviceToLogicalX(0),
731 m_printoutDC
->DeviceToLogicalY(0),
732 m_printoutDC
->DeviceToLogicalXRel(w
),
733 m_printoutDC
->DeviceToLogicalYRel(h
));
736 wxRect
wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData
& pageSetupData
) const
738 // Return the rectangle in logical units that corresponds to the region
739 // within the page margins as specified by the given wxPageSetupDialogData
742 // We get the paper size in device units and the margins in mm,
743 // so we need to calculate the conversion with this trick
745 GetPageSizePixels(&pw
, &ph
);
747 GetPageSizeMM(&mw
, &mh
);
748 float mmToDeviceX
= float(pw
) / mw
;
749 float mmToDeviceY
= float(ph
) / mh
;
751 // paper size in device units
752 wxRect paperRect
= GetPaperRectPixels();
755 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
756 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
758 // calculate margins in device units
759 wxRect
pageMarginsRect(
760 paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
761 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
762 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
763 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
766 m_printoutDC
->GetSize(&w
, &h
);
767 if (w
== pw
&& h
== ph
)
769 // this DC matches the printed page, so no scaling
771 m_printoutDC
->DeviceToLogicalX(pageMarginsRect
.x
),
772 m_printoutDC
->DeviceToLogicalY(pageMarginsRect
.y
),
773 m_printoutDC
->DeviceToLogicalXRel(pageMarginsRect
.width
),
774 m_printoutDC
->DeviceToLogicalYRel(pageMarginsRect
.height
));
777 // This DC doesn't match the printed page, so we have to scale.
778 float scaleX
= float(w
) / pw
;
779 float scaleY
= float(h
) / ph
;
780 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(pageMarginsRect
.x
* scaleX
)),
781 m_printoutDC
->DeviceToLogicalY(wxRound(pageMarginsRect
.y
* scaleY
)),
782 m_printoutDC
->DeviceToLogicalXRel(wxRound(pageMarginsRect
.width
* scaleX
)),
783 m_printoutDC
->DeviceToLogicalYRel(wxRound(pageMarginsRect
.height
* scaleY
)));
786 void wxPrintout::SetLogicalOrigin(wxCoord x
, wxCoord y
)
788 // Set the device origin by specifying a point in logical coordinates.
789 m_printoutDC
->SetDeviceOrigin(
790 m_printoutDC
->LogicalToDeviceX(x
),
791 m_printoutDC
->LogicalToDeviceY(y
) );
794 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff
, wxCoord yoff
)
796 // Offset the device origin by a specified distance in device coordinates.
797 wxPoint dev_org
= m_printoutDC
->GetDeviceOrigin();
798 m_printoutDC
->SetDeviceOrigin(
799 dev_org
.x
+ m_printoutDC
->LogicalToDeviceXRel(xoff
),
800 dev_org
.y
+ m_printoutDC
->LogicalToDeviceYRel(yoff
) );
804 //----------------------------------------------------------------------------
806 //----------------------------------------------------------------------------
808 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
810 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
811 EVT_PAINT(wxPreviewCanvas::OnPaint
)
812 EVT_CHAR(wxPreviewCanvas::OnChar
)
813 EVT_IDLE(wxPreviewCanvas::OnIdle
)
814 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
816 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel
)
820 // VZ: the current code doesn't refresh properly without
821 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
822 // really horrible flicker when resizing the preview frame, but without
823 // this style it simply doesn't work correctly at all...
824 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
825 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
826 wxScrolledWindow(parent
, wxID_ANY
, pos
, size
, style
| wxFULL_REPAINT_ON_RESIZE
, name
)
828 m_printPreview
= preview
;
830 // The app workspace colour is always white, but we should have
831 // a contrast with the page.
832 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
833 #elif defined(__WXGTK__)
834 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
836 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
838 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
840 SetScrollbars(10, 10, 100, 100);
843 wxPreviewCanvas::~wxPreviewCanvas()
847 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
854 if (!GetUpdateRegion().IsEmpty())
855 dc.SetClippingRegion( GetUpdateRegion() );
861 m_printPreview
->PaintPage(this, dc
);
865 void wxPreviewCanvas::OnIdle(wxIdleEvent
& event
)
869 // prevent UpdatePageRendering() from being called recursively:
870 static bool s_inIdle
= false;
875 if ( m_printPreview
)
877 if ( m_printPreview
->UpdatePageRendering() )
884 // Responds to colour changes, and passes event on to children.
885 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
888 // The app workspace colour is always white, but we should have
889 // a contrast with the page.
890 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
891 #elif defined(__WXGTK__)
892 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
894 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
896 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
899 // Propagate the event to the non-top-level children
900 wxWindow::OnSysColourChanged(event
);
903 void wxPreviewCanvas::OnChar(wxKeyEvent
&event
)
905 wxPreviewControlBar
* controlBar
= ((wxPreviewFrame
*) GetParent())->GetControlBar();
906 switch (event
.GetKeyCode())
909 controlBar
->OnPrint();
914 controlBar
->DoZoomIn();
917 case WXK_NUMPAD_SUBTRACT
:
919 controlBar
->DoZoomOut();
923 if (!event
.ControlDown())
929 switch(event
.GetKeyCode())
932 controlBar
->OnNext(); break;
934 controlBar
->OnPrevious(); break;
936 controlBar
->OnFirst(); break;
938 controlBar
->OnLast(); break;
946 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent
& event
)
948 wxPreviewControlBar
*
949 controlBar
= wxStaticCast(GetParent(), wxPreviewFrame
)->GetControlBar();
953 if ( event
.ControlDown() && event
.GetWheelRotation() != 0 )
955 int currentZoom
= controlBar
->GetZoomControl();
958 if ( currentZoom
< 100 )
960 else if ( currentZoom
<= 120 )
965 if ( event
.GetWheelRotation() > 0 )
968 int newZoom
= currentZoom
+ delta
;
973 if ( newZoom
!= currentZoom
)
975 controlBar
->SetZoomControl(newZoom
);
976 m_printPreview
->SetZoom(newZoom
);
986 #endif // wxUSE_MOUSEWHEEL
988 // ----------------------------------------------------------------------------
989 // wxPrintPageTextCtrl
990 // ----------------------------------------------------------------------------
992 // This text control contains the page number in the interval specified during
993 // its construction. Invalid pages are not accepted and the control contents is
994 // validated when it loses focus. Conversely, if the user changes the page to
995 // another valid one or presses Enter, OnGotoPage() method of the preview object
997 class wxPrintPageTextCtrl
: public wxTextCtrl
1000 wxPrintPageTextCtrl(wxPreviewControlBar
*preview
, int minPage
, int maxPage
)
1001 : wxTextCtrl(preview
,
1003 PageAsString(minPage
),
1005 // We use hardcoded 99999 for the width instead of fitting
1006 // it to the values we can show because the control looks
1007 // uncomfortably narrow if the real page number is just
1008 // one or two digits.
1009 wxSize(preview
->GetTextExtent("99999").x
, wxDefaultCoord
),
1011 #if wxUSE_VALIDATORS
1012 , wxTextValidator(wxFILTER_DIGITS
)
1013 #endif // wxUSE_VALIDATORS
1021 Connect(wxEVT_KILL_FOCUS
,
1022 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus
));
1023 Connect(wxEVT_COMMAND_TEXT_ENTER
,
1024 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter
));
1027 // Helpers to conveniently set or get the current page number. Return value
1028 // is 0 if the current controls contents is invalid.
1029 void SetPageNumber(int page
)
1031 wxASSERT( IsValidPage(page
) );
1033 SetValue(PageAsString(page
));
1036 int GetPageNumber() const
1039 if ( !GetValue().ToLong(&value
) || !IsValidPage(value
) )
1042 // Cast is safe because the value is less than (int) m_maxPage.
1043 return static_cast<int>(value
);
1047 static wxString
PageAsString(int page
)
1049 return wxString::Format("%d", page
);
1052 bool IsValidPage(int page
) const
1054 return page
>= m_minPage
&& page
<= m_maxPage
;
1059 const int page
= GetPageNumber();
1064 if ( page
!= m_page
)
1066 // We have a valid page, remember it.
1069 // And notify the owner about the change.
1070 m_preview
->OnGotoPage();
1072 //else: Nothing really changed.
1077 void OnKillFocus(wxFocusEvent
& event
)
1079 if ( !DoChangePage() )
1081 // The current contents is invalid so reset it back to the last
1082 // known good page index.
1083 SetPageNumber(m_page
);
1089 void OnTextEnter(wxCommandEvent
& WXUNUSED(event
))
1095 wxPreviewControlBar
* const m_preview
;
1097 const int m_minPage
,
1100 // This is the last valid page value that we had, we revert to it if an
1101 // invalid page is entered.
1104 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl
);
1107 //----------------------------------------------------------------------------
1108 // wxPreviewControlBar
1109 //----------------------------------------------------------------------------
1111 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
1113 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
1114 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
1115 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrintButton
)
1116 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
1117 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
1118 EVT_BUTTON(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnFirstButton
)
1119 EVT_BUTTON(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnLastButton
)
1120 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnZoomInButton
)
1121 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnZoomOutButton
)
1123 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnUpdatePreviousButton
)
1124 EVT_UPDATE_UI(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnUpdateNextButton
)
1125 EVT_UPDATE_UI(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnUpdateFirstButton
)
1126 EVT_UPDATE_UI(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnUpdateLastButton
)
1127 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnUpdateZoomInButton
)
1128 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnUpdateZoomOutButton
)
1130 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoomChoice
)
1131 EVT_PAINT(wxPreviewControlBar::OnPaint
)
1135 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
1136 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
1137 long style
, const wxString
& name
):
1138 wxPanel(parent
, wxID_ANY
, pos
, size
, style
, name
)
1140 m_printPreview
= preview
;
1141 m_closeButton
= NULL
;
1142 m_zoomControl
= NULL
;
1143 m_currentPageText
= NULL
;
1144 m_buttonFlags
= buttons
;
1147 wxPreviewControlBar::~wxPreviewControlBar()
1151 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1157 dc
.SetPen(*wxBLACK_PEN
);
1158 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1159 dc
.DrawLine( 0, h
-1, w
, h
-1 );
1162 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
1164 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
1168 void wxPreviewControlBar::OnPrint(void)
1170 wxPrintPreviewBase
*preview
= GetPrintPreview();
1171 preview
->Print(true);
1174 void wxPreviewControlBar::OnNext()
1176 if ( IsNextEnabled() )
1177 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1180 void wxPreviewControlBar::OnPrevious()
1182 if ( IsPreviousEnabled() )
1183 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1186 void wxPreviewControlBar::OnFirst()
1188 if ( IsFirstEnabled() )
1189 DoGotoPage(GetPrintPreview()->GetMinPage());
1192 void wxPreviewControlBar::OnLast()
1194 if ( IsLastEnabled() )
1195 DoGotoPage(GetPrintPreview()->GetMaxPage());
1198 bool wxPreviewControlBar::IsNextEnabled() const
1200 wxPrintPreviewBase
*preview
= GetPrintPreview();
1204 const int currentPage
= preview
->GetCurrentPage();
1205 return currentPage
< preview
->GetMaxPage() &&
1206 preview
->GetPrintout()->HasPage(currentPage
+ 1);
1209 bool wxPreviewControlBar::IsPreviousEnabled() const
1211 wxPrintPreviewBase
*preview
= GetPrintPreview();
1215 const int currentPage
= preview
->GetCurrentPage();
1216 return currentPage
> preview
->GetMinPage() &&
1217 preview
->GetPrintout()->HasPage(currentPage
- 1);
1220 bool wxPreviewControlBar::IsFirstEnabled() const
1222 wxPrintPreviewBase
*preview
= GetPrintPreview();
1226 return preview
->GetPrintout()->HasPage(preview
->GetMinPage());
1229 bool wxPreviewControlBar::IsLastEnabled() const
1231 wxPrintPreviewBase
*preview
= GetPrintPreview();
1235 return preview
->GetPrintout()->HasPage(preview
->GetMaxPage());
1238 void wxPreviewControlBar::DoGotoPage(int page
)
1240 wxPrintPreviewBase
*preview
= GetPrintPreview();
1241 wxCHECK_RET( preview
, "Shouldn't be called if there is no preview." );
1243 preview
->SetCurrentPage(page
);
1245 if ( m_currentPageText
)
1246 m_currentPageText
->SetPageNumber(page
);
1249 void wxPreviewControlBar::OnGotoPage()
1251 wxPrintPreviewBase
*preview
= GetPrintPreview();
1254 if (preview
->GetMinPage() > 0)
1256 long currentPage
= m_currentPageText
->GetPageNumber();
1259 if (preview
->GetPrintout()->HasPage(currentPage
))
1261 preview
->SetCurrentPage(currentPage
);
1268 void wxPreviewControlBar::DoZoom()
1270 int zoom
= GetZoomControl();
1271 if (GetPrintPreview())
1272 GetPrintPreview()->SetZoom(zoom
);
1275 bool wxPreviewControlBar::IsZoomInEnabled() const
1277 if ( !m_zoomControl
)
1280 const unsigned sel
= m_zoomControl
->GetSelection();
1281 return sel
< m_zoomControl
->GetCount() - 1;
1284 bool wxPreviewControlBar::IsZoomOutEnabled() const
1286 return m_zoomControl
&& m_zoomControl
->GetSelection() > 0;
1289 void wxPreviewControlBar::DoZoomIn()
1291 if (IsZoomInEnabled())
1293 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() + 1);
1298 void wxPreviewControlBar::DoZoomOut()
1300 if (IsZoomOutEnabled())
1302 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() - 1);
1310 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1311 // sequentially to it in the simplest way possible.
1312 class SizerWithButtons
1315 // Constructor creates the sizer that will hold the buttons and stores the
1316 // parent that will be used for their creation.
1317 SizerWithButtons(wxWindow
*parent
)
1318 : m_sizer(new wxBoxSizer(wxHORIZONTAL
)),
1322 m_needsSeparator
= false;
1325 // Destructor associates the sizer with the parent window.
1328 m_parent
->SetSizer(m_sizer
);
1329 m_sizer
->Fit(m_parent
);
1333 // Add an arbitrary window to the sizer.
1334 void Add(wxWindow
*win
)
1336 if ( m_needsSeparator
)
1338 m_needsSeparator
= false;
1340 m_sizer
->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1343 m_hasContents
= true;
1346 wxSizerFlags().Border(wxLEFT
| wxTOP
| wxBOTTOM
).Center());
1349 // Add a button with the specified id, bitmap and tooltip.
1350 void AddButton(wxWindowID btnId
,
1351 const wxArtID
& artId
,
1352 const wxString
& tooltip
)
1354 // We don't use (smaller) images inside a button with a text label but
1355 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1356 // wxART_BUTTON here.
1357 wxBitmap bmp
= wxArtProvider::GetBitmap(artId
, wxART_TOOLBAR
);
1358 wxBitmapButton
* const btn
= new wxBitmapButton(m_parent
, btnId
, bmp
);
1359 btn
->SetToolTip(tooltip
);
1364 // Add a control at the right end of the window. This should be called last
1365 // as everything else added after it will be added on the right side too.
1366 void AddAtEnd(wxWindow
*win
)
1368 m_sizer
->AddStretchSpacer();
1370 wxSizerFlags().Border(wxTOP
| wxBOTTOM
| wxRIGHT
).Center());
1373 // Indicates the end of a group of buttons, a separator will be added after
1377 if ( m_hasContents
)
1379 m_needsSeparator
= true;
1380 m_hasContents
= false;
1385 wxSizer
* const m_sizer
;
1386 wxWindow
* const m_parent
;
1388 // If true, we have some controls since the last group beginning. This is
1389 // used to avoid inserting two consecutive separators if EndOfGroup() is
1393 // If true, a separator should be inserted before adding the next button.
1394 bool m_needsSeparator
;
1396 wxDECLARE_NO_COPY_CLASS(SizerWithButtons
);
1399 } // anonymous namespace
1401 void wxPreviewControlBar::CreateButtons()
1403 SizerWithButtons
sizer(this);
1405 // Print button group (a single button).
1406 if (m_buttonFlags
& wxPREVIEW_PRINT
)
1408 sizer
.AddButton(wxID_PREVIEW_PRINT
, wxART_PRINT
, _("Print"));
1412 // Page selection buttons group.
1413 if (m_buttonFlags
& wxPREVIEW_FIRST
)
1415 sizer
.AddButton(wxID_PREVIEW_FIRST
, wxART_GOTO_FIRST
, _("First page"));
1418 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
1420 sizer
.AddButton(wxID_PREVIEW_PREVIOUS
, wxART_GO_BACK
, _("Previous page"));
1423 if (m_buttonFlags
& wxPREVIEW_GOTO
)
1425 int minPage
, maxPage
, pageFrom
, pageTo
;
1426 m_printPreview
->GetPrintout()->GetPageInfo(&minPage
, &maxPage
,
1427 &pageFrom
, &pageTo
);
1429 m_currentPageText
= new wxPrintPageTextCtrl(this, minPage
, maxPage
);
1430 sizer
.Add(m_currentPageText
);
1433 maxPageText
= new wxStaticText(this, wxID_ANY
,
1434 wxString::Format("/ %d", maxPage
));
1436 sizer
.Add(maxPageText
);
1439 if (m_buttonFlags
& wxPREVIEW_NEXT
)
1441 sizer
.AddButton(wxID_PREVIEW_NEXT
, wxART_GO_FORWARD
, _("Next page"));
1444 if (m_buttonFlags
& wxPREVIEW_LAST
)
1446 sizer
.AddButton(wxID_PREVIEW_LAST
, wxART_GOTO_LAST
, _("Last page"));
1451 // Zoom controls group.
1452 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
1454 sizer
.AddButton(wxID_PREVIEW_ZOOM_OUT
, wxART_MINUS
, _("Zoom Out"));
1456 wxString choices
[] =
1458 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1459 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1460 wxT("120%"), wxT("150%"), wxT("200%")
1462 int n
= WXSIZEOF(choices
);
1464 m_zoomControl
= new wxChoice( this, wxID_PREVIEW_ZOOM
, wxDefaultPosition
, wxSize(70,wxDefaultCoord
), n
, choices
, 0 );
1465 sizer
.Add(m_zoomControl
);
1466 SetZoomControl(m_printPreview
->GetZoom());
1468 sizer
.AddButton(wxID_PREVIEW_ZOOM_IN
, wxART_PLUS
, _("Zoom In"));
1473 // Close button group (single button again).
1474 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("&Close"));
1475 sizer
.AddAtEnd(m_closeButton
);
1478 void wxPreviewControlBar::SetZoomControl(int zoom
)
1482 int n
, count
= m_zoomControl
->GetCount();
1484 for (n
=0; n
<count
; n
++)
1486 if (m_zoomControl
->GetString(n
).BeforeFirst(wxT('%')).ToLong(&val
) &&
1487 (val
>= long(zoom
)))
1489 m_zoomControl
->SetSelection(n
);
1494 m_zoomControl
->SetSelection(count
-1);
1498 int wxPreviewControlBar::GetZoomControl()
1500 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxEmptyString
))
1503 if (m_zoomControl
->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val
))
1515 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
1517 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
1518 EVT_CHAR_HOOK(wxPreviewFrame::OnChar
)
1519 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
1522 void wxPreviewFrame::OnChar(wxKeyEvent
&event
)
1524 if ( event
.GetKeyCode() == WXK_ESCAPE
)
1534 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxWindow
*parent
, const wxString
& title
,
1535 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
1536 wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
, name
)
1538 m_printPreview
= preview
;
1539 m_controlBar
= NULL
;
1540 m_previewCanvas
= NULL
;
1541 m_windowDisabler
= NULL
;
1543 // Give the application icon
1545 wxFrame
* topFrame
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
1547 SetIcons(topFrame
->GetIcons());
1551 wxPreviewFrame::~wxPreviewFrame()
1555 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
1557 if (m_windowDisabler
)
1558 delete m_windowDisabler
;
1560 // Need to delete the printout and the print preview
1561 wxPrintout
*printout
= m_printPreview
->GetPrintout();
1565 m_printPreview
->SetPrintout(NULL
);
1566 m_printPreview
->SetCanvas(NULL
);
1567 m_printPreview
->SetFrame(NULL
);
1570 m_previewCanvas
->SetPreview(NULL
);
1571 wxDELETE(m_printPreview
);
1576 void wxPreviewFrame::Initialize()
1584 m_printPreview
->SetCanvas(m_previewCanvas
);
1585 m_printPreview
->SetFrame(this);
1587 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
1589 item0
->Add( m_controlBar
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1590 item0
->Add( m_previewCanvas
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1592 SetAutoLayout( true );
1595 m_windowDisabler
= new wxWindowDisabler(this);
1599 m_printPreview
->AdjustScrollbars(m_previewCanvas
);
1600 m_previewCanvas
->SetFocus();
1601 m_controlBar
->SetFocus();
1604 void wxPreviewFrame::CreateCanvas()
1606 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
1609 void wxPreviewFrame::CreateControlBar()
1611 long buttons
= wxPREVIEW_DEFAULT
;
1612 if (m_printPreview
->GetPrintoutForPrinting())
1613 buttons
|= wxPREVIEW_PRINT
;
1615 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this);
1616 m_controlBar
->CreateButtons();
1623 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
1625 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1626 wxPrintout
*printoutForPrinting
,
1630 m_printDialogData
= (*data
);
1632 Init(printout
, printoutForPrinting
);
1635 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1636 wxPrintout
*printoutForPrinting
,
1637 wxPrintDialogData
*data
)
1640 m_printDialogData
= (*data
);
1642 Init(printout
, printoutForPrinting
);
1645 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
1646 wxPrintout
*printoutForPrinting
)
1649 m_previewPrintout
= printout
;
1650 if (m_previewPrintout
)
1651 m_previewPrintout
->SetPreview(static_cast<wxPrintPreview
*>(this));
1653 m_printPrintout
= printoutForPrinting
;
1655 m_previewCanvas
= NULL
;
1656 m_previewFrame
= NULL
;
1657 m_previewBitmap
= NULL
;
1658 m_previewFailed
= false;
1665 m_printingPrepared
= false;
1670 wxPrintPreviewBase::~wxPrintPreviewBase()
1672 if (m_previewPrintout
)
1673 delete m_previewPrintout
;
1674 if (m_previewBitmap
)
1675 delete m_previewBitmap
;
1676 if (m_printPrintout
)
1677 delete m_printPrintout
;
1680 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
1682 if (m_currentPage
== pageNum
)
1685 m_currentPage
= pageNum
;
1687 InvalidatePreviewBitmap();
1689 if (m_previewCanvas
)
1691 AdjustScrollbars(m_previewCanvas
);
1693 m_previewCanvas
->Refresh();
1694 m_previewCanvas
->SetFocus();
1699 int wxPrintPreviewBase::GetCurrentPage() const
1700 { return m_currentPage
; }
1701 void wxPrintPreviewBase::SetPrintout(wxPrintout
*printout
)
1702 { m_previewPrintout
= printout
; }
1703 wxPrintout
*wxPrintPreviewBase::GetPrintout() const
1704 { return m_previewPrintout
; }
1705 wxPrintout
*wxPrintPreviewBase::GetPrintoutForPrinting() const
1706 { return m_printPrintout
; }
1707 void wxPrintPreviewBase::SetFrame(wxFrame
*frame
)
1708 { m_previewFrame
= frame
; }
1709 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas
*canvas
)
1710 { m_previewCanvas
= canvas
; }
1711 wxFrame
*wxPrintPreviewBase::GetFrame() const
1712 { return m_previewFrame
; }
1713 wxPreviewCanvas
*wxPrintPreviewBase::GetCanvas() const
1714 { return m_previewCanvas
; }
1716 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas
*canvas
, wxRect
& pageRect
, wxRect
& paperRect
)
1718 // Calculate the rectangles for the printable area of the page and the
1719 // entire paper as they appear on the canvas on-screen.
1720 int canvasWidth
, canvasHeight
;
1721 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
1723 float zoomScale
= float(m_currentZoom
) / 100;
1724 float screenPrintableWidth
= zoomScale
* m_pageWidth
* m_previewScaleX
;
1725 float screenPrintableHeight
= zoomScale
* m_pageHeight
* m_previewScaleY
;
1727 wxRect devicePaperRect
= m_previewPrintout
->GetPaperRectPixels();
1728 wxCoord devicePrintableWidth
, devicePrintableHeight
;
1729 m_previewPrintout
->GetPageSizePixels(&devicePrintableWidth
, &devicePrintableHeight
);
1730 float scaleX
= screenPrintableWidth
/ devicePrintableWidth
;
1731 float scaleY
= screenPrintableHeight
/ devicePrintableHeight
;
1732 paperRect
.width
= wxCoord(scaleX
* devicePaperRect
.width
);
1733 paperRect
.height
= wxCoord(scaleY
* devicePaperRect
.height
);
1735 paperRect
.x
= wxCoord((canvasWidth
- paperRect
.width
)/ 2.0);
1736 if (paperRect
.x
< m_leftMargin
)
1737 paperRect
.x
= m_leftMargin
;
1738 paperRect
.y
= wxCoord((canvasHeight
- paperRect
.height
)/ 2.0);
1739 if (paperRect
.y
< m_topMargin
)
1740 paperRect
.y
= m_topMargin
;
1742 pageRect
.x
= paperRect
.x
- wxCoord(scaleX
* devicePaperRect
.x
);
1743 pageRect
.y
= paperRect
.y
- wxCoord(scaleY
* devicePaperRect
.y
);
1744 pageRect
.width
= wxCoord(screenPrintableWidth
);
1745 pageRect
.height
= wxCoord(screenPrintableHeight
);
1749 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1751 wxDELETE(m_previewBitmap
);
1752 // if there was a problem with rendering the preview, try again now
1753 // that it changed in some way (less memory may be needed, for example):
1754 m_previewFailed
= false;
1757 bool wxPrintPreviewBase::UpdatePageRendering()
1759 if ( m_previewBitmap
)
1762 if ( m_previewFailed
)
1765 if ( !RenderPage(m_currentPage
) )
1767 m_previewFailed
= true; // don't waste time failing again
1774 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1776 DrawBlankPage(canvas
, dc
);
1778 if (!m_previewBitmap
)
1783 wxRect pageRect
, paperRect
;
1784 CalcRects(canvas
, pageRect
, paperRect
);
1786 temp_dc
.SelectObject(*m_previewBitmap
);
1788 dc
.Blit(pageRect
.x
, pageRect
.y
,
1789 m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
1791 temp_dc
.SelectObject(wxNullBitmap
);
1795 // Adjusts the scrollbars for the current scale
1796 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas
*canvas
)
1801 wxRect pageRect
, paperRect
;
1802 CalcRects(canvas
, pageRect
, paperRect
);
1803 int totalWidth
= paperRect
.width
+ 2 * m_leftMargin
;
1804 int totalHeight
= paperRect
.height
+ 2 * m_topMargin
;
1805 int scrollUnitsX
= totalWidth
/ 10;
1806 int scrollUnitsY
= totalHeight
/ 10;
1807 wxSize virtualSize
= canvas
->GetVirtualSize();
1808 if (virtualSize
.GetWidth() != totalWidth
|| virtualSize
.GetHeight() != totalHeight
)
1809 canvas
->SetScrollbars(10, 10, scrollUnitsX
, scrollUnitsY
, 0, 0, true);
1812 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC
& dc
, int pageNum
)
1814 m_previewPrintout
->SetDC(&dc
);
1815 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
1817 // Need to delay OnPreparePrinting() until here, so we have enough
1819 if (!m_printingPrepared
)
1821 m_previewPrintout
->OnPreparePrinting();
1823 m_previewPrintout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
1824 m_printingPrepared
= true;
1827 m_previewPrintout
->OnBeginPrinting();
1829 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
1831 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
1835 m_previewPrintout
->OnPrintPage(pageNum
);
1836 m_previewPrintout
->OnEndDocument();
1837 m_previewPrintout
->OnEndPrinting();
1839 m_previewPrintout
->SetDC(NULL
);
1844 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap
& bmp
, int pageNum
)
1846 wxMemoryDC memoryDC
;
1847 memoryDC
.SelectObject(bmp
);
1850 return RenderPageIntoDC(memoryDC
, pageNum
);
1853 bool wxPrintPreviewBase::RenderPage(int pageNum
)
1857 if (!m_previewCanvas
)
1859 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1863 wxRect pageRect
, paperRect
;
1864 CalcRects(m_previewCanvas
, pageRect
, paperRect
);
1866 if (!m_previewBitmap
)
1868 m_previewBitmap
= new wxBitmap(pageRect
.width
, pageRect
.height
);
1870 if (!m_previewBitmap
|| !m_previewBitmap
->Ok())
1872 InvalidatePreviewBitmap();
1873 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
1878 if ( !RenderPageIntoBitmap(*m_previewBitmap
, pageNum
) )
1880 InvalidatePreviewBitmap();
1881 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
1888 status
= wxString::Format(_("Page %d of %d"), pageNum
, m_maxPage
);
1890 status
= wxString::Format(_("Page %d"), pageNum
);
1893 m_previewFrame
->SetStatusText(status
);
1899 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1901 wxRect pageRect
, paperRect
;
1903 CalcRects(canvas
, pageRect
, paperRect
);
1905 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
1906 wxCoord shadowOffset
= 4;
1908 dc
.SetPen(*wxBLACK_PEN
);
1909 dc
.SetBrush(*wxBLACK_BRUSH
);
1910 dc
.DrawRectangle(paperRect
.x
+ shadowOffset
, paperRect
.y
+ paperRect
.height
+ 1,
1911 paperRect
.width
, shadowOffset
);
1913 dc
.DrawRectangle(paperRect
.x
+ paperRect
.width
, paperRect
.y
+ shadowOffset
,
1914 shadowOffset
, paperRect
.height
);
1916 // Draw blank page allowing for 1-pixel border AROUND the actual paper
1917 dc
.SetPen(*wxBLACK_PEN
);
1918 dc
.SetBrush(*wxWHITE_BRUSH
);
1919 dc
.DrawRectangle(paperRect
.x
- 2, paperRect
.y
- 1,
1920 paperRect
.width
+ 3, paperRect
.height
+ 2);
1925 void wxPrintPreviewBase::SetZoom(int percent
)
1927 if (m_currentZoom
== percent
)
1930 m_currentZoom
= percent
;
1932 InvalidatePreviewBitmap();
1934 if (m_previewCanvas
)
1936 AdjustScrollbars(m_previewCanvas
);
1937 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
1938 m_previewCanvas
->ClearBackground();
1939 m_previewCanvas
->Refresh();
1940 m_previewCanvas
->SetFocus();
1944 wxPrintDialogData
& wxPrintPreviewBase::GetPrintDialogData()
1946 return m_printDialogData
;
1949 int wxPrintPreviewBase::GetZoom() const
1950 { return m_currentZoom
; }
1951 int wxPrintPreviewBase::GetMaxPage() const
1952 { return m_maxPage
; }
1953 int wxPrintPreviewBase::GetMinPage() const
1954 { return m_minPage
; }
1955 bool wxPrintPreviewBase::IsOk() const
1957 void wxPrintPreviewBase::SetOk(bool ok
)
1960 //----------------------------------------------------------------------------
1962 //----------------------------------------------------------------------------
1964 IMPLEMENT_CLASS(wxPrintPreview
, wxPrintPreviewBase
)
1966 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
1967 wxPrintout
*printoutForPrinting
,
1968 wxPrintDialogData
*data
) :
1969 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
1971 m_pimpl
= wxPrintFactory::GetFactory()->
1972 CreatePrintPreview( printout
, printoutForPrinting
, data
);
1975 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
1976 wxPrintout
*printoutForPrinting
,
1977 wxPrintData
*data
) :
1978 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
1980 m_pimpl
= wxPrintFactory::GetFactory()->
1981 CreatePrintPreview( printout
, printoutForPrinting
, data
);
1984 wxPrintPreview::~wxPrintPreview()
1988 // don't delete twice
1989 m_printPrintout
= NULL
;
1990 m_previewPrintout
= NULL
;
1991 m_previewBitmap
= NULL
;
1994 bool wxPrintPreview::SetCurrentPage(int pageNum
)
1996 return m_pimpl
->SetCurrentPage( pageNum
);
1999 int wxPrintPreview::GetCurrentPage() const
2001 return m_pimpl
->GetCurrentPage();
2004 void wxPrintPreview::SetPrintout(wxPrintout
*printout
)
2006 m_pimpl
->SetPrintout( printout
);
2009 wxPrintout
*wxPrintPreview::GetPrintout() const
2011 return m_pimpl
->GetPrintout();
2014 wxPrintout
*wxPrintPreview::GetPrintoutForPrinting() const
2016 return m_pimpl
->GetPrintoutForPrinting();
2019 void wxPrintPreview::SetFrame(wxFrame
*frame
)
2021 m_pimpl
->SetFrame( frame
);
2024 void wxPrintPreview::SetCanvas(wxPreviewCanvas
*canvas
)
2026 m_pimpl
->SetCanvas( canvas
);
2029 wxFrame
*wxPrintPreview::GetFrame() const
2031 return m_pimpl
->GetFrame();
2034 wxPreviewCanvas
*wxPrintPreview::GetCanvas() const
2036 return m_pimpl
->GetCanvas();
2039 bool wxPrintPreview::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2041 return m_pimpl
->PaintPage( canvas
, dc
);
2044 bool wxPrintPreview::UpdatePageRendering()
2046 return m_pimpl
->UpdatePageRendering();
2049 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2051 return m_pimpl
->DrawBlankPage( canvas
, dc
);
2054 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas
*canvas
)
2056 m_pimpl
->AdjustScrollbars( canvas
);
2059 bool wxPrintPreview::RenderPage(int pageNum
)
2061 return m_pimpl
->RenderPage( pageNum
);
2064 void wxPrintPreview::SetZoom(int percent
)
2066 m_pimpl
->SetZoom( percent
);
2069 int wxPrintPreview::GetZoom() const
2071 return m_pimpl
->GetZoom();
2074 wxPrintDialogData
& wxPrintPreview::GetPrintDialogData()
2076 return m_pimpl
->GetPrintDialogData();
2079 int wxPrintPreview::GetMaxPage() const
2081 return m_pimpl
->GetMaxPage();
2084 int wxPrintPreview::GetMinPage() const
2086 return m_pimpl
->GetMinPage();
2089 bool wxPrintPreview::IsOk() const
2091 return m_pimpl
->Ok();
2094 void wxPrintPreview::SetOk(bool ok
)
2096 m_pimpl
->SetOk( ok
);
2099 bool wxPrintPreview::Print(bool interactive
)
2101 return m_pimpl
->Print( interactive
);
2104 void wxPrintPreview::DetermineScaling()
2106 m_pimpl
->DetermineScaling();
2109 #endif // wxUSE_PRINTING_ARCHITECTURE