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
1002 // ----------------------------------------------------------------------------
1003 // wxPrintPageTextCtrl
1004 // ----------------------------------------------------------------------------
1006 // This text control contains the page number in the interval specified during
1007 // its construction. Invalid pages are not accepted and the control contents is
1008 // validated when it loses focus. Conversely, if the user changes the page to
1009 // another valid one or presses Enter, OnGotoPage() method of the preview object
1011 class wxPrintPageTextCtrl
: public wxTextCtrl
1014 wxPrintPageTextCtrl(wxPreviewControlBar
*preview
, int minPage
, int maxPage
)
1015 : wxTextCtrl(preview
,
1017 PageAsString(minPage
),
1019 // We use hardcoded 99999 for the width instead of fitting
1020 // it to the values we can show because the control looks
1021 // uncomfortably narrow if the real page number is just
1022 // one or two digits.
1023 wxSize(preview
->GetTextExtent("99999").x
, wxDefaultCoord
),
1025 #if wxUSE_VALIDATORS
1026 , wxTextValidator(wxFILTER_DIGITS
)
1027 #endif // wxUSE_VALIDATORS
1035 Connect(wxEVT_KILL_FOCUS
,
1036 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus
));
1037 Connect(wxEVT_COMMAND_TEXT_ENTER
,
1038 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter
));
1041 // Helpers to conveniently set or get the current page number. Return value
1042 // is 0 if the current controls contents is invalid.
1043 void SetPageNumber(int page
)
1045 wxASSERT( IsValidPage(page
) );
1047 SetValue(PageAsString(page
));
1050 int GetPageNumber() const
1053 if ( !GetValue().ToLong(&value
) || !IsValidPage(value
) )
1056 // Cast is safe because the value is less than (int) m_maxPage.
1057 return static_cast<int>(value
);
1061 static wxString
PageAsString(int page
)
1063 return wxString::Format("%d", page
);
1066 bool IsValidPage(int page
) const
1068 return page
>= m_minPage
&& page
<= m_maxPage
;
1073 const int page
= GetPageNumber();
1078 if ( page
!= m_page
)
1080 // We have a valid page, remember it.
1083 // And notify the owner about the change.
1084 m_preview
->OnGotoPage();
1086 //else: Nothing really changed.
1091 void OnKillFocus(wxFocusEvent
& event
)
1093 if ( !DoChangePage() )
1095 // The current contents is invalid so reset it back to the last
1096 // known good page index.
1097 SetPageNumber(m_page
);
1103 void OnTextEnter(wxCommandEvent
& WXUNUSED(event
))
1109 wxPreviewControlBar
* const m_preview
;
1111 const int m_minPage
,
1114 // This is the last valid page value that we had, we revert to it if an
1115 // invalid page is entered.
1118 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl
);
1121 //----------------------------------------------------------------------------
1122 // wxPreviewControlBar
1123 //----------------------------------------------------------------------------
1125 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
1127 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
1128 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
1129 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrintButton
)
1130 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
1131 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
1132 EVT_BUTTON(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnFirstButton
)
1133 EVT_BUTTON(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnLastButton
)
1134 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnZoomInButton
)
1135 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnZoomOutButton
)
1137 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnUpdatePreviousButton
)
1138 EVT_UPDATE_UI(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnUpdateNextButton
)
1139 EVT_UPDATE_UI(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnUpdateFirstButton
)
1140 EVT_UPDATE_UI(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnUpdateLastButton
)
1141 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnUpdateZoomInButton
)
1142 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnUpdateZoomOutButton
)
1144 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoomChoice
)
1145 EVT_PAINT(wxPreviewControlBar::OnPaint
)
1149 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
1150 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
1151 long style
, const wxString
& name
):
1152 wxPanel(parent
, wxID_ANY
, pos
, size
, style
, name
)
1154 m_printPreview
= preview
;
1155 m_closeButton
= NULL
;
1156 m_zoomControl
= NULL
;
1157 m_currentPageText
= NULL
;
1158 m_buttonFlags
= buttons
;
1161 wxPreviewControlBar::~wxPreviewControlBar()
1165 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1171 dc
.SetPen(*wxBLACK_PEN
);
1172 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1173 dc
.DrawLine( 0, h
-1, w
, h
-1 );
1176 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
1178 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
1182 void wxPreviewControlBar::OnPrint(void)
1184 wxPrintPreviewBase
*preview
= GetPrintPreview();
1185 preview
->Print(true);
1188 void wxPreviewControlBar::OnNext()
1190 if ( IsNextEnabled() )
1191 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1194 void wxPreviewControlBar::OnPrevious()
1196 if ( IsPreviousEnabled() )
1197 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1200 void wxPreviewControlBar::OnFirst()
1202 if ( IsFirstEnabled() )
1203 DoGotoPage(GetPrintPreview()->GetMinPage());
1206 void wxPreviewControlBar::OnLast()
1208 if ( IsLastEnabled() )
1209 DoGotoPage(GetPrintPreview()->GetMaxPage());
1212 bool wxPreviewControlBar::IsNextEnabled() const
1214 wxPrintPreviewBase
*preview
= GetPrintPreview();
1218 const int currentPage
= preview
->GetCurrentPage();
1219 return currentPage
< preview
->GetMaxPage() &&
1220 preview
->GetPrintout()->HasPage(currentPage
+ 1);
1223 bool wxPreviewControlBar::IsPreviousEnabled() const
1225 wxPrintPreviewBase
*preview
= GetPrintPreview();
1229 const int currentPage
= preview
->GetCurrentPage();
1230 return currentPage
> preview
->GetMinPage() &&
1231 preview
->GetPrintout()->HasPage(currentPage
- 1);
1234 bool wxPreviewControlBar::IsFirstEnabled() const
1236 wxPrintPreviewBase
*preview
= GetPrintPreview();
1240 return preview
->GetPrintout()->HasPage(preview
->GetMinPage());
1243 bool wxPreviewControlBar::IsLastEnabled() const
1245 wxPrintPreviewBase
*preview
= GetPrintPreview();
1249 return preview
->GetPrintout()->HasPage(preview
->GetMaxPage());
1252 void wxPreviewControlBar::DoGotoPage(int page
)
1254 wxPrintPreviewBase
*preview
= GetPrintPreview();
1255 wxCHECK_RET( preview
, "Shouldn't be called if there is no preview." );
1257 preview
->SetCurrentPage(page
);
1259 if ( m_currentPageText
)
1260 m_currentPageText
->SetPageNumber(page
);
1263 void wxPreviewControlBar::OnGotoPage()
1265 wxPrintPreviewBase
*preview
= GetPrintPreview();
1268 if (preview
->GetMinPage() > 0)
1270 long currentPage
= m_currentPageText
->GetPageNumber();
1273 if (preview
->GetPrintout()->HasPage(currentPage
))
1275 preview
->SetCurrentPage(currentPage
);
1282 void wxPreviewControlBar::DoZoom()
1284 int zoom
= GetZoomControl();
1285 if (GetPrintPreview())
1286 GetPrintPreview()->SetZoom(zoom
);
1289 bool wxPreviewControlBar::IsZoomInEnabled() const
1291 if ( !m_zoomControl
)
1294 const unsigned sel
= m_zoomControl
->GetSelection();
1295 return sel
< m_zoomControl
->GetCount() - 1;
1298 bool wxPreviewControlBar::IsZoomOutEnabled() const
1300 return m_zoomControl
&& m_zoomControl
->GetSelection() > 0;
1303 void wxPreviewControlBar::DoZoomIn()
1305 if (IsZoomInEnabled())
1307 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() + 1);
1312 void wxPreviewControlBar::DoZoomOut()
1314 if (IsZoomOutEnabled())
1316 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() - 1);
1324 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1325 // sequentially to it in the simplest way possible.
1326 class SizerWithButtons
1329 // Constructor creates the sizer that will hold the buttons and stores the
1330 // parent that will be used for their creation.
1331 SizerWithButtons(wxWindow
*parent
)
1332 : m_sizer(new wxBoxSizer(wxHORIZONTAL
)),
1336 m_needsSeparator
= false;
1339 // Destructor associates the sizer with the parent window.
1342 m_parent
->SetSizer(m_sizer
);
1343 m_sizer
->Fit(m_parent
);
1347 // Add an arbitrary window to the sizer.
1348 void Add(wxWindow
*win
)
1350 if ( m_needsSeparator
)
1352 m_needsSeparator
= false;
1354 m_sizer
->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1357 m_hasContents
= true;
1360 wxSizerFlags().Border(wxLEFT
| wxTOP
| wxBOTTOM
).Center());
1363 // Add a button with the specified id, bitmap and tooltip.
1364 void AddButton(wxWindowID btnId
,
1365 const wxArtID
& artId
,
1366 const wxString
& tooltip
)
1368 // We don't use (smaller) images inside a button with a text label but
1369 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1370 // wxART_BUTTON here.
1371 wxBitmap bmp
= wxArtProvider::GetBitmap(artId
, wxART_TOOLBAR
);
1372 wxBitmapButton
* const btn
= new wxBitmapButton(m_parent
, btnId
, bmp
);
1373 btn
->SetToolTip(tooltip
);
1378 // Add a control at the right end of the window. This should be called last
1379 // as everything else added after it will be added on the right side too.
1380 void AddAtEnd(wxWindow
*win
)
1382 m_sizer
->AddStretchSpacer();
1384 wxSizerFlags().Border(wxTOP
| wxBOTTOM
| wxRIGHT
).Center());
1387 // Indicates the end of a group of buttons, a separator will be added after
1391 if ( m_hasContents
)
1393 m_needsSeparator
= true;
1394 m_hasContents
= false;
1399 wxSizer
* const m_sizer
;
1400 wxWindow
* const m_parent
;
1402 // If true, we have some controls since the last group beginning. This is
1403 // used to avoid inserting two consecutive separators if EndOfGroup() is
1407 // If true, a separator should be inserted before adding the next button.
1408 bool m_needsSeparator
;
1410 wxDECLARE_NO_COPY_CLASS(SizerWithButtons
);
1413 } // anonymous namespace
1415 void wxPreviewControlBar::CreateButtons()
1417 SizerWithButtons
sizer(this);
1419 // Print button group (a single button).
1420 if (m_buttonFlags
& wxPREVIEW_PRINT
)
1422 sizer
.AddButton(wxID_PREVIEW_PRINT
, wxART_PRINT
, _("Print"));
1426 // Page selection buttons group.
1427 if (m_buttonFlags
& wxPREVIEW_FIRST
)
1429 sizer
.AddButton(wxID_PREVIEW_FIRST
, wxART_GOTO_FIRST
, _("First page"));
1432 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
1434 sizer
.AddButton(wxID_PREVIEW_PREVIOUS
, wxART_GO_BACK
, _("Previous page"));
1437 if (m_buttonFlags
& wxPREVIEW_GOTO
)
1439 int minPage
, maxPage
, pageFrom
, pageTo
;
1440 m_printPreview
->GetPrintout()->GetPageInfo(&minPage
, &maxPage
,
1441 &pageFrom
, &pageTo
);
1443 m_currentPageText
= new wxPrintPageTextCtrl(this, minPage
, maxPage
);
1444 sizer
.Add(m_currentPageText
);
1447 maxPageText
= new wxStaticText(this, wxID_ANY
,
1448 wxString::Format("/ %d", maxPage
));
1450 sizer
.Add(maxPageText
);
1453 if (m_buttonFlags
& wxPREVIEW_NEXT
)
1455 sizer
.AddButton(wxID_PREVIEW_NEXT
, wxART_GO_FORWARD
, _("Next page"));
1458 if (m_buttonFlags
& wxPREVIEW_LAST
)
1460 sizer
.AddButton(wxID_PREVIEW_LAST
, wxART_GOTO_LAST
, _("Last page"));
1465 // Zoom controls group.
1466 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
1468 sizer
.AddButton(wxID_PREVIEW_ZOOM_OUT
, wxART_MINUS
, _("Zoom Out"));
1470 wxString choices
[] =
1472 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1473 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1474 wxT("120%"), wxT("150%"), wxT("200%")
1476 int n
= WXSIZEOF(choices
);
1478 m_zoomControl
= new wxChoice( this, wxID_PREVIEW_ZOOM
, wxDefaultPosition
, wxSize(70,wxDefaultCoord
), n
, choices
, 0 );
1479 sizer
.Add(m_zoomControl
);
1480 SetZoomControl(m_printPreview
->GetZoom());
1482 sizer
.AddButton(wxID_PREVIEW_ZOOM_IN
, wxART_PLUS
, _("Zoom In"));
1487 // Close button group (single button again).
1488 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("&Close"));
1489 sizer
.AddAtEnd(m_closeButton
);
1492 void wxPreviewControlBar::SetZoomControl(int zoom
)
1496 int n
, count
= m_zoomControl
->GetCount();
1498 for (n
=0; n
<count
; n
++)
1500 if (m_zoomControl
->GetString(n
).BeforeFirst(wxT('%')).ToLong(&val
) &&
1501 (val
>= long(zoom
)))
1503 m_zoomControl
->SetSelection(n
);
1508 m_zoomControl
->SetSelection(count
-1);
1512 int wxPreviewControlBar::GetZoomControl()
1514 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxEmptyString
))
1517 if (m_zoomControl
->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val
))
1529 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
1531 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
1532 EVT_CHAR_HOOK(wxPreviewFrame::OnChar
)
1533 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
1536 void wxPreviewFrame::OnChar(wxKeyEvent
&event
)
1538 if ( event
.GetKeyCode() == WXK_ESCAPE
)
1548 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxWindow
*parent
, const wxString
& title
,
1549 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
1550 wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
, name
)
1552 m_printPreview
= preview
;
1553 m_controlBar
= NULL
;
1554 m_previewCanvas
= NULL
;
1555 m_windowDisabler
= NULL
;
1557 // Give the application icon
1559 wxFrame
* topFrame
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
1561 SetIcons(topFrame
->GetIcons());
1565 wxPreviewFrame::~wxPreviewFrame()
1569 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
1571 if (m_windowDisabler
)
1572 delete m_windowDisabler
;
1574 // Need to delete the printout and the print preview
1575 wxPrintout
*printout
= m_printPreview
->GetPrintout();
1579 m_printPreview
->SetPrintout(NULL
);
1580 m_printPreview
->SetCanvas(NULL
);
1581 m_printPreview
->SetFrame(NULL
);
1584 m_previewCanvas
->SetPreview(NULL
);
1585 wxDELETE(m_printPreview
);
1590 void wxPreviewFrame::Initialize()
1598 m_printPreview
->SetCanvas(m_previewCanvas
);
1599 m_printPreview
->SetFrame(this);
1601 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
1603 item0
->Add( m_controlBar
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1604 item0
->Add( m_previewCanvas
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1606 SetAutoLayout( true );
1609 m_windowDisabler
= new wxWindowDisabler(this);
1613 m_printPreview
->AdjustScrollbars(m_previewCanvas
);
1614 m_previewCanvas
->SetFocus();
1615 m_controlBar
->SetFocus();
1618 void wxPreviewFrame::CreateCanvas()
1620 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
1623 void wxPreviewFrame::CreateControlBar()
1625 long buttons
= wxPREVIEW_DEFAULT
;
1626 if (m_printPreview
->GetPrintoutForPrinting())
1627 buttons
|= wxPREVIEW_PRINT
;
1629 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this);
1630 m_controlBar
->CreateButtons();
1637 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
1639 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1640 wxPrintout
*printoutForPrinting
,
1644 m_printDialogData
= (*data
);
1646 Init(printout
, printoutForPrinting
);
1649 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1650 wxPrintout
*printoutForPrinting
,
1651 wxPrintDialogData
*data
)
1654 m_printDialogData
= (*data
);
1656 Init(printout
, printoutForPrinting
);
1659 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
1660 wxPrintout
*printoutForPrinting
)
1663 m_previewPrintout
= printout
;
1664 if (m_previewPrintout
)
1665 m_previewPrintout
->SetPreview(static_cast<wxPrintPreview
*>(this));
1667 m_printPrintout
= printoutForPrinting
;
1669 m_previewCanvas
= NULL
;
1670 m_previewFrame
= NULL
;
1671 m_previewBitmap
= NULL
;
1672 m_previewFailed
= false;
1676 m_leftMargin
= 2*wxSizerFlags::GetDefaultBorder();
1679 m_printingPrepared
= false;
1684 wxPrintPreviewBase::~wxPrintPreviewBase()
1686 if (m_previewPrintout
)
1687 delete m_previewPrintout
;
1688 if (m_previewBitmap
)
1689 delete m_previewBitmap
;
1690 if (m_printPrintout
)
1691 delete m_printPrintout
;
1694 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
1696 if (m_currentPage
== pageNum
)
1699 m_currentPage
= pageNum
;
1701 InvalidatePreviewBitmap();
1703 if (m_previewCanvas
)
1705 AdjustScrollbars(m_previewCanvas
);
1707 m_previewCanvas
->Refresh();
1708 m_previewCanvas
->SetFocus();
1713 int wxPrintPreviewBase::GetCurrentPage() const
1714 { return m_currentPage
; }
1715 void wxPrintPreviewBase::SetPrintout(wxPrintout
*printout
)
1716 { m_previewPrintout
= printout
; }
1717 wxPrintout
*wxPrintPreviewBase::GetPrintout() const
1718 { return m_previewPrintout
; }
1719 wxPrintout
*wxPrintPreviewBase::GetPrintoutForPrinting() const
1720 { return m_printPrintout
; }
1721 void wxPrintPreviewBase::SetFrame(wxFrame
*frame
)
1722 { m_previewFrame
= frame
; }
1723 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas
*canvas
)
1724 { m_previewCanvas
= canvas
; }
1725 wxFrame
*wxPrintPreviewBase::GetFrame() const
1726 { return m_previewFrame
; }
1727 wxPreviewCanvas
*wxPrintPreviewBase::GetCanvas() const
1728 { return m_previewCanvas
; }
1730 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas
*canvas
, wxRect
& pageRect
, wxRect
& paperRect
)
1732 // Calculate the rectangles for the printable area of the page and the
1733 // entire paper as they appear on the canvas on-screen.
1734 int canvasWidth
, canvasHeight
;
1735 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
1737 float zoomScale
= float(m_currentZoom
) / 100;
1738 float screenPrintableWidth
= zoomScale
* m_pageWidth
* m_previewScaleX
;
1739 float screenPrintableHeight
= zoomScale
* m_pageHeight
* m_previewScaleY
;
1741 wxRect devicePaperRect
= m_previewPrintout
->GetPaperRectPixels();
1742 wxCoord devicePrintableWidth
, devicePrintableHeight
;
1743 m_previewPrintout
->GetPageSizePixels(&devicePrintableWidth
, &devicePrintableHeight
);
1744 float scaleX
= screenPrintableWidth
/ devicePrintableWidth
;
1745 float scaleY
= screenPrintableHeight
/ devicePrintableHeight
;
1746 paperRect
.width
= wxCoord(scaleX
* devicePaperRect
.width
);
1747 paperRect
.height
= wxCoord(scaleY
* devicePaperRect
.height
);
1749 paperRect
.x
= wxCoord((canvasWidth
- paperRect
.width
)/ 2.0);
1750 if (paperRect
.x
< m_leftMargin
)
1751 paperRect
.x
= m_leftMargin
;
1752 paperRect
.y
= wxCoord((canvasHeight
- paperRect
.height
)/ 2.0);
1753 if (paperRect
.y
< m_topMargin
)
1754 paperRect
.y
= m_topMargin
;
1756 pageRect
.x
= paperRect
.x
- wxCoord(scaleX
* devicePaperRect
.x
);
1757 pageRect
.y
= paperRect
.y
- wxCoord(scaleY
* devicePaperRect
.y
);
1758 pageRect
.width
= wxCoord(screenPrintableWidth
);
1759 pageRect
.height
= wxCoord(screenPrintableHeight
);
1763 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1765 wxDELETE(m_previewBitmap
);
1766 // if there was a problem with rendering the preview, try again now
1767 // that it changed in some way (less memory may be needed, for example):
1768 m_previewFailed
= false;
1771 bool wxPrintPreviewBase::UpdatePageRendering()
1773 if ( m_previewBitmap
)
1776 if ( m_previewFailed
)
1779 if ( !RenderPage(m_currentPage
) )
1781 m_previewFailed
= true; // don't waste time failing again
1788 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1790 DrawBlankPage(canvas
, dc
);
1792 if (!m_previewBitmap
)
1797 wxRect pageRect
, paperRect
;
1798 CalcRects(canvas
, pageRect
, paperRect
);
1800 temp_dc
.SelectObject(*m_previewBitmap
);
1802 dc
.Blit(pageRect
.x
, pageRect
.y
,
1803 m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
1805 temp_dc
.SelectObject(wxNullBitmap
);
1809 // Adjusts the scrollbars for the current scale
1810 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas
*canvas
)
1815 wxRect pageRect
, paperRect
;
1816 CalcRects(canvas
, pageRect
, paperRect
);
1817 int totalWidth
= paperRect
.width
+ 2 * m_leftMargin
;
1818 int totalHeight
= paperRect
.height
+ 2 * m_topMargin
;
1819 int scrollUnitsX
= totalWidth
/ 10;
1820 int scrollUnitsY
= totalHeight
/ 10;
1821 wxSize virtualSize
= canvas
->GetVirtualSize();
1822 if (virtualSize
.GetWidth() != totalWidth
|| virtualSize
.GetHeight() != totalHeight
)
1823 canvas
->SetScrollbars(10, 10, scrollUnitsX
, scrollUnitsY
, 0, 0, true);
1826 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC
& dc
, int pageNum
)
1828 m_previewPrintout
->SetDC(&dc
);
1829 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
1831 // Need to delay OnPreparePrinting() until here, so we have enough
1833 if (!m_printingPrepared
)
1835 m_previewPrintout
->OnPreparePrinting();
1837 m_previewPrintout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
1838 m_printingPrepared
= true;
1841 m_previewPrintout
->OnBeginPrinting();
1843 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
1845 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
1849 m_previewPrintout
->OnPrintPage(pageNum
);
1850 m_previewPrintout
->OnEndDocument();
1851 m_previewPrintout
->OnEndPrinting();
1853 m_previewPrintout
->SetDC(NULL
);
1858 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap
& bmp
, int pageNum
)
1860 wxMemoryDC memoryDC
;
1861 memoryDC
.SelectObject(bmp
);
1864 return RenderPageIntoDC(memoryDC
, pageNum
);
1867 bool wxPrintPreviewBase::RenderPage(int pageNum
)
1871 if (!m_previewCanvas
)
1873 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1877 wxRect pageRect
, paperRect
;
1878 CalcRects(m_previewCanvas
, pageRect
, paperRect
);
1880 if (!m_previewBitmap
)
1882 m_previewBitmap
= new wxBitmap(pageRect
.width
, pageRect
.height
);
1884 if (!m_previewBitmap
|| !m_previewBitmap
->Ok())
1886 InvalidatePreviewBitmap();
1887 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
1892 if ( !RenderPageIntoBitmap(*m_previewBitmap
, pageNum
) )
1894 InvalidatePreviewBitmap();
1895 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
1902 status
= wxString::Format(_("Page %d of %d"), pageNum
, m_maxPage
);
1904 status
= wxString::Format(_("Page %d"), pageNum
);
1907 m_previewFrame
->SetStatusText(status
);
1913 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1915 wxRect pageRect
, paperRect
;
1917 CalcRects(canvas
, pageRect
, paperRect
);
1919 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
1920 wxCoord shadowOffset
= 4;
1922 dc
.SetPen(*wxBLACK_PEN
);
1923 dc
.SetBrush(*wxBLACK_BRUSH
);
1924 dc
.DrawRectangle(paperRect
.x
+ shadowOffset
, paperRect
.y
+ paperRect
.height
+ 1,
1925 paperRect
.width
, shadowOffset
);
1927 dc
.DrawRectangle(paperRect
.x
+ paperRect
.width
, paperRect
.y
+ shadowOffset
,
1928 shadowOffset
, paperRect
.height
);
1930 // Draw blank page allowing for 1-pixel border AROUND the actual paper
1931 dc
.SetPen(*wxBLACK_PEN
);
1932 dc
.SetBrush(*wxWHITE_BRUSH
);
1933 dc
.DrawRectangle(paperRect
.x
- 2, paperRect
.y
- 1,
1934 paperRect
.width
+ 3, paperRect
.height
+ 2);
1939 void wxPrintPreviewBase::SetZoom(int percent
)
1941 if (m_currentZoom
== percent
)
1944 m_currentZoom
= percent
;
1946 InvalidatePreviewBitmap();
1948 if (m_previewCanvas
)
1950 AdjustScrollbars(m_previewCanvas
);
1951 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
1952 m_previewCanvas
->ClearBackground();
1953 m_previewCanvas
->Refresh();
1954 m_previewCanvas
->SetFocus();
1958 wxPrintDialogData
& wxPrintPreviewBase::GetPrintDialogData()
1960 return m_printDialogData
;
1963 int wxPrintPreviewBase::GetZoom() const
1964 { return m_currentZoom
; }
1965 int wxPrintPreviewBase::GetMaxPage() const
1966 { return m_maxPage
; }
1967 int wxPrintPreviewBase::GetMinPage() const
1968 { return m_minPage
; }
1969 bool wxPrintPreviewBase::IsOk() const
1971 void wxPrintPreviewBase::SetOk(bool ok
)
1974 //----------------------------------------------------------------------------
1976 //----------------------------------------------------------------------------
1978 IMPLEMENT_CLASS(wxPrintPreview
, wxPrintPreviewBase
)
1980 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
1981 wxPrintout
*printoutForPrinting
,
1982 wxPrintDialogData
*data
) :
1983 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
1985 m_pimpl
= wxPrintFactory::GetFactory()->
1986 CreatePrintPreview( printout
, printoutForPrinting
, data
);
1989 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
1990 wxPrintout
*printoutForPrinting
,
1991 wxPrintData
*data
) :
1992 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
1994 m_pimpl
= wxPrintFactory::GetFactory()->
1995 CreatePrintPreview( printout
, printoutForPrinting
, data
);
1998 wxPrintPreview::~wxPrintPreview()
2002 // don't delete twice
2003 m_printPrintout
= NULL
;
2004 m_previewPrintout
= NULL
;
2005 m_previewBitmap
= NULL
;
2008 bool wxPrintPreview::SetCurrentPage(int pageNum
)
2010 return m_pimpl
->SetCurrentPage( pageNum
);
2013 int wxPrintPreview::GetCurrentPage() const
2015 return m_pimpl
->GetCurrentPage();
2018 void wxPrintPreview::SetPrintout(wxPrintout
*printout
)
2020 m_pimpl
->SetPrintout( printout
);
2023 wxPrintout
*wxPrintPreview::GetPrintout() const
2025 return m_pimpl
->GetPrintout();
2028 wxPrintout
*wxPrintPreview::GetPrintoutForPrinting() const
2030 return m_pimpl
->GetPrintoutForPrinting();
2033 void wxPrintPreview::SetFrame(wxFrame
*frame
)
2035 m_pimpl
->SetFrame( frame
);
2038 void wxPrintPreview::SetCanvas(wxPreviewCanvas
*canvas
)
2040 m_pimpl
->SetCanvas( canvas
);
2043 wxFrame
*wxPrintPreview::GetFrame() const
2045 return m_pimpl
->GetFrame();
2048 wxPreviewCanvas
*wxPrintPreview::GetCanvas() const
2050 return m_pimpl
->GetCanvas();
2053 bool wxPrintPreview::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2055 return m_pimpl
->PaintPage( canvas
, dc
);
2058 bool wxPrintPreview::UpdatePageRendering()
2060 return m_pimpl
->UpdatePageRendering();
2063 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2065 return m_pimpl
->DrawBlankPage( canvas
, dc
);
2068 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas
*canvas
)
2070 m_pimpl
->AdjustScrollbars( canvas
);
2073 bool wxPrintPreview::RenderPage(int pageNum
)
2075 return m_pimpl
->RenderPage( pageNum
);
2078 void wxPrintPreview::SetZoom(int percent
)
2080 m_pimpl
->SetZoom( percent
);
2083 int wxPrintPreview::GetZoom() const
2085 return m_pimpl
->GetZoom();
2088 wxPrintDialogData
& wxPrintPreview::GetPrintDialogData()
2090 return m_pimpl
->GetPrintDialogData();
2093 int wxPrintPreview::GetMaxPage() const
2095 return m_pimpl
->GetMaxPage();
2098 int wxPrintPreview::GetMinPage() const
2100 return m_pimpl
->GetMinPage();
2103 bool wxPrintPreview::IsOk() const
2105 return m_pimpl
->Ok();
2108 void wxPrintPreview::SetOk(bool ok
)
2110 m_pimpl
->SetOk( ok
);
2113 bool wxPrintPreview::Print(bool interactive
)
2115 return m_pimpl
->Print( interactive
);
2118 void wxPrintPreview::DetermineScaling()
2120 m_pimpl
->DetermineScaling();
2123 #endif // wxUSE_PRINTING_ARCHITECTURE