1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/prntbase.cpp
3 // Purpose: Printing framework base class implementation
4 // Author: Julian Smart
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
18 #if wxUSE_PRINTING_ARCHITECTURE
20 #include "wx/dcprint.h"
23 #if defined(__WXMSW__)
24 #include "wx/msw/wrapcdlg.h"
30 #include "wx/msgdlg.h"
31 #include "wx/layout.h"
32 #include "wx/choice.h"
33 #include "wx/button.h"
34 #include "wx/bmpbuttn.h"
35 #include "wx/settings.h"
36 #include "wx/dcmemory.h"
37 #include "wx/dcclient.h"
38 #include "wx/stattext.h"
40 #include "wx/textdlg.h"
42 #include "wx/module.h"
45 #include "wx/prntbase.h"
46 #include "wx/printdlg.h"
48 #include "wx/dcprint.h"
49 #include "wx/artprov.h"
54 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
55 #include "wx/msw/printdlg.h"
56 #include "wx/msw/dcprint.h"
57 #elif defined(__WXMAC__)
58 #include "wx/osx/printdlg.h"
59 #include "wx/osx/private/print.h"
60 #include "wx/osx/dcprint.h"
61 #elif defined(__WXPM__)
62 #include "wx/os2/dcprint.h"
63 #include "wx/generic/prntdlgg.h"
65 #include "wx/generic/prntdlgg.h"
75 //----------------------------------------------------------------------------
77 //----------------------------------------------------------------------------
79 wxPrintFactory
*wxPrintFactory::m_factory
= NULL
;
81 void wxPrintFactory::SetPrintFactory( wxPrintFactory
*factory
)
83 if (wxPrintFactory::m_factory
)
84 delete wxPrintFactory::m_factory
;
86 wxPrintFactory::m_factory
= factory
;
89 wxPrintFactory
*wxPrintFactory::GetFactory()
91 if (!wxPrintFactory::m_factory
)
92 wxPrintFactory::m_factory
= new wxNativePrintFactory
;
94 return wxPrintFactory::m_factory
;
97 //----------------------------------------------------------------------------
98 // wxNativePrintFactory
99 //----------------------------------------------------------------------------
101 wxPrinterBase
*wxNativePrintFactory::CreatePrinter( wxPrintDialogData
*data
)
103 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
104 return new wxWindowsPrinter( data
);
105 #elif defined(__WXMAC__)
106 return new wxMacPrinter( data
);
107 #elif defined(__WXPM__)
108 return new wxOS2Printer( data
);
110 return new wxPostScriptPrinter( data
);
114 wxPrintPreviewBase
*wxNativePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
115 wxPrintout
*printout
, wxPrintDialogData
*data
)
117 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
118 return new wxWindowsPrintPreview( preview
, printout
, data
);
119 #elif defined(__WXMAC__)
120 return new wxMacPrintPreview( preview
, printout
, data
);
121 #elif defined(__WXPM__)
122 return new wxOS2PrintPreview( preview
, printout
, data
);
124 return new wxPostScriptPrintPreview( preview
, printout
, data
);
128 wxPrintPreviewBase
*wxNativePrintFactory::CreatePrintPreview( wxPrintout
*preview
,
129 wxPrintout
*printout
, wxPrintData
*data
)
131 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
132 return new wxWindowsPrintPreview( preview
, printout
, data
);
133 #elif defined(__WXMAC__)
134 return new wxMacPrintPreview( preview
, printout
, data
);
135 #elif defined(__WXPM__)
136 return new wxOS2PrintPreview( preview
, printout
, data
);
138 return new wxPostScriptPrintPreview( preview
, printout
, data
);
142 wxPrintDialogBase
*wxNativePrintFactory::CreatePrintDialog( wxWindow
*parent
,
143 wxPrintDialogData
*data
)
145 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
146 return new wxWindowsPrintDialog( parent
, data
);
147 #elif defined(__WXMAC__)
148 return new wxMacPrintDialog( parent
, data
);
150 return new wxGenericPrintDialog( parent
, data
);
154 wxPrintDialogBase
*wxNativePrintFactory::CreatePrintDialog( wxWindow
*parent
,
157 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
158 return new wxWindowsPrintDialog( parent
, data
);
159 #elif defined(__WXMAC__)
160 return new wxMacPrintDialog( parent
, data
);
162 return new wxGenericPrintDialog( parent
, data
);
166 wxPageSetupDialogBase
*wxNativePrintFactory::CreatePageSetupDialog( wxWindow
*parent
,
167 wxPageSetupDialogData
*data
)
169 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
170 return new wxWindowsPageSetupDialog( parent
, data
);
171 #elif defined(__WXMAC__)
172 return new wxMacPageSetupDialog( parent
, data
);
174 return new wxGenericPageSetupDialog( parent
, data
);
178 bool wxNativePrintFactory::HasPrintSetupDialog()
180 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
182 #elif defined(__WXMAC__)
185 // Only here do we need to provide the print setup
186 // dialog ourselves, the other platforms either have
187 // none, don't make it accessible or let you configure
188 // the printer from the wxPrintDialog anyway.
194 wxDialog
*wxNativePrintFactory::CreatePrintSetupDialog( wxWindow
*parent
,
197 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
201 #elif defined(__WXMAC__)
206 // Only here do we need to provide the print setup
207 // dialog ourselves, the other platforms either have
208 // none, don't make it accessible or let you configure
209 // the printer from the wxPrintDialog anyway.
210 return new wxGenericPrintSetupDialog( parent
, data
);
214 wxDCImpl
* wxNativePrintFactory::CreatePrinterDCImpl( wxPrinterDC
*owner
, const wxPrintData
& data
)
216 #if defined(__WXGTK__) || defined(__WXMOTIF__) || ( defined(__WXUNIVERSAL__) && !defined(__WXMAC__) )
217 return new wxPostScriptDCImpl( owner
, data
);
219 return new wxPrinterDCImpl( owner
, data
);
223 bool wxNativePrintFactory::HasOwnPrintToFile()
225 // Only relevant for PostScript and here the
226 // setup dialog provides no "print to file"
227 // option. In the GNOME setup dialog, the
228 // setup dialog has its own print to file.
232 bool wxNativePrintFactory::HasPrinterLine()
234 // Only relevant for PostScript for now
238 wxString
wxNativePrintFactory::CreatePrinterLine()
240 // Only relevant for PostScript for now
242 // We should query "lpstat -d" here
243 return _("Generic PostScript");
246 bool wxNativePrintFactory::HasStatusLine()
248 // Only relevant for PostScript for now
252 wxString
wxNativePrintFactory::CreateStatusLine()
254 // Only relevant for PostScript for now
256 // We should query "lpstat -r" or "lpstat -p" here
260 wxPrintNativeDataBase
*wxNativePrintFactory::CreatePrintNativeData()
262 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
263 return new wxWindowsPrintNativeData
;
264 #elif defined(__WXMAC__)
265 return wxOSXCreatePrintData();
267 return new wxPostScriptPrintNativeData
;
271 //----------------------------------------------------------------------------
272 // wxPrintNativeDataBase
273 //----------------------------------------------------------------------------
275 IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase
, wxObject
)
277 wxPrintNativeDataBase::wxPrintNativeDataBase()
282 //----------------------------------------------------------------------------
283 // wxPrintFactoryModule
284 //----------------------------------------------------------------------------
286 class wxPrintFactoryModule
: public wxModule
289 wxPrintFactoryModule() {}
290 bool OnInit() { return true; }
291 void OnExit() { wxPrintFactory::SetPrintFactory( NULL
); }
294 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule
)
297 IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule
, wxModule
)
299 //----------------------------------------------------------------------------
301 //----------------------------------------------------------------------------
303 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
305 wxPrinterBase::wxPrinterBase(wxPrintDialogData
*data
)
307 m_currentPrintout
= NULL
;
308 sm_abortWindow
= NULL
;
311 m_printDialogData
= (*data
);
312 sm_lastError
= wxPRINTER_NO_ERROR
;
315 wxWindow
*wxPrinterBase::sm_abortWindow
= NULL
;
316 bool wxPrinterBase::sm_abortIt
= false;
317 wxPrinterError
wxPrinterBase::sm_lastError
= wxPRINTER_NO_ERROR
;
319 wxPrinterBase::~wxPrinterBase()
323 wxPrintAbortDialog
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
* printout
)
325 return new wxPrintAbortDialog(parent
, printout
->GetTitle());
328 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), const wxString
& message
)
330 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
333 wxPrintDialogData
& wxPrinterBase::GetPrintDialogData() const
335 return (wxPrintDialogData
&) m_printDialogData
;
338 //----------------------------------------------------------------------------
340 //----------------------------------------------------------------------------
342 IMPLEMENT_CLASS(wxPrinter
, wxPrinterBase
)
344 wxPrinter::wxPrinter(wxPrintDialogData
*data
)
346 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrinter( data
);
349 wxPrinter::~wxPrinter()
354 wxPrintAbortDialog
*wxPrinter::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*printout
)
356 return m_pimpl
->CreateAbortWindow( parent
, printout
);
359 void wxPrinter::ReportError(wxWindow
*parent
, wxPrintout
*printout
, const wxString
& message
)
361 m_pimpl
->ReportError( parent
, printout
, message
);
364 bool wxPrinter::Setup(wxWindow
*parent
)
366 return m_pimpl
->Setup( parent
);
369 bool wxPrinter::Print(wxWindow
*parent
, wxPrintout
*printout
, bool prompt
)
371 if ( !prompt
&& m_printDialogData
.GetToPage() == 0 )
373 // If the dialog is not shown, set the pages range to print everything
374 // by default (as otherwise we wouldn't print anything at all which is
375 // certainly not a reasonable default behaviour).
376 int minPage
, maxPage
, selFrom
, selTo
;
377 printout
->GetPageInfo(&minPage
, &maxPage
, &selFrom
, &selTo
);
379 wxPrintDialogData
& pdd
= m_pimpl
->GetPrintDialogData();
380 pdd
.SetFromPage(minPage
);
381 pdd
.SetToPage(maxPage
);
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 wxPrintAbortDialog::wxPrintAbortDialog(wxWindow
*parent
,
513 const wxString
& documentTitle
,
517 const wxString
& name
)
518 : wxDialog(parent
, wxID_ANY
, _("Printing"), pos
, size
, style
, name
)
520 wxBoxSizer
*mainSizer
= new wxBoxSizer(wxVERTICAL
);
521 mainSizer
->Add(new wxStaticText(this, wxID_ANY
, _("Please wait while printing...")),
522 wxSizerFlags().Expand().DoubleBorder());
524 wxFlexGridSizer
*gridSizer
= new wxFlexGridSizer(2, wxSize(20, 0));
525 gridSizer
->Add(new wxStaticText(this, wxID_ANY
, _("Document:")));
526 gridSizer
->AddGrowableCol(1);
527 gridSizer
->Add(new wxStaticText(this, wxID_ANY
, documentTitle
));
528 gridSizer
->Add(new wxStaticText(this, wxID_ANY
, _("Progress:")));
529 m_progress
= new wxStaticText(this, wxID_ANY
, _("Preparing"));
530 m_progress
->SetMinSize(wxSize(250, -1));
531 gridSizer
->Add(m_progress
);
532 mainSizer
->Add(gridSizer
, wxSizerFlags().Expand().DoubleBorder(wxLEFT
| wxRIGHT
));
534 mainSizer
->Add(CreateStdDialogButtonSizer(wxCANCEL
),
535 wxSizerFlags().Expand().DoubleBorder());
537 SetSizerAndFit(mainSizer
);
540 void wxPrintAbortDialog::SetProgress(int currentPage
, int totalPages
,
541 int currentCopy
, int totalCopies
)
544 text
.Printf(_("Printing page %d of %d"), currentPage
, totalPages
);
545 if ( totalCopies
> 1 )
546 text
+= wxString::Format(_(" (copy %d of %d)"), currentCopy
, totalCopies
);
547 m_progress
->SetLabel(text
);
550 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
552 wxCHECK_RET( wxPrinterBase::sm_abortWindow
!= NULL
, "OnCancel called twice" );
554 wxPrinterBase::sm_abortIt
= true;
555 wxPrinterBase::sm_abortWindow
->Destroy();
556 wxPrinterBase::sm_abortWindow
= NULL
;
559 //----------------------------------------------------------------------------
561 //----------------------------------------------------------------------------
563 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
565 wxPrintout::wxPrintout(const wxString
& title
)
567 m_printoutTitle
= title
;
571 m_pageWidthPixels
= 0;
572 m_pageHeightPixels
= 0;
580 wxPrintout::~wxPrintout()
584 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
586 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle
);
589 void wxPrintout::OnEndDocument()
594 void wxPrintout::OnBeginPrinting()
598 void wxPrintout::OnEndPrinting()
602 bool wxPrintout::HasPage(int page
)
607 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
615 void wxPrintout::FitThisSizeToPaper(const wxSize
& imageSize
)
617 // Set the DC scale and origin so that the given image size fits within the
618 // entire page and the origin is at the top left corner of the page. Note
619 // that with most printers, portions of the page will be non-printable. Use
620 // this if you're managing your own page margins.
621 if (!m_printoutDC
) return;
622 wxRect paperRect
= GetPaperRectPixels();
624 GetPageSizePixels(&pw
, &ph
);
626 m_printoutDC
->GetSize(&w
, &h
);
627 float scaleX
= ((float(paperRect
.width
) * w
) / (float(pw
) * imageSize
.x
));
628 float scaleY
= ((float(paperRect
.height
) * h
) / (float(ph
) * imageSize
.y
));
629 float actualScale
= wxMin(scaleX
, scaleY
);
630 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
631 m_printoutDC
->SetDeviceOrigin(0, 0);
632 wxRect logicalPaperRect
= GetLogicalPaperRect();
633 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
636 void wxPrintout::FitThisSizeToPage(const wxSize
& imageSize
)
638 // Set the DC scale and origin so that the given image size fits within the
639 // printable area of the page and the origin is at the top left corner of
640 // the printable area.
641 if (!m_printoutDC
) return;
643 m_printoutDC
->GetSize(&w
, &h
);
644 float scaleX
= float(w
) / imageSize
.x
;
645 float scaleY
= float(h
) / imageSize
.y
;
646 float actualScale
= wxMin(scaleX
, scaleY
);
647 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
648 m_printoutDC
->SetDeviceOrigin(0, 0);
651 void wxPrintout::FitThisSizeToPageMargins(const wxSize
& imageSize
, const wxPageSetupDialogData
& pageSetupData
)
653 // Set the DC scale and origin so that the given image size fits within the
654 // page margins defined in the given wxPageSetupDialogData object and the
655 // origin is at the top left corner of the page margins.
656 if (!m_printoutDC
) return;
657 wxRect paperRect
= GetPaperRectPixels();
659 GetPageSizePixels(&pw
, &ph
);
660 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
661 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
663 GetPageSizeMM(&mw
, &mh
);
664 float mmToDeviceX
= float(pw
) / mw
;
665 float mmToDeviceY
= float(ph
) / mh
;
666 wxRect
pageMarginsRect(paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
667 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
668 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
669 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
671 m_printoutDC
->GetSize(&w
, &h
);
672 float scaleX
= (float(pageMarginsRect
.width
) * w
) / (float(pw
) * imageSize
.x
);
673 float scaleY
= (float(pageMarginsRect
.height
) * h
) / (float(ph
) * imageSize
.y
);
674 float actualScale
= wxMin(scaleX
, scaleY
);
675 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
676 m_printoutDC
->SetDeviceOrigin(0, 0);
677 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
678 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
681 void wxPrintout::MapScreenSizeToPaper()
683 // Set the DC scale so that an image on the screen is the same size on the
684 // paper and the origin is at the top left of the paper. Note that with most
685 // printers, portions of the page will be cut off. Use this if you're
686 // managing your own page margins.
687 if (!m_printoutDC
) return;
688 MapScreenSizeToPage();
689 wxRect logicalPaperRect
= GetLogicalPaperRect();
690 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
693 void wxPrintout::MapScreenSizeToPage()
695 // Set the DC scale and origin so that an image on the screen is the same
696 // size on the paper and the origin is at the top left of the printable area.
697 if (!m_printoutDC
) return;
698 int ppiScreenX
, ppiScreenY
;
699 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
700 int ppiPrinterX
, ppiPrinterY
;
701 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
703 m_printoutDC
->GetSize(&w
, &h
);
704 int pageSizePixelsX
, pageSizePixelsY
;
705 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
706 float userScaleX
= (float(ppiPrinterX
) * w
) / (float(ppiScreenX
) * pageSizePixelsX
);
707 float userScaleY
= (float(ppiPrinterY
) * h
) / (float(ppiScreenY
) * pageSizePixelsY
);
708 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
709 m_printoutDC
->SetDeviceOrigin(0, 0);
712 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData
& pageSetupData
)
714 // Set the DC scale so that an image on the screen is the same size on the
715 // paper and the origin is at the top left of the page margins defined by
716 // the given wxPageSetupDialogData object.
717 if (!m_printoutDC
) return;
718 MapScreenSizeToPage();
719 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
720 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
723 void wxPrintout::MapScreenSizeToDevice()
725 // Set the DC scale so that a screen pixel is the same size as a device
726 // pixel and the origin is at the top left of the printable area.
727 if (!m_printoutDC
) return;
729 m_printoutDC
->GetSize(&w
, &h
);
730 int pageSizePixelsX
, pageSizePixelsY
;
731 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
732 float userScaleX
= float(w
) / pageSizePixelsX
;
733 float userScaleY
= float(h
) / pageSizePixelsY
;
734 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
735 m_printoutDC
->SetDeviceOrigin(0, 0);
738 wxRect
wxPrintout::GetLogicalPaperRect() const
740 // Return the rectangle in logical units that corresponds to the paper
742 wxRect paperRect
= GetPaperRectPixels();
744 GetPageSizePixels(&pw
, &ph
);
746 m_printoutDC
->GetSize(&w
, &h
);
747 if (w
== pw
&& h
== ph
) {
748 // this DC matches the printed page, so no scaling
749 return wxRect(m_printoutDC
->DeviceToLogicalX(paperRect
.x
),
750 m_printoutDC
->DeviceToLogicalY(paperRect
.y
),
751 m_printoutDC
->DeviceToLogicalXRel(paperRect
.width
),
752 m_printoutDC
->DeviceToLogicalYRel(paperRect
.height
));
754 // This DC doesn't match the printed page, so we have to scale.
755 float scaleX
= float(w
) / pw
;
756 float scaleY
= float(h
) / ph
;
757 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(paperRect
.x
* scaleX
)),
758 m_printoutDC
->DeviceToLogicalY(wxRound(paperRect
.y
* scaleY
)),
759 m_printoutDC
->DeviceToLogicalXRel(wxRound(paperRect
.width
* scaleX
)),
760 m_printoutDC
->DeviceToLogicalYRel(wxRound(paperRect
.height
* scaleY
)));
763 wxRect
wxPrintout::GetLogicalPageRect() const
765 // Return the rectangle in logical units that corresponds to the printable
768 m_printoutDC
->GetSize(&w
, &h
);
769 return wxRect(m_printoutDC
->DeviceToLogicalX(0),
770 m_printoutDC
->DeviceToLogicalY(0),
771 m_printoutDC
->DeviceToLogicalXRel(w
),
772 m_printoutDC
->DeviceToLogicalYRel(h
));
775 wxRect
wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData
& pageSetupData
) const
777 // Return the rectangle in logical units that corresponds to the region
778 // within the page margins as specified by the given wxPageSetupDialogData
781 // We get the paper size in device units and the margins in mm,
782 // so we need to calculate the conversion with this trick
784 GetPageSizePixels(&pw
, &ph
);
786 GetPageSizeMM(&mw
, &mh
);
787 float mmToDeviceX
= float(pw
) / mw
;
788 float mmToDeviceY
= float(ph
) / mh
;
790 // paper size in device units
791 wxRect paperRect
= GetPaperRectPixels();
794 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
795 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
797 // calculate margins in device units
798 wxRect
pageMarginsRect(
799 paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
800 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
801 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
802 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
805 m_printoutDC
->GetSize(&w
, &h
);
806 if (w
== pw
&& h
== ph
)
808 // this DC matches the printed page, so no scaling
810 m_printoutDC
->DeviceToLogicalX(pageMarginsRect
.x
),
811 m_printoutDC
->DeviceToLogicalY(pageMarginsRect
.y
),
812 m_printoutDC
->DeviceToLogicalXRel(pageMarginsRect
.width
),
813 m_printoutDC
->DeviceToLogicalYRel(pageMarginsRect
.height
));
816 // This DC doesn't match the printed page, so we have to scale.
817 float scaleX
= float(w
) / pw
;
818 float scaleY
= float(h
) / ph
;
819 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(pageMarginsRect
.x
* scaleX
)),
820 m_printoutDC
->DeviceToLogicalY(wxRound(pageMarginsRect
.y
* scaleY
)),
821 m_printoutDC
->DeviceToLogicalXRel(wxRound(pageMarginsRect
.width
* scaleX
)),
822 m_printoutDC
->DeviceToLogicalYRel(wxRound(pageMarginsRect
.height
* scaleY
)));
825 void wxPrintout::SetLogicalOrigin(wxCoord x
, wxCoord y
)
827 // Set the device origin by specifying a point in logical coordinates.
828 m_printoutDC
->SetDeviceOrigin(
829 m_printoutDC
->LogicalToDeviceX(x
),
830 m_printoutDC
->LogicalToDeviceY(y
) );
833 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff
, wxCoord yoff
)
835 // Offset the device origin by a specified distance in device coordinates.
836 wxPoint dev_org
= m_printoutDC
->GetDeviceOrigin();
837 m_printoutDC
->SetDeviceOrigin(
838 dev_org
.x
+ m_printoutDC
->LogicalToDeviceXRel(xoff
),
839 dev_org
.y
+ m_printoutDC
->LogicalToDeviceYRel(yoff
) );
843 //----------------------------------------------------------------------------
845 //----------------------------------------------------------------------------
847 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
849 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
850 EVT_PAINT(wxPreviewCanvas::OnPaint
)
851 EVT_CHAR(wxPreviewCanvas::OnChar
)
852 EVT_IDLE(wxPreviewCanvas::OnIdle
)
853 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
855 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel
)
859 // VZ: the current code doesn't refresh properly without
860 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
861 // really horrible flicker when resizing the preview frame, but without
862 // this style it simply doesn't work correctly at all...
863 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
864 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
865 wxScrolledWindow(parent
, wxID_ANY
, pos
, size
, style
| wxFULL_REPAINT_ON_RESIZE
, name
)
867 m_printPreview
= preview
;
869 // The app workspace colour is always white, but we should have
870 // a contrast with the page.
871 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
872 #elif defined(__WXGTK__)
873 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
875 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
877 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
879 SetScrollbars(10, 10, 100, 100);
882 wxPreviewCanvas::~wxPreviewCanvas()
886 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
893 if (!GetUpdateRegion().IsEmpty())
894 dc.SetClippingRegion( GetUpdateRegion() );
900 m_printPreview
->PaintPage(this, dc
);
904 void wxPreviewCanvas::OnIdle(wxIdleEvent
& event
)
908 // prevent UpdatePageRendering() from being called recursively:
909 static bool s_inIdle
= false;
914 if ( m_printPreview
)
916 if ( m_printPreview
->UpdatePageRendering() )
923 // Responds to colour changes, and passes event on to children.
924 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
927 // The app workspace colour is always white, but we should have
928 // a contrast with the page.
929 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
930 #elif defined(__WXGTK__)
931 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
933 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
935 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
938 // Propagate the event to the non-top-level children
939 wxWindow::OnSysColourChanged(event
);
942 void wxPreviewCanvas::OnChar(wxKeyEvent
&event
)
944 wxPreviewControlBar
* controlBar
= ((wxPreviewFrame
*) GetParent())->GetControlBar();
945 switch (event
.GetKeyCode())
948 controlBar
->OnPrint();
953 controlBar
->DoZoomIn();
956 case WXK_NUMPAD_SUBTRACT
:
958 controlBar
->DoZoomOut();
962 if (!event
.ControlDown())
968 switch(event
.GetKeyCode())
971 controlBar
->OnNext(); break;
973 controlBar
->OnPrevious(); break;
975 controlBar
->OnFirst(); break;
977 controlBar
->OnLast(); break;
985 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent
& event
)
987 wxPreviewControlBar
*
988 controlBar
= wxStaticCast(GetParent(), wxPreviewFrame
)->GetControlBar();
992 if ( event
.ControlDown() && event
.GetWheelRotation() != 0 )
994 int currentZoom
= controlBar
->GetZoomControl();
997 if ( currentZoom
< 100 )
999 else if ( currentZoom
<= 120 )
1004 if ( event
.GetWheelRotation() > 0 )
1007 int newZoom
= currentZoom
+ delta
;
1010 if ( newZoom
> 200 )
1012 if ( newZoom
!= currentZoom
)
1014 controlBar
->SetZoomControl(newZoom
);
1015 m_printPreview
->SetZoom(newZoom
);
1025 #endif // wxUSE_MOUSEWHEEL
1030 // This is by the controls in the print preview as the maximal (and hence
1031 // longest) page number we may have to display.
1032 enum { MAX_PAGE_NUMBER
= 99999 };
1034 } // anonymous namespace
1036 // ----------------------------------------------------------------------------
1037 // wxPrintPageMaxCtrl
1038 // ----------------------------------------------------------------------------
1040 // A simple static control showing the maximal number of pages.
1041 class wxPrintPageMaxCtrl
: public wxStaticText
1044 wxPrintPageMaxCtrl(wxWindow
*parent
)
1052 parent
->GetTextExtent(MaxAsString(MAX_PAGE_NUMBER
)).x
,
1055 wxST_NO_AUTORESIZE
| wxALIGN_CENTRE
1060 // Set the maximal page to display once we really know what it is.
1061 void SetMaxPage(int maxPage
)
1063 SetLabel(MaxAsString(maxPage
));
1067 static wxString
MaxAsString(int maxPage
)
1069 return wxString::Format("/ %d", maxPage
);
1072 wxDECLARE_NO_COPY_CLASS(wxPrintPageMaxCtrl
);
1075 // ----------------------------------------------------------------------------
1076 // wxPrintPageTextCtrl
1077 // ----------------------------------------------------------------------------
1079 // This text control contains the page number in the specified interval.
1081 // Invalid pages are not accepted and the control contents is validated when it
1082 // loses focus. Conversely, if the user changes the page to another valid one
1083 // or presses Enter, OnGotoPage() method of the preview object will be called.
1084 class wxPrintPageTextCtrl
: public wxTextCtrl
1087 wxPrintPageTextCtrl(wxPreviewControlBar
*preview
)
1088 : wxTextCtrl(preview
,
1092 // We use hardcoded maximal page number for the width
1093 // instead of fitting it to the values we can show because
1094 // the control looks uncomfortably narrow if the real page
1095 // number is just one or two digits.
1098 preview
->GetTextExtent(PageAsString(MAX_PAGE_NUMBER
)).x
,
1102 #if wxUSE_VALIDATORS
1103 , wxTextValidator(wxFILTER_DIGITS
)
1104 #endif // wxUSE_VALIDATORS
1112 Connect(wxEVT_KILL_FOCUS
,
1113 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus
));
1114 Connect(wxEVT_TEXT_ENTER
,
1115 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter
));
1118 // Update the pages range, must be called after OnPreparePrinting() as
1119 // these values are not known before.
1120 void SetPageInfo(int minPage
, int maxPage
)
1122 m_minPage
= minPage
;
1123 m_maxPage
= maxPage
;
1125 // Show the first page by default.
1126 SetPageNumber(minPage
);
1129 // Helpers to conveniently set or get the current page number. Return value
1130 // is 0 if the current controls contents is invalid.
1131 void SetPageNumber(int page
)
1133 wxASSERT( IsValidPage(page
) );
1135 SetValue(PageAsString(page
));
1138 int GetPageNumber() const
1141 if ( !GetValue().ToLong(&value
) || !IsValidPage(value
) )
1144 // Cast is safe because the value is less than (int) m_maxPage.
1145 return static_cast<int>(value
);
1149 static wxString
PageAsString(int page
)
1151 return wxString::Format("%d", page
);
1154 bool IsValidPage(int page
) const
1156 return page
>= m_minPage
&& page
<= m_maxPage
;
1161 const int page
= GetPageNumber();
1166 if ( page
!= m_page
)
1168 // We have a valid page, remember it.
1171 // And notify the owner about the change.
1172 m_preview
->OnGotoPage();
1174 //else: Nothing really changed.
1179 void OnKillFocus(wxFocusEvent
& event
)
1181 if ( !DoChangePage() )
1183 // The current contents is invalid so reset it back to the last
1184 // known good page index.
1185 SetPageNumber(m_page
);
1191 void OnTextEnter(wxCommandEvent
& WXUNUSED(event
))
1197 wxPreviewControlBar
* const m_preview
;
1202 // This is the last valid page value that we had, we revert to it if an
1203 // invalid page is entered.
1206 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl
);
1209 //----------------------------------------------------------------------------
1210 // wxPreviewControlBar
1211 //----------------------------------------------------------------------------
1213 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
1215 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
1216 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
1217 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrintButton
)
1218 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
1219 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
1220 EVT_BUTTON(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnFirstButton
)
1221 EVT_BUTTON(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnLastButton
)
1222 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnZoomInButton
)
1223 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnZoomOutButton
)
1225 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnUpdatePreviousButton
)
1226 EVT_UPDATE_UI(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnUpdateNextButton
)
1227 EVT_UPDATE_UI(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnUpdateFirstButton
)
1228 EVT_UPDATE_UI(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnUpdateLastButton
)
1229 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnUpdateZoomInButton
)
1230 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnUpdateZoomOutButton
)
1232 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoomChoice
)
1233 EVT_PAINT(wxPreviewControlBar::OnPaint
)
1237 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
1238 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
1239 long style
, const wxString
& name
):
1240 wxPanel(parent
, wxID_ANY
, pos
, size
, style
, name
)
1242 m_printPreview
= preview
;
1243 m_closeButton
= NULL
;
1244 m_zoomControl
= NULL
;
1245 m_currentPageText
= NULL
;
1246 m_maxPageText
= NULL
;
1247 m_buttonFlags
= buttons
;
1250 wxPreviewControlBar::~wxPreviewControlBar()
1254 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1260 dc
.SetPen(*wxBLACK_PEN
);
1261 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1262 dc
.DrawLine( 0, h
-1, w
, h
-1 );
1265 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
1267 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
1271 void wxPreviewControlBar::OnPrint(void)
1273 wxPrintPreviewBase
*preview
= GetPrintPreview();
1274 preview
->Print(true);
1277 void wxPreviewControlBar::OnNext()
1279 if ( IsNextEnabled() )
1280 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1283 void wxPreviewControlBar::OnPrevious()
1285 if ( IsPreviousEnabled() )
1286 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1289 void wxPreviewControlBar::OnFirst()
1291 if ( IsFirstEnabled() )
1292 DoGotoPage(GetPrintPreview()->GetMinPage());
1295 void wxPreviewControlBar::OnLast()
1297 if ( IsLastEnabled() )
1298 DoGotoPage(GetPrintPreview()->GetMaxPage());
1301 bool wxPreviewControlBar::IsNextEnabled() const
1303 wxPrintPreviewBase
*preview
= GetPrintPreview();
1307 const int currentPage
= preview
->GetCurrentPage();
1308 return currentPage
< preview
->GetMaxPage() &&
1309 preview
->GetPrintout()->HasPage(currentPage
+ 1);
1312 bool wxPreviewControlBar::IsPreviousEnabled() const
1314 wxPrintPreviewBase
*preview
= GetPrintPreview();
1318 const int currentPage
= preview
->GetCurrentPage();
1319 return currentPage
> preview
->GetMinPage() &&
1320 preview
->GetPrintout()->HasPage(currentPage
- 1);
1323 bool wxPreviewControlBar::IsFirstEnabled() const
1325 wxPrintPreviewBase
*preview
= GetPrintPreview();
1329 return preview
->GetPrintout()->HasPage(preview
->GetMinPage());
1332 bool wxPreviewControlBar::IsLastEnabled() const
1334 wxPrintPreviewBase
*preview
= GetPrintPreview();
1338 return preview
->GetPrintout()->HasPage(preview
->GetMaxPage());
1341 void wxPreviewControlBar::DoGotoPage(int page
)
1343 wxPrintPreviewBase
*preview
= GetPrintPreview();
1344 wxCHECK_RET( preview
, "Shouldn't be called if there is no preview." );
1346 preview
->SetCurrentPage(page
);
1348 if ( m_currentPageText
)
1349 m_currentPageText
->SetPageNumber(page
);
1352 void wxPreviewControlBar::OnGotoPage()
1354 wxPrintPreviewBase
*preview
= GetPrintPreview();
1357 if (preview
->GetMinPage() > 0)
1359 long currentPage
= m_currentPageText
->GetPageNumber();
1362 if (preview
->GetPrintout()->HasPage(currentPage
))
1364 preview
->SetCurrentPage(currentPage
);
1371 void wxPreviewControlBar::DoZoom()
1373 int zoom
= GetZoomControl();
1374 if (GetPrintPreview())
1375 GetPrintPreview()->SetZoom(zoom
);
1378 bool wxPreviewControlBar::IsZoomInEnabled() const
1380 if ( !m_zoomControl
)
1383 const unsigned sel
= m_zoomControl
->GetSelection();
1384 return sel
< m_zoomControl
->GetCount() - 1;
1387 bool wxPreviewControlBar::IsZoomOutEnabled() const
1389 return m_zoomControl
&& m_zoomControl
->GetSelection() > 0;
1392 void wxPreviewControlBar::DoZoomIn()
1394 if (IsZoomInEnabled())
1396 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() + 1);
1401 void wxPreviewControlBar::DoZoomOut()
1403 if (IsZoomOutEnabled())
1405 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() - 1);
1413 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1414 // sequentially to it in the simplest way possible.
1415 class SizerWithButtons
1418 // Constructor creates the sizer that will hold the buttons and stores the
1419 // parent that will be used for their creation.
1420 SizerWithButtons(wxWindow
*parent
)
1421 : m_sizer(new wxBoxSizer(wxHORIZONTAL
)),
1425 m_needsSeparator
= false;
1428 // Destructor associates the sizer with the parent window.
1431 m_parent
->SetSizer(m_sizer
);
1432 m_sizer
->Fit(m_parent
);
1436 // Add an arbitrary window to the sizer.
1437 void Add(wxWindow
*win
)
1439 if ( m_needsSeparator
)
1441 m_needsSeparator
= false;
1443 m_sizer
->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1446 m_hasContents
= true;
1449 wxSizerFlags().Border(wxLEFT
| wxTOP
| wxBOTTOM
).Center());
1452 // Add a button with the specified id, bitmap and tooltip.
1453 void AddButton(wxWindowID btnId
,
1454 const wxArtID
& artId
,
1455 const wxString
& tooltip
)
1457 // We don't use (smaller) images inside a button with a text label but
1458 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1459 // wxART_BUTTON here.
1460 wxBitmap bmp
= wxArtProvider::GetBitmap(artId
, wxART_TOOLBAR
);
1461 wxBitmapButton
* const btn
= new wxBitmapButton(m_parent
, btnId
, bmp
);
1462 btn
->SetToolTip(tooltip
);
1467 // Add a control at the right end of the window. This should be called last
1468 // as everything else added after it will be added on the right side too.
1469 void AddAtEnd(wxWindow
*win
)
1471 m_sizer
->AddStretchSpacer();
1473 wxSizerFlags().Border(wxTOP
| wxBOTTOM
| wxRIGHT
).Center());
1476 // Indicates the end of a group of buttons, a separator will be added after
1480 if ( m_hasContents
)
1482 m_needsSeparator
= true;
1483 m_hasContents
= false;
1488 wxSizer
* const m_sizer
;
1489 wxWindow
* const m_parent
;
1491 // If true, we have some controls since the last group beginning. This is
1492 // used to avoid inserting two consecutive separators if EndOfGroup() is
1496 // If true, a separator should be inserted before adding the next button.
1497 bool m_needsSeparator
;
1499 wxDECLARE_NO_COPY_CLASS(SizerWithButtons
);
1502 } // anonymous namespace
1504 void wxPreviewControlBar::CreateButtons()
1506 SizerWithButtons
sizer(this);
1508 // Print button group (a single button).
1509 if (m_buttonFlags
& wxPREVIEW_PRINT
)
1511 sizer
.AddButton(wxID_PREVIEW_PRINT
, wxART_PRINT
, _("Print"));
1515 // Page selection buttons group.
1516 if (m_buttonFlags
& wxPREVIEW_FIRST
)
1518 sizer
.AddButton(wxID_PREVIEW_FIRST
, wxART_GOTO_FIRST
, _("First page"));
1521 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
1523 sizer
.AddButton(wxID_PREVIEW_PREVIOUS
, wxART_GO_BACK
, _("Previous page"));
1526 if (m_buttonFlags
& wxPREVIEW_GOTO
)
1528 m_currentPageText
= new wxPrintPageTextCtrl(this);
1529 sizer
.Add(m_currentPageText
);
1531 m_maxPageText
= new wxPrintPageMaxCtrl(this);
1532 sizer
.Add(m_maxPageText
);
1535 if (m_buttonFlags
& wxPREVIEW_NEXT
)
1537 sizer
.AddButton(wxID_PREVIEW_NEXT
, wxART_GO_FORWARD
, _("Next page"));
1540 if (m_buttonFlags
& wxPREVIEW_LAST
)
1542 sizer
.AddButton(wxID_PREVIEW_LAST
, wxART_GOTO_LAST
, _("Last page"));
1547 // Zoom controls group.
1548 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
1550 sizer
.AddButton(wxID_PREVIEW_ZOOM_OUT
, wxART_MINUS
, _("Zoom Out"));
1552 wxString choices
[] =
1554 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1555 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1556 wxT("120%"), wxT("150%"), wxT("200%")
1558 int n
= WXSIZEOF(choices
);
1560 m_zoomControl
= new wxChoice( this, wxID_PREVIEW_ZOOM
, wxDefaultPosition
, wxSize(70,wxDefaultCoord
), n
, choices
, 0 );
1561 sizer
.Add(m_zoomControl
);
1562 SetZoomControl(m_printPreview
->GetZoom());
1564 sizer
.AddButton(wxID_PREVIEW_ZOOM_IN
, wxART_PLUS
, _("Zoom In"));
1569 // Close button group (single button again).
1570 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("&Close"));
1571 sizer
.AddAtEnd(m_closeButton
);
1574 void wxPreviewControlBar::SetPageInfo(int minPage
, int maxPage
)
1576 if ( m_currentPageText
)
1577 m_currentPageText
->SetPageInfo(minPage
, maxPage
);
1579 if ( m_maxPageText
)
1580 m_maxPageText
->SetMaxPage(maxPage
);
1583 void wxPreviewControlBar::SetZoomControl(int zoom
)
1587 int n
, count
= m_zoomControl
->GetCount();
1589 for (n
=0; n
<count
; n
++)
1591 if (m_zoomControl
->GetString(n
).BeforeFirst(wxT('%')).ToLong(&val
) &&
1592 (val
>= long(zoom
)))
1594 m_zoomControl
->SetSelection(n
);
1599 m_zoomControl
->SetSelection(count
-1);
1603 int wxPreviewControlBar::GetZoomControl()
1605 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxEmptyString
))
1608 if (m_zoomControl
->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val
))
1620 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
1622 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
1623 EVT_CHAR_HOOK(wxPreviewFrame::OnChar
)
1624 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
1627 void wxPreviewFrame::OnChar(wxKeyEvent
&event
)
1629 if ( event
.GetKeyCode() == WXK_ESCAPE
)
1639 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxWindow
*parent
, const wxString
& title
,
1640 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
1641 wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
, name
)
1643 m_printPreview
= preview
;
1644 m_controlBar
= NULL
;
1645 m_previewCanvas
= NULL
;
1646 m_windowDisabler
= NULL
;
1647 m_modalityKind
= wxPreviewFrame_NonModal
;
1649 // Give the application icon
1651 wxFrame
* topFrame
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
1653 SetIcons(topFrame
->GetIcons());
1657 wxPreviewFrame::~wxPreviewFrame()
1659 wxPrintout
*printout
= m_printPreview
->GetPrintout();
1663 m_printPreview
->SetPrintout(NULL
);
1664 m_printPreview
->SetCanvas(NULL
);
1665 m_printPreview
->SetFrame(NULL
);
1668 m_previewCanvas
->SetPreview(NULL
);
1669 delete m_printPreview
;
1672 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
1674 // Reenable any windows we disabled by undoing whatever we did in our
1676 switch ( m_modalityKind
)
1678 case wxPreviewFrame_AppModal
:
1679 delete m_windowDisabler
;
1680 m_windowDisabler
= NULL
;
1683 case wxPreviewFrame_WindowModal
:
1685 GetParent()->Enable();
1688 case wxPreviewFrame_NonModal
:
1695 void wxPreviewFrame::InitializeWithModality(wxPreviewFrameModalityKind kind
)
1703 m_printPreview
->SetCanvas(m_previewCanvas
);
1704 m_printPreview
->SetFrame(this);
1706 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
1708 item0
->Add( m_controlBar
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1709 item0
->Add( m_previewCanvas
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1711 SetAutoLayout( true );
1714 m_modalityKind
= kind
;
1715 switch ( m_modalityKind
)
1717 case wxPreviewFrame_AppModal
:
1718 // Disable everything.
1719 m_windowDisabler
= new wxWindowDisabler( this );
1722 case wxPreviewFrame_WindowModal
:
1723 // Disable our parent if we have one.
1725 GetParent()->Disable();
1728 case wxPreviewFrame_NonModal
:
1729 // Nothing to do, we don't need to disable any windows.
1733 if ( m_modalityKind
!= wxPreviewFrame_NonModal
)
1735 // Behave like modal dialogs, don't show in taskbar. This implies
1736 // removing the minimize box, because minimizing windows without
1737 // taskbar entry is confusing.
1738 SetWindowStyle((GetWindowStyle() & ~wxMINIMIZE_BOX
) | wxFRAME_NO_TASKBAR
);
1743 m_printPreview
->AdjustScrollbars(m_previewCanvas
);
1744 m_previewCanvas
->SetFocus();
1745 m_controlBar
->SetFocus();
1748 void wxPreviewFrame::CreateCanvas()
1750 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
1753 void wxPreviewFrame::CreateControlBar()
1755 long buttons
= wxPREVIEW_DEFAULT
;
1756 if (m_printPreview
->GetPrintoutForPrinting())
1757 buttons
|= wxPREVIEW_PRINT
;
1759 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this);
1760 m_controlBar
->CreateButtons();
1767 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
1769 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1770 wxPrintout
*printoutForPrinting
,
1774 m_printDialogData
= (*data
);
1776 Init(printout
, printoutForPrinting
);
1779 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1780 wxPrintout
*printoutForPrinting
,
1781 wxPrintDialogData
*data
)
1784 m_printDialogData
= (*data
);
1786 Init(printout
, printoutForPrinting
);
1789 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
1790 wxPrintout
*printoutForPrinting
)
1793 m_previewPrintout
= printout
;
1794 if (m_previewPrintout
)
1795 m_previewPrintout
->SetPreview(static_cast<wxPrintPreview
*>(this));
1797 m_printPrintout
= printoutForPrinting
;
1799 m_previewCanvas
= NULL
;
1800 m_previewFrame
= NULL
;
1801 m_previewBitmap
= NULL
;
1802 m_previewFailed
= false;
1806 m_leftMargin
= 2*wxSizerFlags::GetDefaultBorder();
1809 m_printingPrepared
= false;
1814 wxPrintPreviewBase::~wxPrintPreviewBase()
1816 if (m_previewPrintout
)
1817 delete m_previewPrintout
;
1818 if (m_previewBitmap
)
1819 delete m_previewBitmap
;
1820 if (m_printPrintout
)
1821 delete m_printPrintout
;
1824 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
1826 if (m_currentPage
== pageNum
)
1829 m_currentPage
= pageNum
;
1831 InvalidatePreviewBitmap();
1833 if (m_previewCanvas
)
1835 AdjustScrollbars(m_previewCanvas
);
1837 m_previewCanvas
->Refresh();
1838 m_previewCanvas
->SetFocus();
1843 int wxPrintPreviewBase::GetCurrentPage() const
1844 { return m_currentPage
; }
1845 void wxPrintPreviewBase::SetPrintout(wxPrintout
*printout
)
1846 { m_previewPrintout
= printout
; }
1847 wxPrintout
*wxPrintPreviewBase::GetPrintout() const
1848 { return m_previewPrintout
; }
1849 wxPrintout
*wxPrintPreviewBase::GetPrintoutForPrinting() const
1850 { return m_printPrintout
; }
1851 void wxPrintPreviewBase::SetFrame(wxFrame
*frame
)
1852 { m_previewFrame
= frame
; }
1853 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas
*canvas
)
1854 { m_previewCanvas
= canvas
; }
1855 wxFrame
*wxPrintPreviewBase::GetFrame() const
1856 { return m_previewFrame
; }
1857 wxPreviewCanvas
*wxPrintPreviewBase::GetCanvas() const
1858 { return m_previewCanvas
; }
1860 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas
*canvas
, wxRect
& pageRect
, wxRect
& paperRect
)
1862 // Calculate the rectangles for the printable area of the page and the
1863 // entire paper as they appear on the canvas on-screen.
1864 int canvasWidth
, canvasHeight
;
1865 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
1867 float zoomScale
= float(m_currentZoom
) / 100;
1868 float screenPrintableWidth
= zoomScale
* m_pageWidth
* m_previewScaleX
;
1869 float screenPrintableHeight
= zoomScale
* m_pageHeight
* m_previewScaleY
;
1871 wxRect devicePaperRect
= m_previewPrintout
->GetPaperRectPixels();
1872 wxCoord devicePrintableWidth
, devicePrintableHeight
;
1873 m_previewPrintout
->GetPageSizePixels(&devicePrintableWidth
, &devicePrintableHeight
);
1874 float scaleX
= screenPrintableWidth
/ devicePrintableWidth
;
1875 float scaleY
= screenPrintableHeight
/ devicePrintableHeight
;
1876 paperRect
.width
= wxCoord(scaleX
* devicePaperRect
.width
);
1877 paperRect
.height
= wxCoord(scaleY
* devicePaperRect
.height
);
1879 paperRect
.x
= wxCoord((canvasWidth
- paperRect
.width
)/ 2.0);
1880 if (paperRect
.x
< m_leftMargin
)
1881 paperRect
.x
= m_leftMargin
;
1882 paperRect
.y
= wxCoord((canvasHeight
- paperRect
.height
)/ 2.0);
1883 if (paperRect
.y
< m_topMargin
)
1884 paperRect
.y
= m_topMargin
;
1886 pageRect
.x
= paperRect
.x
- wxCoord(scaleX
* devicePaperRect
.x
);
1887 pageRect
.y
= paperRect
.y
- wxCoord(scaleY
* devicePaperRect
.y
);
1888 pageRect
.width
= wxCoord(screenPrintableWidth
);
1889 pageRect
.height
= wxCoord(screenPrintableHeight
);
1893 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1895 wxDELETE(m_previewBitmap
);
1896 // if there was a problem with rendering the preview, try again now
1897 // that it changed in some way (less memory may be needed, for example):
1898 m_previewFailed
= false;
1901 bool wxPrintPreviewBase::UpdatePageRendering()
1903 if ( m_previewBitmap
)
1906 if ( m_previewFailed
)
1909 if ( !RenderPage(m_currentPage
) )
1911 m_previewFailed
= true; // don't waste time failing again
1918 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1920 DrawBlankPage(canvas
, dc
);
1922 if (!m_previewBitmap
)
1927 wxRect pageRect
, paperRect
;
1928 CalcRects(canvas
, pageRect
, paperRect
);
1930 temp_dc
.SelectObject(*m_previewBitmap
);
1932 dc
.Blit(pageRect
.x
, pageRect
.y
,
1933 m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
1935 temp_dc
.SelectObject(wxNullBitmap
);
1939 // Adjusts the scrollbars for the current scale
1940 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas
*canvas
)
1945 wxRect pageRect
, paperRect
;
1946 CalcRects(canvas
, pageRect
, paperRect
);
1947 int totalWidth
= paperRect
.width
+ 2 * m_leftMargin
;
1948 int totalHeight
= paperRect
.height
+ 2 * m_topMargin
;
1949 int scrollUnitsX
= totalWidth
/ 10;
1950 int scrollUnitsY
= totalHeight
/ 10;
1951 wxSize virtualSize
= canvas
->GetVirtualSize();
1952 if (virtualSize
.GetWidth() != totalWidth
|| virtualSize
.GetHeight() != totalHeight
)
1953 canvas
->SetScrollbars(10, 10, scrollUnitsX
, scrollUnitsY
, 0, 0, true);
1956 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC
& dc
, int pageNum
)
1958 m_previewPrintout
->SetDC(&dc
);
1959 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
1961 // Need to delay OnPreparePrinting() until here, so we have enough
1962 // information and a wxDC.
1963 if (!m_printingPrepared
)
1965 m_printingPrepared
= true;
1967 m_previewPrintout
->OnPreparePrinting();
1969 m_previewPrintout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
1971 // Update the wxPreviewControlBar page range display.
1972 if ( m_previewFrame
)
1974 wxPreviewControlBar
* const
1975 controlBar
= ((wxPreviewFrame
*)m_previewFrame
)->GetControlBar();
1977 controlBar
->SetPageInfo(m_minPage
, m_maxPage
);
1981 m_previewPrintout
->OnBeginPrinting();
1983 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
1985 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
1989 m_previewPrintout
->OnPrintPage(pageNum
);
1990 m_previewPrintout
->OnEndDocument();
1991 m_previewPrintout
->OnEndPrinting();
1993 m_previewPrintout
->SetDC(NULL
);
1998 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap
& bmp
, int pageNum
)
2000 wxMemoryDC memoryDC
;
2001 memoryDC
.SelectObject(bmp
);
2004 return RenderPageIntoDC(memoryDC
, pageNum
);
2007 bool wxPrintPreviewBase::RenderPage(int pageNum
)
2011 if (!m_previewCanvas
)
2013 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
2017 wxRect pageRect
, paperRect
;
2018 CalcRects(m_previewCanvas
, pageRect
, paperRect
);
2020 if (!m_previewBitmap
)
2022 m_previewBitmap
= new wxBitmap(pageRect
.width
, pageRect
.height
);
2024 if (!m_previewBitmap
|| !m_previewBitmap
->IsOk())
2026 InvalidatePreviewBitmap();
2027 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2032 if ( !RenderPageIntoBitmap(*m_previewBitmap
, pageNum
) )
2034 InvalidatePreviewBitmap();
2035 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2042 status
= wxString::Format(_("Page %d of %d"), pageNum
, m_maxPage
);
2044 status
= wxString::Format(_("Page %d"), pageNum
);
2047 m_previewFrame
->SetStatusText(status
);
2053 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2055 wxRect pageRect
, paperRect
;
2057 CalcRects(canvas
, pageRect
, paperRect
);
2059 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
2060 wxCoord shadowOffset
= 4;
2062 dc
.SetPen(*wxBLACK_PEN
);
2063 dc
.SetBrush(*wxBLACK_BRUSH
);
2064 dc
.DrawRectangle(paperRect
.x
+ shadowOffset
, paperRect
.y
+ paperRect
.height
+ 1,
2065 paperRect
.width
, shadowOffset
);
2067 dc
.DrawRectangle(paperRect
.x
+ paperRect
.width
, paperRect
.y
+ shadowOffset
,
2068 shadowOffset
, paperRect
.height
);
2070 // Draw blank page allowing for 1-pixel border AROUND the actual paper
2071 dc
.SetPen(*wxBLACK_PEN
);
2072 dc
.SetBrush(*wxWHITE_BRUSH
);
2073 dc
.DrawRectangle(paperRect
.x
- 2, paperRect
.y
- 1,
2074 paperRect
.width
+ 3, paperRect
.height
+ 2);
2079 void wxPrintPreviewBase::SetZoom(int percent
)
2081 if (m_currentZoom
== percent
)
2084 m_currentZoom
= percent
;
2086 InvalidatePreviewBitmap();
2088 if (m_previewCanvas
)
2090 AdjustScrollbars(m_previewCanvas
);
2091 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
2092 m_previewCanvas
->ClearBackground();
2093 m_previewCanvas
->Refresh();
2094 m_previewCanvas
->SetFocus();
2098 wxPrintDialogData
& wxPrintPreviewBase::GetPrintDialogData()
2100 return m_printDialogData
;
2103 int wxPrintPreviewBase::GetZoom() const
2104 { return m_currentZoom
; }
2105 int wxPrintPreviewBase::GetMaxPage() const
2106 { return m_maxPage
; }
2107 int wxPrintPreviewBase::GetMinPage() const
2108 { return m_minPage
; }
2109 bool wxPrintPreviewBase::IsOk() const
2111 void wxPrintPreviewBase::SetOk(bool ok
)
2114 //----------------------------------------------------------------------------
2116 //----------------------------------------------------------------------------
2118 IMPLEMENT_CLASS(wxPrintPreview
, wxPrintPreviewBase
)
2120 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2121 wxPrintout
*printoutForPrinting
,
2122 wxPrintDialogData
*data
) :
2123 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2125 m_pimpl
= wxPrintFactory::GetFactory()->
2126 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2129 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2130 wxPrintout
*printoutForPrinting
,
2131 wxPrintData
*data
) :
2132 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2134 m_pimpl
= wxPrintFactory::GetFactory()->
2135 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2138 wxPrintPreview::~wxPrintPreview()
2142 // don't delete twice
2143 m_printPrintout
= NULL
;
2144 m_previewPrintout
= NULL
;
2145 m_previewBitmap
= NULL
;
2148 bool wxPrintPreview::SetCurrentPage(int pageNum
)
2150 return m_pimpl
->SetCurrentPage( pageNum
);
2153 int wxPrintPreview::GetCurrentPage() const
2155 return m_pimpl
->GetCurrentPage();
2158 void wxPrintPreview::SetPrintout(wxPrintout
*printout
)
2160 m_pimpl
->SetPrintout( printout
);
2163 wxPrintout
*wxPrintPreview::GetPrintout() const
2165 return m_pimpl
->GetPrintout();
2168 wxPrintout
*wxPrintPreview::GetPrintoutForPrinting() const
2170 return m_pimpl
->GetPrintoutForPrinting();
2173 void wxPrintPreview::SetFrame(wxFrame
*frame
)
2175 m_pimpl
->SetFrame( frame
);
2178 void wxPrintPreview::SetCanvas(wxPreviewCanvas
*canvas
)
2180 m_pimpl
->SetCanvas( canvas
);
2183 wxFrame
*wxPrintPreview::GetFrame() const
2185 return m_pimpl
->GetFrame();
2188 wxPreviewCanvas
*wxPrintPreview::GetCanvas() const
2190 return m_pimpl
->GetCanvas();
2193 bool wxPrintPreview::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2195 return m_pimpl
->PaintPage( canvas
, dc
);
2198 bool wxPrintPreview::UpdatePageRendering()
2200 return m_pimpl
->UpdatePageRendering();
2203 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2205 return m_pimpl
->DrawBlankPage( canvas
, dc
);
2208 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas
*canvas
)
2210 m_pimpl
->AdjustScrollbars( canvas
);
2213 bool wxPrintPreview::RenderPage(int pageNum
)
2215 return m_pimpl
->RenderPage( pageNum
);
2218 void wxPrintPreview::SetZoom(int percent
)
2220 m_pimpl
->SetZoom( percent
);
2223 int wxPrintPreview::GetZoom() const
2225 return m_pimpl
->GetZoom();
2228 wxPrintDialogData
& wxPrintPreview::GetPrintDialogData()
2230 return m_pimpl
->GetPrintDialogData();
2233 int wxPrintPreview::GetMaxPage() const
2235 return m_pimpl
->GetMaxPage();
2238 int wxPrintPreview::GetMinPage() const
2240 return m_pimpl
->GetMinPage();
2243 bool wxPrintPreview::IsOk() const
2245 return m_pimpl
->IsOk();
2248 void wxPrintPreview::SetOk(bool ok
)
2250 m_pimpl
->SetOk( ok
);
2253 bool wxPrintPreview::Print(bool interactive
)
2255 return m_pimpl
->Print( interactive
);
2258 void wxPrintPreview::DetermineScaling()
2260 m_pimpl
->DetermineScaling();
2263 #endif // wxUSE_PRINTING_ARCHITECTURE