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 return m_pimpl
->Print( parent
, printout
, prompt
);
387 wxDC
* wxPrinter::PrintDialog(wxWindow
*parent
)
389 return m_pimpl
->PrintDialog( parent
);
392 wxPrintDialogData
& wxPrinter::GetPrintDialogData() const
394 return m_pimpl
->GetPrintDialogData();
397 // ---------------------------------------------------------------------------
398 // wxPrintDialogBase: the dialog for printing.
399 // ---------------------------------------------------------------------------
401 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase
, wxDialog
)
403 wxPrintDialogBase::wxPrintDialogBase(wxWindow
*parent
,
405 const wxString
&title
,
409 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Print")) : title
,
414 // ---------------------------------------------------------------------------
415 // wxPrintDialog: the dialog for printing
416 // ---------------------------------------------------------------------------
418 IMPLEMENT_CLASS(wxPrintDialog
, wxObject
)
420 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintDialogData
* data
)
422 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
425 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintData
* data
)
427 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
430 wxPrintDialog::~wxPrintDialog()
435 int wxPrintDialog::ShowModal()
437 return m_pimpl
->ShowModal();
440 wxPrintDialogData
& wxPrintDialog::GetPrintDialogData()
442 return m_pimpl
->GetPrintDialogData();
445 wxPrintData
& wxPrintDialog::GetPrintData()
447 return m_pimpl
->GetPrintData();
450 wxDC
*wxPrintDialog::GetPrintDC()
452 return m_pimpl
->GetPrintDC();
455 // ---------------------------------------------------------------------------
456 // wxPageSetupDialogBase: the page setup dialog
457 // ---------------------------------------------------------------------------
459 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase
, wxDialog
)
461 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow
*parent
,
463 const wxString
&title
,
467 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Page setup")) : title
,
472 // ---------------------------------------------------------------------------
473 // wxPageSetupDialog: the page setup dialog
474 // ---------------------------------------------------------------------------
476 IMPLEMENT_CLASS(wxPageSetupDialog
, wxObject
)
478 wxPageSetupDialog::wxPageSetupDialog(wxWindow
*parent
, wxPageSetupDialogData
*data
)
480 m_pimpl
= wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent
, data
);
483 wxPageSetupDialog::~wxPageSetupDialog()
488 int wxPageSetupDialog::ShowModal()
490 return m_pimpl
->ShowModal();
493 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupDialogData()
495 return m_pimpl
->GetPageSetupDialogData();
499 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupData()
501 return m_pimpl
->GetPageSetupDialogData();
504 //----------------------------------------------------------------------------
505 // wxPrintAbortDialog
506 //----------------------------------------------------------------------------
508 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
509 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
512 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
514 wxPrinterBase::sm_abortIt
= true;
515 wxPrinterBase::sm_abortWindow
->Show(false);
516 wxPrinterBase::sm_abortWindow
->Close(true);
517 wxPrinterBase::sm_abortWindow
->Destroy();
518 wxPrinterBase::sm_abortWindow
= NULL
;
521 //----------------------------------------------------------------------------
523 //----------------------------------------------------------------------------
525 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
527 wxPrintout::wxPrintout(const wxString
& title
)
529 m_printoutTitle
= title
;
533 m_pageWidthPixels
= 0;
534 m_pageHeightPixels
= 0;
542 wxPrintout::~wxPrintout()
546 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
548 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle
);
551 void wxPrintout::OnEndDocument()
556 void wxPrintout::OnBeginPrinting()
560 void wxPrintout::OnEndPrinting()
564 bool wxPrintout::HasPage(int page
)
569 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
577 void wxPrintout::FitThisSizeToPaper(const wxSize
& imageSize
)
579 // Set the DC scale and origin so that the given image size fits within the
580 // entire page and the origin is at the top left corner of the page. Note
581 // that with most printers, portions of the page will be non-printable. Use
582 // this if you're managing your own page margins.
583 if (!m_printoutDC
) return;
584 wxRect paperRect
= GetPaperRectPixels();
586 GetPageSizePixels(&pw
, &ph
);
588 m_printoutDC
->GetSize(&w
, &h
);
589 float scaleX
= ((float(paperRect
.width
) * w
) / (float(pw
) * imageSize
.x
));
590 float scaleY
= ((float(paperRect
.height
) * h
) / (float(ph
) * imageSize
.y
));
591 float actualScale
= wxMin(scaleX
, scaleY
);
592 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
593 m_printoutDC
->SetDeviceOrigin(0, 0);
594 wxRect logicalPaperRect
= GetLogicalPaperRect();
595 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
598 void wxPrintout::FitThisSizeToPage(const wxSize
& imageSize
)
600 // Set the DC scale and origin so that the given image size fits within the
601 // printable area of the page and the origin is at the top left corner of
602 // the printable area.
603 if (!m_printoutDC
) return;
605 m_printoutDC
->GetSize(&w
, &h
);
606 float scaleX
= float(w
) / imageSize
.x
;
607 float scaleY
= float(h
) / imageSize
.y
;
608 float actualScale
= wxMin(scaleX
, scaleY
);
609 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
610 m_printoutDC
->SetDeviceOrigin(0, 0);
613 void wxPrintout::FitThisSizeToPageMargins(const wxSize
& imageSize
, const wxPageSetupDialogData
& pageSetupData
)
615 // Set the DC scale and origin so that the given image size fits within the
616 // page margins defined in the given wxPageSetupDialogData object and the
617 // origin is at the top left corner of the page margins.
618 if (!m_printoutDC
) return;
619 wxRect paperRect
= GetPaperRectPixels();
621 GetPageSizePixels(&pw
, &ph
);
622 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
623 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
625 GetPageSizeMM(&mw
, &mh
);
626 float mmToDeviceX
= float(pw
) / mw
;
627 float mmToDeviceY
= float(ph
) / mh
;
628 wxRect
pageMarginsRect(paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
629 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
630 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
631 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
633 m_printoutDC
->GetSize(&w
, &h
);
634 float scaleX
= (float(pageMarginsRect
.width
) * w
) / (float(pw
) * imageSize
.x
);
635 float scaleY
= (float(pageMarginsRect
.height
) * h
) / (float(ph
) * imageSize
.y
);
636 float actualScale
= wxMin(scaleX
, scaleY
);
637 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
638 m_printoutDC
->SetDeviceOrigin(0, 0);
639 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
640 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
643 void wxPrintout::MapScreenSizeToPaper()
645 // Set the DC scale so that an image on the screen is the same size on the
646 // paper and the origin is at the top left of the paper. Note that with most
647 // printers, portions of the page will be cut off. Use this if you're
648 // managing your own page margins.
649 if (!m_printoutDC
) return;
650 MapScreenSizeToPage();
651 wxRect logicalPaperRect
= GetLogicalPaperRect();
652 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
655 void wxPrintout::MapScreenSizeToPage()
657 // Set the DC scale and origin so that an image on the screen is the same
658 // size on the paper and the origin is at the top left of the printable area.
659 if (!m_printoutDC
) return;
660 int ppiScreenX
, ppiScreenY
;
661 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
662 int ppiPrinterX
, ppiPrinterY
;
663 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
665 m_printoutDC
->GetSize(&w
, &h
);
666 int pageSizePixelsX
, pageSizePixelsY
;
667 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
668 float userScaleX
= (float(ppiPrinterX
) * w
) / (float(ppiScreenX
) * pageSizePixelsX
);
669 float userScaleY
= (float(ppiPrinterY
) * h
) / (float(ppiScreenY
) * pageSizePixelsY
);
670 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
671 m_printoutDC
->SetDeviceOrigin(0, 0);
674 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData
& pageSetupData
)
676 // Set the DC scale so that an image on the screen is the same size on the
677 // paper and the origin is at the top left of the page margins defined by
678 // the given wxPageSetupDialogData object.
679 if (!m_printoutDC
) return;
680 MapScreenSizeToPage();
681 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
682 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
685 void wxPrintout::MapScreenSizeToDevice()
687 // Set the DC scale so that a screen pixel is the same size as a device
688 // pixel and the origin is at the top left of the printable area.
689 if (!m_printoutDC
) return;
691 m_printoutDC
->GetSize(&w
, &h
);
692 int pageSizePixelsX
, pageSizePixelsY
;
693 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
694 float userScaleX
= float(w
) / pageSizePixelsX
;
695 float userScaleY
= float(h
) / pageSizePixelsY
;
696 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
697 m_printoutDC
->SetDeviceOrigin(0, 0);
700 wxRect
wxPrintout::GetLogicalPaperRect() const
702 // Return the rectangle in logical units that corresponds to the paper
704 wxRect paperRect
= GetPaperRectPixels();
706 GetPageSizePixels(&pw
, &ph
);
708 m_printoutDC
->GetSize(&w
, &h
);
709 if (w
== pw
&& h
== ph
) {
710 // this DC matches the printed page, so no scaling
711 return wxRect(m_printoutDC
->DeviceToLogicalX(paperRect
.x
),
712 m_printoutDC
->DeviceToLogicalY(paperRect
.y
),
713 m_printoutDC
->DeviceToLogicalXRel(paperRect
.width
),
714 m_printoutDC
->DeviceToLogicalYRel(paperRect
.height
));
716 // This DC doesn't match the printed page, so we have to scale.
717 float scaleX
= float(w
) / pw
;
718 float scaleY
= float(h
) / ph
;
719 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(paperRect
.x
* scaleX
)),
720 m_printoutDC
->DeviceToLogicalY(wxRound(paperRect
.y
* scaleY
)),
721 m_printoutDC
->DeviceToLogicalXRel(wxRound(paperRect
.width
* scaleX
)),
722 m_printoutDC
->DeviceToLogicalYRel(wxRound(paperRect
.height
* scaleY
)));
725 wxRect
wxPrintout::GetLogicalPageRect() const
727 // Return the rectangle in logical units that corresponds to the printable
730 m_printoutDC
->GetSize(&w
, &h
);
731 return wxRect(m_printoutDC
->DeviceToLogicalX(0),
732 m_printoutDC
->DeviceToLogicalY(0),
733 m_printoutDC
->DeviceToLogicalXRel(w
),
734 m_printoutDC
->DeviceToLogicalYRel(h
));
737 wxRect
wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData
& pageSetupData
) const
739 // Return the rectangle in logical units that corresponds to the region
740 // within the page margins as specified by the given wxPageSetupDialogData
743 // We get the paper size in device units and the margins in mm,
744 // so we need to calculate the conversion with this trick
746 GetPageSizePixels(&pw
, &ph
);
748 GetPageSizeMM(&mw
, &mh
);
749 float mmToDeviceX
= float(pw
) / mw
;
750 float mmToDeviceY
= float(ph
) / mh
;
752 // paper size in device units
753 wxRect paperRect
= GetPaperRectPixels();
756 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
757 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
759 // calculate margins in device units
760 wxRect
pageMarginsRect(
761 paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
762 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
763 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
764 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
767 m_printoutDC
->GetSize(&w
, &h
);
768 if (w
== pw
&& h
== ph
)
770 // this DC matches the printed page, so no scaling
772 m_printoutDC
->DeviceToLogicalX(pageMarginsRect
.x
),
773 m_printoutDC
->DeviceToLogicalY(pageMarginsRect
.y
),
774 m_printoutDC
->DeviceToLogicalXRel(pageMarginsRect
.width
),
775 m_printoutDC
->DeviceToLogicalYRel(pageMarginsRect
.height
));
778 // This DC doesn't match the printed page, so we have to scale.
779 float scaleX
= float(w
) / pw
;
780 float scaleY
= float(h
) / ph
;
781 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(pageMarginsRect
.x
* scaleX
)),
782 m_printoutDC
->DeviceToLogicalY(wxRound(pageMarginsRect
.y
* scaleY
)),
783 m_printoutDC
->DeviceToLogicalXRel(wxRound(pageMarginsRect
.width
* scaleX
)),
784 m_printoutDC
->DeviceToLogicalYRel(wxRound(pageMarginsRect
.height
* scaleY
)));
787 void wxPrintout::SetLogicalOrigin(wxCoord x
, wxCoord y
)
789 // Set the device origin by specifying a point in logical coordinates.
790 m_printoutDC
->SetDeviceOrigin(
791 m_printoutDC
->LogicalToDeviceX(x
),
792 m_printoutDC
->LogicalToDeviceY(y
) );
795 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff
, wxCoord yoff
)
797 // Offset the device origin by a specified distance in device coordinates.
798 wxPoint dev_org
= m_printoutDC
->GetDeviceOrigin();
799 m_printoutDC
->SetDeviceOrigin(
800 dev_org
.x
+ m_printoutDC
->LogicalToDeviceXRel(xoff
),
801 dev_org
.y
+ m_printoutDC
->LogicalToDeviceYRel(yoff
) );
805 //----------------------------------------------------------------------------
807 //----------------------------------------------------------------------------
809 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
811 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
812 EVT_PAINT(wxPreviewCanvas::OnPaint
)
813 EVT_CHAR(wxPreviewCanvas::OnChar
)
814 EVT_IDLE(wxPreviewCanvas::OnIdle
)
815 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
817 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel
)
821 // VZ: the current code doesn't refresh properly without
822 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
823 // really horrible flicker when resizing the preview frame, but without
824 // this style it simply doesn't work correctly at all...
825 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
826 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
827 wxScrolledWindow(parent
, wxID_ANY
, pos
, size
, style
| wxFULL_REPAINT_ON_RESIZE
, name
)
829 m_printPreview
= preview
;
831 // The app workspace colour is always white, but we should have
832 // a contrast with the page.
833 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
834 #elif defined(__WXGTK__)
835 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
837 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
839 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
841 SetScrollbars(10, 10, 100, 100);
844 wxPreviewCanvas::~wxPreviewCanvas()
848 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
855 if (!GetUpdateRegion().IsEmpty())
856 dc.SetClippingRegion( GetUpdateRegion() );
862 m_printPreview
->PaintPage(this, dc
);
866 void wxPreviewCanvas::OnIdle(wxIdleEvent
& event
)
870 // prevent UpdatePageRendering() from being called recursively:
871 static bool s_inIdle
= false;
876 if ( m_printPreview
)
878 if ( m_printPreview
->UpdatePageRendering() )
885 // Responds to colour changes, and passes event on to children.
886 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
889 // The app workspace colour is always white, but we should have
890 // a contrast with the page.
891 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
892 #elif defined(__WXGTK__)
893 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
895 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
897 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
900 // Propagate the event to the non-top-level children
901 wxWindow::OnSysColourChanged(event
);
904 void wxPreviewCanvas::OnChar(wxKeyEvent
&event
)
906 wxPreviewControlBar
* controlBar
= ((wxPreviewFrame
*) GetParent())->GetControlBar();
907 switch (event
.GetKeyCode())
910 controlBar
->OnPrint();
915 controlBar
->DoZoomIn();
918 case WXK_NUMPAD_SUBTRACT
:
920 controlBar
->DoZoomOut();
924 if (!event
.ControlDown())
930 switch(event
.GetKeyCode())
933 controlBar
->OnNext(); break;
935 controlBar
->OnPrevious(); break;
937 controlBar
->OnFirst(); break;
939 controlBar
->OnLast(); break;
947 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent
& event
)
949 wxPreviewControlBar
*
950 controlBar
= wxStaticCast(GetParent(), wxPreviewFrame
)->GetControlBar();
954 if ( event
.ControlDown() && event
.GetWheelRotation() != 0 )
956 int currentZoom
= controlBar
->GetZoomControl();
959 if ( currentZoom
< 100 )
961 else if ( currentZoom
<= 120 )
966 if ( event
.GetWheelRotation() > 0 )
969 int newZoom
= currentZoom
+ delta
;
974 if ( newZoom
!= currentZoom
)
976 controlBar
->SetZoomControl(newZoom
);
977 m_printPreview
->SetZoom(newZoom
);
987 #endif // wxUSE_MOUSEWHEEL
989 // ----------------------------------------------------------------------------
990 // wxPrintPageTextCtrl
991 // ----------------------------------------------------------------------------
993 // This text control contains the page number in the interval specified during
994 // its construction. Invalid pages are not accepted and the control contents is
995 // validated when it loses focus. Conversely, if the user changes the page to
996 // another valid one or presses Enter, OnGotoPage() method of the preview object
998 class wxPrintPageTextCtrl
: public wxTextCtrl
1001 wxPrintPageTextCtrl(wxPreviewControlBar
*preview
, int minPage
, int maxPage
)
1002 : wxTextCtrl(preview
,
1004 PageAsString(minPage
),
1006 // We use hardcoded 99999 for the width instead of fitting
1007 // it to the values we can show because the control looks
1008 // uncomfortably narrow if the real page number is just
1009 // one or two digits.
1010 wxSize(preview
->GetTextExtent("99999").x
, wxDefaultCoord
),
1012 #if wxUSE_VALIDATORS
1013 , wxTextValidator(wxFILTER_DIGITS
)
1014 #endif // wxUSE_VALIDATORS
1022 Connect(wxEVT_KILL_FOCUS
,
1023 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus
));
1024 Connect(wxEVT_COMMAND_TEXT_ENTER
,
1025 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter
));
1028 // Helpers to conveniently set or get the current page number. Return value
1029 // is 0 if the current controls contents is invalid.
1030 void SetPageNumber(int page
)
1032 wxASSERT( IsValidPage(page
) );
1034 SetValue(PageAsString(page
));
1037 int GetPageNumber() const
1040 if ( !GetValue().ToLong(&value
) || !IsValidPage(value
) )
1043 // Cast is safe because the value is less than (int) m_maxPage.
1044 return static_cast<int>(value
);
1048 static wxString
PageAsString(int page
)
1050 return wxString::Format("%d", page
);
1053 bool IsValidPage(int page
) const
1055 return page
>= m_minPage
&& page
<= m_maxPage
;
1060 const int page
= GetPageNumber();
1065 if ( page
!= m_page
)
1067 // We have a valid page, remember it.
1070 // And notify the owner about the change.
1071 m_preview
->OnGotoPage();
1073 //else: Nothing really changed.
1078 void OnKillFocus(wxFocusEvent
& event
)
1080 if ( !DoChangePage() )
1082 // The current contents is invalid so reset it back to the last
1083 // known good page index.
1084 SetPageNumber(m_page
);
1090 void OnTextEnter(wxCommandEvent
& WXUNUSED(event
))
1096 wxPreviewControlBar
* const m_preview
;
1098 const int m_minPage
,
1101 // This is the last valid page value that we had, we revert to it if an
1102 // invalid page is entered.
1105 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl
);
1108 //----------------------------------------------------------------------------
1109 // wxPreviewControlBar
1110 //----------------------------------------------------------------------------
1112 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
1114 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
1115 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
1116 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrintButton
)
1117 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
1118 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
1119 EVT_BUTTON(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnFirstButton
)
1120 EVT_BUTTON(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnLastButton
)
1121 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnZoomInButton
)
1122 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnZoomOutButton
)
1124 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnUpdatePreviousButton
)
1125 EVT_UPDATE_UI(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnUpdateNextButton
)
1126 EVT_UPDATE_UI(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnUpdateFirstButton
)
1127 EVT_UPDATE_UI(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnUpdateLastButton
)
1128 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnUpdateZoomInButton
)
1129 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnUpdateZoomOutButton
)
1131 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoomChoice
)
1132 EVT_PAINT(wxPreviewControlBar::OnPaint
)
1136 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
1137 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
1138 long style
, const wxString
& name
):
1139 wxPanel(parent
, wxID_ANY
, pos
, size
, style
, name
)
1141 m_printPreview
= preview
;
1142 m_closeButton
= NULL
;
1143 m_zoomControl
= NULL
;
1144 m_currentPageText
= NULL
;
1145 m_buttonFlags
= buttons
;
1148 wxPreviewControlBar::~wxPreviewControlBar()
1152 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1158 dc
.SetPen(*wxBLACK_PEN
);
1159 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1160 dc
.DrawLine( 0, h
-1, w
, h
-1 );
1163 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
1165 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
1169 void wxPreviewControlBar::OnPrint(void)
1171 wxPrintPreviewBase
*preview
= GetPrintPreview();
1172 preview
->Print(true);
1175 void wxPreviewControlBar::OnNext()
1177 if ( IsNextEnabled() )
1178 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1181 void wxPreviewControlBar::OnPrevious()
1183 if ( IsPreviousEnabled() )
1184 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1187 void wxPreviewControlBar::OnFirst()
1189 if ( IsFirstEnabled() )
1190 DoGotoPage(GetPrintPreview()->GetMinPage());
1193 void wxPreviewControlBar::OnLast()
1195 if ( IsLastEnabled() )
1196 DoGotoPage(GetPrintPreview()->GetMaxPage());
1199 bool wxPreviewControlBar::IsNextEnabled() const
1201 wxPrintPreviewBase
*preview
= GetPrintPreview();
1205 const int currentPage
= preview
->GetCurrentPage();
1206 return currentPage
< preview
->GetMaxPage() &&
1207 preview
->GetPrintout()->HasPage(currentPage
+ 1);
1210 bool wxPreviewControlBar::IsPreviousEnabled() const
1212 wxPrintPreviewBase
*preview
= GetPrintPreview();
1216 const int currentPage
= preview
->GetCurrentPage();
1217 return currentPage
> preview
->GetMinPage() &&
1218 preview
->GetPrintout()->HasPage(currentPage
- 1);
1221 bool wxPreviewControlBar::IsFirstEnabled() const
1223 wxPrintPreviewBase
*preview
= GetPrintPreview();
1227 return preview
->GetPrintout()->HasPage(preview
->GetMinPage());
1230 bool wxPreviewControlBar::IsLastEnabled() const
1232 wxPrintPreviewBase
*preview
= GetPrintPreview();
1236 return preview
->GetPrintout()->HasPage(preview
->GetMaxPage());
1239 void wxPreviewControlBar::DoGotoPage(int page
)
1241 wxPrintPreviewBase
*preview
= GetPrintPreview();
1242 wxCHECK_RET( preview
, "Shouldn't be called if there is no preview." );
1244 preview
->SetCurrentPage(page
);
1246 if ( m_currentPageText
)
1247 m_currentPageText
->SetPageNumber(page
);
1250 void wxPreviewControlBar::OnGotoPage()
1252 wxPrintPreviewBase
*preview
= GetPrintPreview();
1255 if (preview
->GetMinPage() > 0)
1257 long currentPage
= m_currentPageText
->GetPageNumber();
1260 if (preview
->GetPrintout()->HasPage(currentPage
))
1262 preview
->SetCurrentPage(currentPage
);
1269 void wxPreviewControlBar::DoZoom()
1271 int zoom
= GetZoomControl();
1272 if (GetPrintPreview())
1273 GetPrintPreview()->SetZoom(zoom
);
1276 bool wxPreviewControlBar::IsZoomInEnabled() const
1278 if ( !m_zoomControl
)
1281 const unsigned sel
= m_zoomControl
->GetSelection();
1282 return sel
< m_zoomControl
->GetCount() - 1;
1285 bool wxPreviewControlBar::IsZoomOutEnabled() const
1287 return m_zoomControl
&& m_zoomControl
->GetSelection() > 0;
1290 void wxPreviewControlBar::DoZoomIn()
1292 if (IsZoomInEnabled())
1294 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() + 1);
1299 void wxPreviewControlBar::DoZoomOut()
1301 if (IsZoomOutEnabled())
1303 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() - 1);
1311 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1312 // sequentially to it in the simplest way possible.
1313 class SizerWithButtons
1316 // Constructor creates the sizer that will hold the buttons and stores the
1317 // parent that will be used for their creation.
1318 SizerWithButtons(wxWindow
*parent
)
1319 : m_sizer(new wxBoxSizer(wxHORIZONTAL
)),
1323 m_needsSeparator
= false;
1326 // Destructor associates the sizer with the parent window.
1329 m_parent
->SetSizer(m_sizer
);
1330 m_sizer
->Fit(m_parent
);
1334 // Add an arbitrary window to the sizer.
1335 void Add(wxWindow
*win
)
1337 if ( m_needsSeparator
)
1339 m_needsSeparator
= false;
1341 m_sizer
->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1344 m_hasContents
= true;
1347 wxSizerFlags().Border(wxLEFT
| wxTOP
| wxBOTTOM
).Center());
1350 // Add a button with the specified id, bitmap and tooltip.
1351 void AddButton(wxWindowID btnId
,
1352 const wxArtID
& artId
,
1353 const wxString
& tooltip
)
1355 // We don't use (smaller) images inside a button with a text label but
1356 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1357 // wxART_BUTTON here.
1358 wxBitmap bmp
= wxArtProvider::GetBitmap(artId
, wxART_TOOLBAR
);
1359 wxBitmapButton
* const btn
= new wxBitmapButton(m_parent
, btnId
, bmp
);
1360 btn
->SetToolTip(tooltip
);
1365 // Add a control at the right end of the window. This should be called last
1366 // as everything else added after it will be added on the right side too.
1367 void AddAtEnd(wxWindow
*win
)
1369 m_sizer
->AddStretchSpacer();
1371 wxSizerFlags().Border(wxTOP
| wxBOTTOM
| wxRIGHT
).Center());
1374 // Indicates the end of a group of buttons, a separator will be added after
1378 if ( m_hasContents
)
1380 m_needsSeparator
= true;
1381 m_hasContents
= false;
1386 wxSizer
* const m_sizer
;
1387 wxWindow
* const m_parent
;
1389 // If true, we have some controls since the last group beginning. This is
1390 // used to avoid inserting two consecutive separators if EndOfGroup() is
1394 // If true, a separator should be inserted before adding the next button.
1395 bool m_needsSeparator
;
1397 wxDECLARE_NO_COPY_CLASS(SizerWithButtons
);
1400 } // anonymous namespace
1402 void wxPreviewControlBar::CreateButtons()
1404 SizerWithButtons
sizer(this);
1406 // Print button group (a single button).
1407 if (m_buttonFlags
& wxPREVIEW_PRINT
)
1409 sizer
.AddButton(wxID_PREVIEW_PRINT
, wxART_PRINT
, _("Print"));
1413 // Page selection buttons group.
1414 if (m_buttonFlags
& wxPREVIEW_FIRST
)
1416 sizer
.AddButton(wxID_PREVIEW_FIRST
, wxART_GOTO_FIRST
, _("First page"));
1419 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
1421 sizer
.AddButton(wxID_PREVIEW_PREVIOUS
, wxART_GO_BACK
, _("Previous page"));
1424 if (m_buttonFlags
& wxPREVIEW_GOTO
)
1426 int minPage
, maxPage
, pageFrom
, pageTo
;
1427 m_printPreview
->GetPrintout()->GetPageInfo(&minPage
, &maxPage
,
1428 &pageFrom
, &pageTo
);
1430 m_currentPageText
= new wxPrintPageTextCtrl(this, minPage
, maxPage
);
1431 sizer
.Add(m_currentPageText
);
1434 maxPageText
= new wxStaticText(this, wxID_ANY
,
1435 wxString::Format("/ %d", maxPage
));
1437 sizer
.Add(maxPageText
);
1440 if (m_buttonFlags
& wxPREVIEW_NEXT
)
1442 sizer
.AddButton(wxID_PREVIEW_NEXT
, wxART_GO_FORWARD
, _("Next page"));
1445 if (m_buttonFlags
& wxPREVIEW_LAST
)
1447 sizer
.AddButton(wxID_PREVIEW_LAST
, wxART_GOTO_LAST
, _("Last page"));
1452 // Zoom controls group.
1453 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
1455 sizer
.AddButton(wxID_PREVIEW_ZOOM_OUT
, wxART_MINUS
, _("Zoom Out"));
1457 wxString choices
[] =
1459 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1460 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1461 wxT("120%"), wxT("150%"), wxT("200%")
1463 int n
= WXSIZEOF(choices
);
1465 m_zoomControl
= new wxChoice( this, wxID_PREVIEW_ZOOM
, wxDefaultPosition
, wxSize(70,wxDefaultCoord
), n
, choices
, 0 );
1466 sizer
.Add(m_zoomControl
);
1467 SetZoomControl(m_printPreview
->GetZoom());
1469 sizer
.AddButton(wxID_PREVIEW_ZOOM_IN
, wxART_PLUS
, _("Zoom In"));
1474 // Close button group (single button again).
1475 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("&Close"));
1476 sizer
.AddAtEnd(m_closeButton
);
1479 void wxPreviewControlBar::SetZoomControl(int zoom
)
1483 int n
, count
= m_zoomControl
->GetCount();
1485 for (n
=0; n
<count
; n
++)
1487 if (m_zoomControl
->GetString(n
).BeforeFirst(wxT('%')).ToLong(&val
) &&
1488 (val
>= long(zoom
)))
1490 m_zoomControl
->SetSelection(n
);
1495 m_zoomControl
->SetSelection(count
-1);
1499 int wxPreviewControlBar::GetZoomControl()
1501 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxEmptyString
))
1504 if (m_zoomControl
->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val
))
1516 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
1518 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
1519 EVT_CHAR_HOOK(wxPreviewFrame::OnChar
)
1520 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
1523 void wxPreviewFrame::OnChar(wxKeyEvent
&event
)
1525 if ( event
.GetKeyCode() == WXK_ESCAPE
)
1535 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxWindow
*parent
, const wxString
& title
,
1536 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
1537 wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
, name
)
1539 m_printPreview
= preview
;
1540 m_controlBar
= NULL
;
1541 m_previewCanvas
= NULL
;
1542 m_windowDisabler
= NULL
;
1544 // Give the application icon
1546 wxFrame
* topFrame
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
1548 SetIcons(topFrame
->GetIcons());
1552 wxPreviewFrame::~wxPreviewFrame()
1556 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
1558 if (m_windowDisabler
)
1559 delete m_windowDisabler
;
1561 // Need to delete the printout and the print preview
1562 wxPrintout
*printout
= m_printPreview
->GetPrintout();
1566 m_printPreview
->SetPrintout(NULL
);
1567 m_printPreview
->SetCanvas(NULL
);
1568 m_printPreview
->SetFrame(NULL
);
1571 m_previewCanvas
->SetPreview(NULL
);
1572 wxDELETE(m_printPreview
);
1577 void wxPreviewFrame::Initialize()
1585 m_printPreview
->SetCanvas(m_previewCanvas
);
1586 m_printPreview
->SetFrame(this);
1588 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
1590 item0
->Add( m_controlBar
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1591 item0
->Add( m_previewCanvas
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1593 SetAutoLayout( true );
1596 m_windowDisabler
= new wxWindowDisabler(this);
1600 m_printPreview
->AdjustScrollbars(m_previewCanvas
);
1601 m_previewCanvas
->SetFocus();
1602 m_controlBar
->SetFocus();
1605 void wxPreviewFrame::CreateCanvas()
1607 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
1610 void wxPreviewFrame::CreateControlBar()
1612 long buttons
= wxPREVIEW_DEFAULT
;
1613 if (m_printPreview
->GetPrintoutForPrinting())
1614 buttons
|= wxPREVIEW_PRINT
;
1616 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this);
1617 m_controlBar
->CreateButtons();
1624 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
1626 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1627 wxPrintout
*printoutForPrinting
,
1631 m_printDialogData
= (*data
);
1633 Init(printout
, printoutForPrinting
);
1636 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1637 wxPrintout
*printoutForPrinting
,
1638 wxPrintDialogData
*data
)
1641 m_printDialogData
= (*data
);
1643 Init(printout
, printoutForPrinting
);
1646 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
1647 wxPrintout
*printoutForPrinting
)
1650 m_previewPrintout
= printout
;
1651 if (m_previewPrintout
)
1652 m_previewPrintout
->SetPreview(static_cast<wxPrintPreview
*>(this));
1654 m_printPrintout
= printoutForPrinting
;
1656 m_previewCanvas
= NULL
;
1657 m_previewFrame
= NULL
;
1658 m_previewBitmap
= NULL
;
1659 m_previewFailed
= false;
1663 m_leftMargin
= 2*wxSizerFlags::GetDefaultBorder();
1666 m_printingPrepared
= false;
1671 wxPrintPreviewBase::~wxPrintPreviewBase()
1673 if (m_previewPrintout
)
1674 delete m_previewPrintout
;
1675 if (m_previewBitmap
)
1676 delete m_previewBitmap
;
1677 if (m_printPrintout
)
1678 delete m_printPrintout
;
1681 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
1683 if (m_currentPage
== pageNum
)
1686 m_currentPage
= pageNum
;
1688 InvalidatePreviewBitmap();
1690 if (m_previewCanvas
)
1692 AdjustScrollbars(m_previewCanvas
);
1694 m_previewCanvas
->Refresh();
1695 m_previewCanvas
->SetFocus();
1700 int wxPrintPreviewBase::GetCurrentPage() const
1701 { return m_currentPage
; }
1702 void wxPrintPreviewBase::SetPrintout(wxPrintout
*printout
)
1703 { m_previewPrintout
= printout
; }
1704 wxPrintout
*wxPrintPreviewBase::GetPrintout() const
1705 { return m_previewPrintout
; }
1706 wxPrintout
*wxPrintPreviewBase::GetPrintoutForPrinting() const
1707 { return m_printPrintout
; }
1708 void wxPrintPreviewBase::SetFrame(wxFrame
*frame
)
1709 { m_previewFrame
= frame
; }
1710 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas
*canvas
)
1711 { m_previewCanvas
= canvas
; }
1712 wxFrame
*wxPrintPreviewBase::GetFrame() const
1713 { return m_previewFrame
; }
1714 wxPreviewCanvas
*wxPrintPreviewBase::GetCanvas() const
1715 { return m_previewCanvas
; }
1717 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas
*canvas
, wxRect
& pageRect
, wxRect
& paperRect
)
1719 // Calculate the rectangles for the printable area of the page and the
1720 // entire paper as they appear on the canvas on-screen.
1721 int canvasWidth
, canvasHeight
;
1722 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
1724 float zoomScale
= float(m_currentZoom
) / 100;
1725 float screenPrintableWidth
= zoomScale
* m_pageWidth
* m_previewScaleX
;
1726 float screenPrintableHeight
= zoomScale
* m_pageHeight
* m_previewScaleY
;
1728 wxRect devicePaperRect
= m_previewPrintout
->GetPaperRectPixels();
1729 wxCoord devicePrintableWidth
, devicePrintableHeight
;
1730 m_previewPrintout
->GetPageSizePixels(&devicePrintableWidth
, &devicePrintableHeight
);
1731 float scaleX
= screenPrintableWidth
/ devicePrintableWidth
;
1732 float scaleY
= screenPrintableHeight
/ devicePrintableHeight
;
1733 paperRect
.width
= wxCoord(scaleX
* devicePaperRect
.width
);
1734 paperRect
.height
= wxCoord(scaleY
* devicePaperRect
.height
);
1736 paperRect
.x
= wxCoord((canvasWidth
- paperRect
.width
)/ 2.0);
1737 if (paperRect
.x
< m_leftMargin
)
1738 paperRect
.x
= m_leftMargin
;
1739 paperRect
.y
= wxCoord((canvasHeight
- paperRect
.height
)/ 2.0);
1740 if (paperRect
.y
< m_topMargin
)
1741 paperRect
.y
= m_topMargin
;
1743 pageRect
.x
= paperRect
.x
- wxCoord(scaleX
* devicePaperRect
.x
);
1744 pageRect
.y
= paperRect
.y
- wxCoord(scaleY
* devicePaperRect
.y
);
1745 pageRect
.width
= wxCoord(screenPrintableWidth
);
1746 pageRect
.height
= wxCoord(screenPrintableHeight
);
1750 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1752 wxDELETE(m_previewBitmap
);
1753 // if there was a problem with rendering the preview, try again now
1754 // that it changed in some way (less memory may be needed, for example):
1755 m_previewFailed
= false;
1758 bool wxPrintPreviewBase::UpdatePageRendering()
1760 if ( m_previewBitmap
)
1763 if ( m_previewFailed
)
1766 if ( !RenderPage(m_currentPage
) )
1768 m_previewFailed
= true; // don't waste time failing again
1775 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1777 DrawBlankPage(canvas
, dc
);
1779 if (!m_previewBitmap
)
1784 wxRect pageRect
, paperRect
;
1785 CalcRects(canvas
, pageRect
, paperRect
);
1787 temp_dc
.SelectObject(*m_previewBitmap
);
1789 dc
.Blit(pageRect
.x
, pageRect
.y
,
1790 m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
1792 temp_dc
.SelectObject(wxNullBitmap
);
1796 // Adjusts the scrollbars for the current scale
1797 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas
*canvas
)
1802 wxRect pageRect
, paperRect
;
1803 CalcRects(canvas
, pageRect
, paperRect
);
1804 int totalWidth
= paperRect
.width
+ 2 * m_leftMargin
;
1805 int totalHeight
= paperRect
.height
+ 2 * m_topMargin
;
1806 int scrollUnitsX
= totalWidth
/ 10;
1807 int scrollUnitsY
= totalHeight
/ 10;
1808 wxSize virtualSize
= canvas
->GetVirtualSize();
1809 if (virtualSize
.GetWidth() != totalWidth
|| virtualSize
.GetHeight() != totalHeight
)
1810 canvas
->SetScrollbars(10, 10, scrollUnitsX
, scrollUnitsY
, 0, 0, true);
1813 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC
& dc
, int pageNum
)
1815 m_previewPrintout
->SetDC(&dc
);
1816 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
1818 // Need to delay OnPreparePrinting() until here, so we have enough
1820 if (!m_printingPrepared
)
1822 m_previewPrintout
->OnPreparePrinting();
1824 m_previewPrintout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
1825 m_printingPrepared
= true;
1828 m_previewPrintout
->OnBeginPrinting();
1830 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
1832 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
1836 m_previewPrintout
->OnPrintPage(pageNum
);
1837 m_previewPrintout
->OnEndDocument();
1838 m_previewPrintout
->OnEndPrinting();
1840 m_previewPrintout
->SetDC(NULL
);
1845 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap
& bmp
, int pageNum
)
1847 wxMemoryDC memoryDC
;
1848 memoryDC
.SelectObject(bmp
);
1851 return RenderPageIntoDC(memoryDC
, pageNum
);
1854 bool wxPrintPreviewBase::RenderPage(int pageNum
)
1858 if (!m_previewCanvas
)
1860 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1864 wxRect pageRect
, paperRect
;
1865 CalcRects(m_previewCanvas
, pageRect
, paperRect
);
1867 if (!m_previewBitmap
)
1869 m_previewBitmap
= new wxBitmap(pageRect
.width
, pageRect
.height
);
1871 if (!m_previewBitmap
|| !m_previewBitmap
->Ok())
1873 InvalidatePreviewBitmap();
1874 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
1879 if ( !RenderPageIntoBitmap(*m_previewBitmap
, pageNum
) )
1881 InvalidatePreviewBitmap();
1882 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
1889 status
= wxString::Format(_("Page %d of %d"), pageNum
, m_maxPage
);
1891 status
= wxString::Format(_("Page %d"), pageNum
);
1894 m_previewFrame
->SetStatusText(status
);
1900 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1902 wxRect pageRect
, paperRect
;
1904 CalcRects(canvas
, pageRect
, paperRect
);
1906 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
1907 wxCoord shadowOffset
= 4;
1909 dc
.SetPen(*wxBLACK_PEN
);
1910 dc
.SetBrush(*wxBLACK_BRUSH
);
1911 dc
.DrawRectangle(paperRect
.x
+ shadowOffset
, paperRect
.y
+ paperRect
.height
+ 1,
1912 paperRect
.width
, shadowOffset
);
1914 dc
.DrawRectangle(paperRect
.x
+ paperRect
.width
, paperRect
.y
+ shadowOffset
,
1915 shadowOffset
, paperRect
.height
);
1917 // Draw blank page allowing for 1-pixel border AROUND the actual paper
1918 dc
.SetPen(*wxBLACK_PEN
);
1919 dc
.SetBrush(*wxWHITE_BRUSH
);
1920 dc
.DrawRectangle(paperRect
.x
- 2, paperRect
.y
- 1,
1921 paperRect
.width
+ 3, paperRect
.height
+ 2);
1926 void wxPrintPreviewBase::SetZoom(int percent
)
1928 if (m_currentZoom
== percent
)
1931 m_currentZoom
= percent
;
1933 InvalidatePreviewBitmap();
1935 if (m_previewCanvas
)
1937 AdjustScrollbars(m_previewCanvas
);
1938 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
1939 m_previewCanvas
->ClearBackground();
1940 m_previewCanvas
->Refresh();
1941 m_previewCanvas
->SetFocus();
1945 wxPrintDialogData
& wxPrintPreviewBase::GetPrintDialogData()
1947 return m_printDialogData
;
1950 int wxPrintPreviewBase::GetZoom() const
1951 { return m_currentZoom
; }
1952 int wxPrintPreviewBase::GetMaxPage() const
1953 { return m_maxPage
; }
1954 int wxPrintPreviewBase::GetMinPage() const
1955 { return m_minPage
; }
1956 bool wxPrintPreviewBase::IsOk() const
1958 void wxPrintPreviewBase::SetOk(bool ok
)
1961 //----------------------------------------------------------------------------
1963 //----------------------------------------------------------------------------
1965 IMPLEMENT_CLASS(wxPrintPreview
, wxPrintPreviewBase
)
1967 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
1968 wxPrintout
*printoutForPrinting
,
1969 wxPrintDialogData
*data
) :
1970 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
1972 m_pimpl
= wxPrintFactory::GetFactory()->
1973 CreatePrintPreview( printout
, printoutForPrinting
, data
);
1976 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
1977 wxPrintout
*printoutForPrinting
,
1978 wxPrintData
*data
) :
1979 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
1981 m_pimpl
= wxPrintFactory::GetFactory()->
1982 CreatePrintPreview( printout
, printoutForPrinting
, data
);
1985 wxPrintPreview::~wxPrintPreview()
1989 // don't delete twice
1990 m_printPrintout
= NULL
;
1991 m_previewPrintout
= NULL
;
1992 m_previewBitmap
= NULL
;
1995 bool wxPrintPreview::SetCurrentPage(int pageNum
)
1997 return m_pimpl
->SetCurrentPage( pageNum
);
2000 int wxPrintPreview::GetCurrentPage() const
2002 return m_pimpl
->GetCurrentPage();
2005 void wxPrintPreview::SetPrintout(wxPrintout
*printout
)
2007 m_pimpl
->SetPrintout( printout
);
2010 wxPrintout
*wxPrintPreview::GetPrintout() const
2012 return m_pimpl
->GetPrintout();
2015 wxPrintout
*wxPrintPreview::GetPrintoutForPrinting() const
2017 return m_pimpl
->GetPrintoutForPrinting();
2020 void wxPrintPreview::SetFrame(wxFrame
*frame
)
2022 m_pimpl
->SetFrame( frame
);
2025 void wxPrintPreview::SetCanvas(wxPreviewCanvas
*canvas
)
2027 m_pimpl
->SetCanvas( canvas
);
2030 wxFrame
*wxPrintPreview::GetFrame() const
2032 return m_pimpl
->GetFrame();
2035 wxPreviewCanvas
*wxPrintPreview::GetCanvas() const
2037 return m_pimpl
->GetCanvas();
2040 bool wxPrintPreview::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2042 return m_pimpl
->PaintPage( canvas
, dc
);
2045 bool wxPrintPreview::UpdatePageRendering()
2047 return m_pimpl
->UpdatePageRendering();
2050 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2052 return m_pimpl
->DrawBlankPage( canvas
, dc
);
2055 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas
*canvas
)
2057 m_pimpl
->AdjustScrollbars( canvas
);
2060 bool wxPrintPreview::RenderPage(int pageNum
)
2062 return m_pimpl
->RenderPage( pageNum
);
2065 void wxPrintPreview::SetZoom(int percent
)
2067 m_pimpl
->SetZoom( percent
);
2070 int wxPrintPreview::GetZoom() const
2072 return m_pimpl
->GetZoom();
2075 wxPrintDialogData
& wxPrintPreview::GetPrintDialogData()
2077 return m_pimpl
->GetPrintDialogData();
2080 int wxPrintPreview::GetMaxPage() const
2082 return m_pimpl
->GetMaxPage();
2085 int wxPrintPreview::GetMinPage() const
2087 return m_pimpl
->GetMinPage();
2090 bool wxPrintPreview::IsOk() const
2092 return m_pimpl
->Ok();
2095 void wxPrintPreview::SetOk(bool ok
)
2097 m_pimpl
->SetOk( ok
);
2100 bool wxPrintPreview::Print(bool interactive
)
2102 return m_pimpl
->Print( interactive
);
2105 void wxPrintPreview::DetermineScaling()
2107 m_pimpl
->DetermineScaling();
2110 #endif // wxUSE_PRINTING_ARCHITECTURE