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 wxPrintAbortDialog
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
* printout
)
326 return new wxPrintAbortDialog(parent
, printout
->GetTitle());
329 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), const wxString
& message
)
331 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
334 wxPrintDialogData
& wxPrinterBase::GetPrintDialogData() const
336 return (wxPrintDialogData
&) m_printDialogData
;
339 //----------------------------------------------------------------------------
341 //----------------------------------------------------------------------------
343 IMPLEMENT_CLASS(wxPrinter
, wxPrinterBase
)
345 wxPrinter::wxPrinter(wxPrintDialogData
*data
)
347 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrinter( data
);
350 wxPrinter::~wxPrinter()
355 wxPrintAbortDialog
*wxPrinter::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*printout
)
357 return m_pimpl
->CreateAbortWindow( parent
, printout
);
360 void wxPrinter::ReportError(wxWindow
*parent
, wxPrintout
*printout
, const wxString
& message
)
362 m_pimpl
->ReportError( parent
, printout
, message
);
365 bool wxPrinter::Setup(wxWindow
*parent
)
367 return m_pimpl
->Setup( parent
);
370 bool wxPrinter::Print(wxWindow
*parent
, wxPrintout
*printout
, bool prompt
)
372 if ( !prompt
&& m_printDialogData
.GetToPage() == 0 )
374 // If the dialog is not shown, set the pages range to print everything
375 // by default (as otherwise we wouldn't print anything at all which is
376 // certainly not a reasonable default behaviour).
377 int minPage
, maxPage
, selFrom
, selTo
;
378 printout
->GetPageInfo(&minPage
, &maxPage
, &selFrom
, &selTo
);
380 wxPrintDialogData
& pdd
= m_pimpl
->GetPrintDialogData();
381 pdd
.SetFromPage(minPage
);
382 pdd
.SetToPage(maxPage
);
385 return m_pimpl
->Print( parent
, printout
, prompt
);
388 wxDC
* wxPrinter::PrintDialog(wxWindow
*parent
)
390 return m_pimpl
->PrintDialog( parent
);
393 wxPrintDialogData
& wxPrinter::GetPrintDialogData() const
395 return m_pimpl
->GetPrintDialogData();
398 // ---------------------------------------------------------------------------
399 // wxPrintDialogBase: the dialog for printing.
400 // ---------------------------------------------------------------------------
402 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase
, wxDialog
)
404 wxPrintDialogBase::wxPrintDialogBase(wxWindow
*parent
,
406 const wxString
&title
,
410 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Print")) : title
,
415 // ---------------------------------------------------------------------------
416 // wxPrintDialog: the dialog for printing
417 // ---------------------------------------------------------------------------
419 IMPLEMENT_CLASS(wxPrintDialog
, wxObject
)
421 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintDialogData
* data
)
423 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
426 wxPrintDialog::wxPrintDialog(wxWindow
*parent
, wxPrintData
* data
)
428 m_pimpl
= wxPrintFactory::GetFactory()->CreatePrintDialog( parent
, data
);
431 wxPrintDialog::~wxPrintDialog()
436 int wxPrintDialog::ShowModal()
438 return m_pimpl
->ShowModal();
441 wxPrintDialogData
& wxPrintDialog::GetPrintDialogData()
443 return m_pimpl
->GetPrintDialogData();
446 wxPrintData
& wxPrintDialog::GetPrintData()
448 return m_pimpl
->GetPrintData();
451 wxDC
*wxPrintDialog::GetPrintDC()
453 return m_pimpl
->GetPrintDC();
456 // ---------------------------------------------------------------------------
457 // wxPageSetupDialogBase: the page setup dialog
458 // ---------------------------------------------------------------------------
460 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase
, wxDialog
)
462 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow
*parent
,
464 const wxString
&title
,
468 : wxDialog( parent
, id
, title
.empty() ? wxString(_("Page setup")) : title
,
473 // ---------------------------------------------------------------------------
474 // wxPageSetupDialog: the page setup dialog
475 // ---------------------------------------------------------------------------
477 IMPLEMENT_CLASS(wxPageSetupDialog
, wxObject
)
479 wxPageSetupDialog::wxPageSetupDialog(wxWindow
*parent
, wxPageSetupDialogData
*data
)
481 m_pimpl
= wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent
, data
);
484 wxPageSetupDialog::~wxPageSetupDialog()
489 int wxPageSetupDialog::ShowModal()
491 return m_pimpl
->ShowModal();
494 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupDialogData()
496 return m_pimpl
->GetPageSetupDialogData();
500 wxPageSetupDialogData
& wxPageSetupDialog::GetPageSetupData()
502 return m_pimpl
->GetPageSetupDialogData();
505 //----------------------------------------------------------------------------
506 // wxPrintAbortDialog
507 //----------------------------------------------------------------------------
509 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
510 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
513 wxPrintAbortDialog::wxPrintAbortDialog(wxWindow
*parent
,
514 const wxString
& documentTitle
,
518 const wxString
& name
)
519 : wxDialog(parent
, wxID_ANY
, _("Printing"), pos
, size
, style
, name
)
521 wxBoxSizer
*mainSizer
= new wxBoxSizer(wxVERTICAL
);
522 mainSizer
->Add(new wxStaticText(this, wxID_ANY
, _("Please wait while printing...")),
523 wxSizerFlags().Expand().DoubleBorder());
525 wxFlexGridSizer
*gridSizer
= new wxFlexGridSizer(2, wxSize(20, 0));
526 gridSizer
->Add(new wxStaticText(this, wxID_ANY
, _("Document:")));
527 gridSizer
->AddGrowableCol(1);
528 gridSizer
->Add(new wxStaticText(this, wxID_ANY
, documentTitle
));
529 gridSizer
->Add(new wxStaticText(this, wxID_ANY
, _("Progress:")));
530 m_progress
= new wxStaticText(this, wxID_ANY
, _("Preparing"));
531 m_progress
->SetMinSize(wxSize(250, -1));
532 gridSizer
->Add(m_progress
);
533 mainSizer
->Add(gridSizer
, wxSizerFlags().Expand().DoubleBorder(wxLEFT
| wxRIGHT
));
535 mainSizer
->Add(CreateStdDialogButtonSizer(wxCANCEL
),
536 wxSizerFlags().Expand().DoubleBorder());
538 SetSizerAndFit(mainSizer
);
541 void wxPrintAbortDialog::SetProgress(int currentPage
, int totalPages
,
542 int currentCopy
, int totalCopies
)
545 text
.Printf(_("Printing page %d of %d"), currentPage
, totalPages
);
546 if ( totalCopies
> 1 )
547 text
+= wxString::Format(_(" (copy %d of %d)"), currentCopy
, totalCopies
);
548 m_progress
->SetLabel(text
);
551 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
553 wxCHECK_RET( wxPrinterBase::sm_abortWindow
!= NULL
, "OnCancel called twice" );
555 wxPrinterBase::sm_abortIt
= true;
556 wxPrinterBase::sm_abortWindow
->Destroy();
557 wxPrinterBase::sm_abortWindow
= NULL
;
560 //----------------------------------------------------------------------------
562 //----------------------------------------------------------------------------
564 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
566 wxPrintout::wxPrintout(const wxString
& title
)
568 m_printoutTitle
= title
;
572 m_pageWidthPixels
= 0;
573 m_pageHeightPixels
= 0;
581 wxPrintout::~wxPrintout()
585 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
587 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle
);
590 void wxPrintout::OnEndDocument()
595 void wxPrintout::OnBeginPrinting()
599 void wxPrintout::OnEndPrinting()
603 bool wxPrintout::HasPage(int page
)
608 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
616 void wxPrintout::FitThisSizeToPaper(const wxSize
& imageSize
)
618 // Set the DC scale and origin so that the given image size fits within the
619 // entire page and the origin is at the top left corner of the page. Note
620 // that with most printers, portions of the page will be non-printable. Use
621 // this if you're managing your own page margins.
622 if (!m_printoutDC
) return;
623 wxRect paperRect
= GetPaperRectPixels();
625 GetPageSizePixels(&pw
, &ph
);
627 m_printoutDC
->GetSize(&w
, &h
);
628 float scaleX
= ((float(paperRect
.width
) * w
) / (float(pw
) * imageSize
.x
));
629 float scaleY
= ((float(paperRect
.height
) * h
) / (float(ph
) * imageSize
.y
));
630 float actualScale
= wxMin(scaleX
, scaleY
);
631 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
632 m_printoutDC
->SetDeviceOrigin(0, 0);
633 wxRect logicalPaperRect
= GetLogicalPaperRect();
634 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
637 void wxPrintout::FitThisSizeToPage(const wxSize
& imageSize
)
639 // Set the DC scale and origin so that the given image size fits within the
640 // printable area of the page and the origin is at the top left corner of
641 // the printable area.
642 if (!m_printoutDC
) return;
644 m_printoutDC
->GetSize(&w
, &h
);
645 float scaleX
= float(w
) / imageSize
.x
;
646 float scaleY
= float(h
) / imageSize
.y
;
647 float actualScale
= wxMin(scaleX
, scaleY
);
648 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
649 m_printoutDC
->SetDeviceOrigin(0, 0);
652 void wxPrintout::FitThisSizeToPageMargins(const wxSize
& imageSize
, const wxPageSetupDialogData
& pageSetupData
)
654 // Set the DC scale and origin so that the given image size fits within the
655 // page margins defined in the given wxPageSetupDialogData object and the
656 // origin is at the top left corner of the page margins.
657 if (!m_printoutDC
) return;
658 wxRect paperRect
= GetPaperRectPixels();
660 GetPageSizePixels(&pw
, &ph
);
661 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
662 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
664 GetPageSizeMM(&mw
, &mh
);
665 float mmToDeviceX
= float(pw
) / mw
;
666 float mmToDeviceY
= float(ph
) / mh
;
667 wxRect
pageMarginsRect(paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
668 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
669 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
670 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
672 m_printoutDC
->GetSize(&w
, &h
);
673 float scaleX
= (float(pageMarginsRect
.width
) * w
) / (float(pw
) * imageSize
.x
);
674 float scaleY
= (float(pageMarginsRect
.height
) * h
) / (float(ph
) * imageSize
.y
);
675 float actualScale
= wxMin(scaleX
, scaleY
);
676 m_printoutDC
->SetUserScale(actualScale
, actualScale
);
677 m_printoutDC
->SetDeviceOrigin(0, 0);
678 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
679 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
682 void wxPrintout::MapScreenSizeToPaper()
684 // Set the DC scale so that an image on the screen is the same size on the
685 // paper and the origin is at the top left of the paper. Note that with most
686 // printers, portions of the page will be cut off. Use this if you're
687 // managing your own page margins.
688 if (!m_printoutDC
) return;
689 MapScreenSizeToPage();
690 wxRect logicalPaperRect
= GetLogicalPaperRect();
691 SetLogicalOrigin(logicalPaperRect
.x
, logicalPaperRect
.y
);
694 void wxPrintout::MapScreenSizeToPage()
696 // Set the DC scale and origin so that an image on the screen is the same
697 // size on the paper and the origin is at the top left of the printable area.
698 if (!m_printoutDC
) return;
699 int ppiScreenX
, ppiScreenY
;
700 GetPPIScreen(&ppiScreenX
, &ppiScreenY
);
701 int ppiPrinterX
, ppiPrinterY
;
702 GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
);
704 m_printoutDC
->GetSize(&w
, &h
);
705 int pageSizePixelsX
, pageSizePixelsY
;
706 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
707 float userScaleX
= (float(ppiPrinterX
) * w
) / (float(ppiScreenX
) * pageSizePixelsX
);
708 float userScaleY
= (float(ppiPrinterY
) * h
) / (float(ppiScreenY
) * pageSizePixelsY
);
709 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
710 m_printoutDC
->SetDeviceOrigin(0, 0);
713 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData
& pageSetupData
)
715 // Set the DC scale so that an image on the screen is the same size on the
716 // paper and the origin is at the top left of the page margins defined by
717 // the given wxPageSetupDialogData object.
718 if (!m_printoutDC
) return;
719 MapScreenSizeToPage();
720 wxRect logicalPageMarginsRect
= GetLogicalPageMarginsRect(pageSetupData
);
721 SetLogicalOrigin(logicalPageMarginsRect
.x
, logicalPageMarginsRect
.y
);
724 void wxPrintout::MapScreenSizeToDevice()
726 // Set the DC scale so that a screen pixel is the same size as a device
727 // pixel and the origin is at the top left of the printable area.
728 if (!m_printoutDC
) return;
730 m_printoutDC
->GetSize(&w
, &h
);
731 int pageSizePixelsX
, pageSizePixelsY
;
732 GetPageSizePixels(&pageSizePixelsX
, &pageSizePixelsY
);
733 float userScaleX
= float(w
) / pageSizePixelsX
;
734 float userScaleY
= float(h
) / pageSizePixelsY
;
735 m_printoutDC
->SetUserScale(userScaleX
, userScaleY
);
736 m_printoutDC
->SetDeviceOrigin(0, 0);
739 wxRect
wxPrintout::GetLogicalPaperRect() const
741 // Return the rectangle in logical units that corresponds to the paper
743 wxRect paperRect
= GetPaperRectPixels();
745 GetPageSizePixels(&pw
, &ph
);
747 m_printoutDC
->GetSize(&w
, &h
);
748 if (w
== pw
&& h
== ph
) {
749 // this DC matches the printed page, so no scaling
750 return wxRect(m_printoutDC
->DeviceToLogicalX(paperRect
.x
),
751 m_printoutDC
->DeviceToLogicalY(paperRect
.y
),
752 m_printoutDC
->DeviceToLogicalXRel(paperRect
.width
),
753 m_printoutDC
->DeviceToLogicalYRel(paperRect
.height
));
755 // This DC doesn't match the printed page, so we have to scale.
756 float scaleX
= float(w
) / pw
;
757 float scaleY
= float(h
) / ph
;
758 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(paperRect
.x
* scaleX
)),
759 m_printoutDC
->DeviceToLogicalY(wxRound(paperRect
.y
* scaleY
)),
760 m_printoutDC
->DeviceToLogicalXRel(wxRound(paperRect
.width
* scaleX
)),
761 m_printoutDC
->DeviceToLogicalYRel(wxRound(paperRect
.height
* scaleY
)));
764 wxRect
wxPrintout::GetLogicalPageRect() const
766 // Return the rectangle in logical units that corresponds to the printable
769 m_printoutDC
->GetSize(&w
, &h
);
770 return wxRect(m_printoutDC
->DeviceToLogicalX(0),
771 m_printoutDC
->DeviceToLogicalY(0),
772 m_printoutDC
->DeviceToLogicalXRel(w
),
773 m_printoutDC
->DeviceToLogicalYRel(h
));
776 wxRect
wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData
& pageSetupData
) const
778 // Return the rectangle in logical units that corresponds to the region
779 // within the page margins as specified by the given wxPageSetupDialogData
782 // We get the paper size in device units and the margins in mm,
783 // so we need to calculate the conversion with this trick
785 GetPageSizePixels(&pw
, &ph
);
787 GetPageSizeMM(&mw
, &mh
);
788 float mmToDeviceX
= float(pw
) / mw
;
789 float mmToDeviceY
= float(ph
) / mh
;
791 // paper size in device units
792 wxRect paperRect
= GetPaperRectPixels();
795 wxPoint topLeft
= pageSetupData
.GetMarginTopLeft();
796 wxPoint bottomRight
= pageSetupData
.GetMarginBottomRight();
798 // calculate margins in device units
799 wxRect
pageMarginsRect(
800 paperRect
.x
+ wxRound(mmToDeviceX
* topLeft
.x
),
801 paperRect
.y
+ wxRound(mmToDeviceY
* topLeft
.y
),
802 paperRect
.width
- wxRound(mmToDeviceX
* (topLeft
.x
+ bottomRight
.x
)),
803 paperRect
.height
- wxRound(mmToDeviceY
* (topLeft
.y
+ bottomRight
.y
)));
806 m_printoutDC
->GetSize(&w
, &h
);
807 if (w
== pw
&& h
== ph
)
809 // this DC matches the printed page, so no scaling
811 m_printoutDC
->DeviceToLogicalX(pageMarginsRect
.x
),
812 m_printoutDC
->DeviceToLogicalY(pageMarginsRect
.y
),
813 m_printoutDC
->DeviceToLogicalXRel(pageMarginsRect
.width
),
814 m_printoutDC
->DeviceToLogicalYRel(pageMarginsRect
.height
));
817 // This DC doesn't match the printed page, so we have to scale.
818 float scaleX
= float(w
) / pw
;
819 float scaleY
= float(h
) / ph
;
820 return wxRect(m_printoutDC
->DeviceToLogicalX(wxRound(pageMarginsRect
.x
* scaleX
)),
821 m_printoutDC
->DeviceToLogicalY(wxRound(pageMarginsRect
.y
* scaleY
)),
822 m_printoutDC
->DeviceToLogicalXRel(wxRound(pageMarginsRect
.width
* scaleX
)),
823 m_printoutDC
->DeviceToLogicalYRel(wxRound(pageMarginsRect
.height
* scaleY
)));
826 void wxPrintout::SetLogicalOrigin(wxCoord x
, wxCoord y
)
828 // Set the device origin by specifying a point in logical coordinates.
829 m_printoutDC
->SetDeviceOrigin(
830 m_printoutDC
->LogicalToDeviceX(x
),
831 m_printoutDC
->LogicalToDeviceY(y
) );
834 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff
, wxCoord yoff
)
836 // Offset the device origin by a specified distance in device coordinates.
837 wxPoint dev_org
= m_printoutDC
->GetDeviceOrigin();
838 m_printoutDC
->SetDeviceOrigin(
839 dev_org
.x
+ m_printoutDC
->LogicalToDeviceXRel(xoff
),
840 dev_org
.y
+ m_printoutDC
->LogicalToDeviceYRel(yoff
) );
844 //----------------------------------------------------------------------------
846 //----------------------------------------------------------------------------
848 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
850 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
851 EVT_PAINT(wxPreviewCanvas::OnPaint
)
852 EVT_CHAR(wxPreviewCanvas::OnChar
)
853 EVT_IDLE(wxPreviewCanvas::OnIdle
)
854 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
856 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel
)
860 // VZ: the current code doesn't refresh properly without
861 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
862 // really horrible flicker when resizing the preview frame, but without
863 // this style it simply doesn't work correctly at all...
864 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
865 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
866 wxScrolledWindow(parent
, wxID_ANY
, pos
, size
, style
| wxFULL_REPAINT_ON_RESIZE
, name
)
868 m_printPreview
= preview
;
870 // The app workspace colour is always white, but we should have
871 // a contrast with the page.
872 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
873 #elif defined(__WXGTK__)
874 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
876 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
878 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
880 SetScrollbars(10, 10, 100, 100);
883 wxPreviewCanvas::~wxPreviewCanvas()
887 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
894 if (!GetUpdateRegion().IsEmpty())
895 dc.SetClippingRegion( GetUpdateRegion() );
901 m_printPreview
->PaintPage(this, dc
);
905 void wxPreviewCanvas::OnIdle(wxIdleEvent
& event
)
909 // prevent UpdatePageRendering() from being called recursively:
910 static bool s_inIdle
= false;
915 if ( m_printPreview
)
917 if ( m_printPreview
->UpdatePageRendering() )
924 // Responds to colour changes, and passes event on to children.
925 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
928 // The app workspace colour is always white, but we should have
929 // a contrast with the page.
930 wxSystemColour colourIndex
= wxSYS_COLOUR_3DDKSHADOW
;
931 #elif defined(__WXGTK__)
932 wxSystemColour colourIndex
= wxSYS_COLOUR_BTNFACE
;
934 wxSystemColour colourIndex
= wxSYS_COLOUR_APPWORKSPACE
;
936 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex
));
939 // Propagate the event to the non-top-level children
940 wxWindow::OnSysColourChanged(event
);
943 void wxPreviewCanvas::OnChar(wxKeyEvent
&event
)
945 wxPreviewControlBar
* controlBar
= ((wxPreviewFrame
*) GetParent())->GetControlBar();
946 switch (event
.GetKeyCode())
949 controlBar
->OnPrint();
954 controlBar
->DoZoomIn();
957 case WXK_NUMPAD_SUBTRACT
:
959 controlBar
->DoZoomOut();
963 if (!event
.ControlDown())
969 switch(event
.GetKeyCode())
972 controlBar
->OnNext(); break;
974 controlBar
->OnPrevious(); break;
976 controlBar
->OnFirst(); break;
978 controlBar
->OnLast(); break;
986 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent
& event
)
988 wxPreviewControlBar
*
989 controlBar
= wxStaticCast(GetParent(), wxPreviewFrame
)->GetControlBar();
993 if ( event
.ControlDown() && event
.GetWheelRotation() != 0 )
995 int currentZoom
= controlBar
->GetZoomControl();
998 if ( currentZoom
< 100 )
1000 else if ( currentZoom
<= 120 )
1005 if ( event
.GetWheelRotation() > 0 )
1008 int newZoom
= currentZoom
+ delta
;
1011 if ( newZoom
> 200 )
1013 if ( newZoom
!= currentZoom
)
1015 controlBar
->SetZoomControl(newZoom
);
1016 m_printPreview
->SetZoom(newZoom
);
1026 #endif // wxUSE_MOUSEWHEEL
1031 // This is by the controls in the print preview as the maximal (and hence
1032 // longest) page number we may have to display.
1033 enum { MAX_PAGE_NUMBER
= 99999 };
1035 } // anonymous namespace
1037 // ----------------------------------------------------------------------------
1038 // wxPrintPageMaxCtrl
1039 // ----------------------------------------------------------------------------
1041 // A simple static control showing the maximal number of pages.
1042 class wxPrintPageMaxCtrl
: public wxStaticText
1045 wxPrintPageMaxCtrl(wxWindow
*parent
)
1053 parent
->GetTextExtent(MaxAsString(MAX_PAGE_NUMBER
)).x
,
1056 wxST_NO_AUTORESIZE
| wxALIGN_CENTRE
1061 // Set the maximal page to display once we really know what it is.
1062 void SetMaxPage(int maxPage
)
1064 SetLabel(MaxAsString(maxPage
));
1068 static wxString
MaxAsString(int maxPage
)
1070 return wxString::Format("/ %d", maxPage
);
1073 wxDECLARE_NO_COPY_CLASS(wxPrintPageMaxCtrl
);
1076 // ----------------------------------------------------------------------------
1077 // wxPrintPageTextCtrl
1078 // ----------------------------------------------------------------------------
1080 // This text control contains the page number in the specified interval.
1082 // Invalid pages are not accepted and the control contents is validated when it
1083 // loses focus. Conversely, if the user changes the page to another valid one
1084 // or presses Enter, OnGotoPage() method of the preview object will be called.
1085 class wxPrintPageTextCtrl
: public wxTextCtrl
1088 wxPrintPageTextCtrl(wxPreviewControlBar
*preview
)
1089 : wxTextCtrl(preview
,
1093 // We use hardcoded maximal page number for the width
1094 // instead of fitting it to the values we can show because
1095 // the control looks uncomfortably narrow if the real page
1096 // number is just one or two digits.
1099 preview
->GetTextExtent(PageAsString(MAX_PAGE_NUMBER
)).x
,
1103 #if wxUSE_VALIDATORS
1104 , wxTextValidator(wxFILTER_DIGITS
)
1105 #endif // wxUSE_VALIDATORS
1113 Connect(wxEVT_KILL_FOCUS
,
1114 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus
));
1115 Connect(wxEVT_COMMAND_TEXT_ENTER
,
1116 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter
));
1119 // Update the pages range, must be called after OnPreparePrinting() as
1120 // these values are not known before.
1121 void SetPageInfo(int minPage
, int maxPage
)
1123 m_minPage
= minPage
;
1124 m_maxPage
= maxPage
;
1126 // Show the first page by default.
1127 SetPageNumber(minPage
);
1130 // Helpers to conveniently set or get the current page number. Return value
1131 // is 0 if the current controls contents is invalid.
1132 void SetPageNumber(int page
)
1134 wxASSERT( IsValidPage(page
) );
1136 SetValue(PageAsString(page
));
1139 int GetPageNumber() const
1142 if ( !GetValue().ToLong(&value
) || !IsValidPage(value
) )
1145 // Cast is safe because the value is less than (int) m_maxPage.
1146 return static_cast<int>(value
);
1150 static wxString
PageAsString(int page
)
1152 return wxString::Format("%d", page
);
1155 bool IsValidPage(int page
) const
1157 return page
>= m_minPage
&& page
<= m_maxPage
;
1162 const int page
= GetPageNumber();
1167 if ( page
!= m_page
)
1169 // We have a valid page, remember it.
1172 // And notify the owner about the change.
1173 m_preview
->OnGotoPage();
1175 //else: Nothing really changed.
1180 void OnKillFocus(wxFocusEvent
& event
)
1182 if ( !DoChangePage() )
1184 // The current contents is invalid so reset it back to the last
1185 // known good page index.
1186 SetPageNumber(m_page
);
1192 void OnTextEnter(wxCommandEvent
& WXUNUSED(event
))
1198 wxPreviewControlBar
* const m_preview
;
1203 // This is the last valid page value that we had, we revert to it if an
1204 // invalid page is entered.
1207 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl
);
1210 //----------------------------------------------------------------------------
1211 // wxPreviewControlBar
1212 //----------------------------------------------------------------------------
1214 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
1216 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
1217 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
1218 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrintButton
)
1219 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
1220 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
1221 EVT_BUTTON(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnFirstButton
)
1222 EVT_BUTTON(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnLastButton
)
1223 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnZoomInButton
)
1224 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnZoomOutButton
)
1226 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnUpdatePreviousButton
)
1227 EVT_UPDATE_UI(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnUpdateNextButton
)
1228 EVT_UPDATE_UI(wxID_PREVIEW_FIRST
, wxPreviewControlBar::OnUpdateFirstButton
)
1229 EVT_UPDATE_UI(wxID_PREVIEW_LAST
, wxPreviewControlBar::OnUpdateLastButton
)
1230 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN
, wxPreviewControlBar::OnUpdateZoomInButton
)
1231 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT
, wxPreviewControlBar::OnUpdateZoomOutButton
)
1233 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoomChoice
)
1234 EVT_PAINT(wxPreviewControlBar::OnPaint
)
1238 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
1239 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
1240 long style
, const wxString
& name
):
1241 wxPanel(parent
, wxID_ANY
, pos
, size
, style
, name
)
1243 m_printPreview
= preview
;
1244 m_closeButton
= NULL
;
1245 m_zoomControl
= NULL
;
1246 m_currentPageText
= NULL
;
1247 m_maxPageText
= NULL
;
1248 m_buttonFlags
= buttons
;
1251 wxPreviewControlBar::~wxPreviewControlBar()
1255 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1261 dc
.SetPen(*wxBLACK_PEN
);
1262 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1263 dc
.DrawLine( 0, h
-1, w
, h
-1 );
1266 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
1268 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
1272 void wxPreviewControlBar::OnPrint(void)
1274 wxPrintPreviewBase
*preview
= GetPrintPreview();
1275 preview
->Print(true);
1278 void wxPreviewControlBar::OnNext()
1280 if ( IsNextEnabled() )
1281 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1284 void wxPreviewControlBar::OnPrevious()
1286 if ( IsPreviousEnabled() )
1287 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1290 void wxPreviewControlBar::OnFirst()
1292 if ( IsFirstEnabled() )
1293 DoGotoPage(GetPrintPreview()->GetMinPage());
1296 void wxPreviewControlBar::OnLast()
1298 if ( IsLastEnabled() )
1299 DoGotoPage(GetPrintPreview()->GetMaxPage());
1302 bool wxPreviewControlBar::IsNextEnabled() const
1304 wxPrintPreviewBase
*preview
= GetPrintPreview();
1308 const int currentPage
= preview
->GetCurrentPage();
1309 return currentPage
< preview
->GetMaxPage() &&
1310 preview
->GetPrintout()->HasPage(currentPage
+ 1);
1313 bool wxPreviewControlBar::IsPreviousEnabled() const
1315 wxPrintPreviewBase
*preview
= GetPrintPreview();
1319 const int currentPage
= preview
->GetCurrentPage();
1320 return currentPage
> preview
->GetMinPage() &&
1321 preview
->GetPrintout()->HasPage(currentPage
- 1);
1324 bool wxPreviewControlBar::IsFirstEnabled() const
1326 wxPrintPreviewBase
*preview
= GetPrintPreview();
1330 return preview
->GetPrintout()->HasPage(preview
->GetMinPage());
1333 bool wxPreviewControlBar::IsLastEnabled() const
1335 wxPrintPreviewBase
*preview
= GetPrintPreview();
1339 return preview
->GetPrintout()->HasPage(preview
->GetMaxPage());
1342 void wxPreviewControlBar::DoGotoPage(int page
)
1344 wxPrintPreviewBase
*preview
= GetPrintPreview();
1345 wxCHECK_RET( preview
, "Shouldn't be called if there is no preview." );
1347 preview
->SetCurrentPage(page
);
1349 if ( m_currentPageText
)
1350 m_currentPageText
->SetPageNumber(page
);
1353 void wxPreviewControlBar::OnGotoPage()
1355 wxPrintPreviewBase
*preview
= GetPrintPreview();
1358 if (preview
->GetMinPage() > 0)
1360 long currentPage
= m_currentPageText
->GetPageNumber();
1363 if (preview
->GetPrintout()->HasPage(currentPage
))
1365 preview
->SetCurrentPage(currentPage
);
1372 void wxPreviewControlBar::DoZoom()
1374 int zoom
= GetZoomControl();
1375 if (GetPrintPreview())
1376 GetPrintPreview()->SetZoom(zoom
);
1379 bool wxPreviewControlBar::IsZoomInEnabled() const
1381 if ( !m_zoomControl
)
1384 const unsigned sel
= m_zoomControl
->GetSelection();
1385 return sel
< m_zoomControl
->GetCount() - 1;
1388 bool wxPreviewControlBar::IsZoomOutEnabled() const
1390 return m_zoomControl
&& m_zoomControl
->GetSelection() > 0;
1393 void wxPreviewControlBar::DoZoomIn()
1395 if (IsZoomInEnabled())
1397 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() + 1);
1402 void wxPreviewControlBar::DoZoomOut()
1404 if (IsZoomOutEnabled())
1406 m_zoomControl
->SetSelection(m_zoomControl
->GetSelection() - 1);
1414 // Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1415 // sequentially to it in the simplest way possible.
1416 class SizerWithButtons
1419 // Constructor creates the sizer that will hold the buttons and stores the
1420 // parent that will be used for their creation.
1421 SizerWithButtons(wxWindow
*parent
)
1422 : m_sizer(new wxBoxSizer(wxHORIZONTAL
)),
1426 m_needsSeparator
= false;
1429 // Destructor associates the sizer with the parent window.
1432 m_parent
->SetSizer(m_sizer
);
1433 m_sizer
->Fit(m_parent
);
1437 // Add an arbitrary window to the sizer.
1438 void Add(wxWindow
*win
)
1440 if ( m_needsSeparator
)
1442 m_needsSeparator
= false;
1444 m_sizer
->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1447 m_hasContents
= true;
1450 wxSizerFlags().Border(wxLEFT
| wxTOP
| wxBOTTOM
).Center());
1453 // Add a button with the specified id, bitmap and tooltip.
1454 void AddButton(wxWindowID btnId
,
1455 const wxArtID
& artId
,
1456 const wxString
& tooltip
)
1458 // We don't use (smaller) images inside a button with a text label but
1459 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1460 // wxART_BUTTON here.
1461 wxBitmap bmp
= wxArtProvider::GetBitmap(artId
, wxART_TOOLBAR
);
1462 wxBitmapButton
* const btn
= new wxBitmapButton(m_parent
, btnId
, bmp
);
1463 btn
->SetToolTip(tooltip
);
1468 // Add a control at the right end of the window. This should be called last
1469 // as everything else added after it will be added on the right side too.
1470 void AddAtEnd(wxWindow
*win
)
1472 m_sizer
->AddStretchSpacer();
1474 wxSizerFlags().Border(wxTOP
| wxBOTTOM
| wxRIGHT
).Center());
1477 // Indicates the end of a group of buttons, a separator will be added after
1481 if ( m_hasContents
)
1483 m_needsSeparator
= true;
1484 m_hasContents
= false;
1489 wxSizer
* const m_sizer
;
1490 wxWindow
* const m_parent
;
1492 // If true, we have some controls since the last group beginning. This is
1493 // used to avoid inserting two consecutive separators if EndOfGroup() is
1497 // If true, a separator should be inserted before adding the next button.
1498 bool m_needsSeparator
;
1500 wxDECLARE_NO_COPY_CLASS(SizerWithButtons
);
1503 } // anonymous namespace
1505 void wxPreviewControlBar::CreateButtons()
1507 SizerWithButtons
sizer(this);
1509 // Print button group (a single button).
1510 if (m_buttonFlags
& wxPREVIEW_PRINT
)
1512 sizer
.AddButton(wxID_PREVIEW_PRINT
, wxART_PRINT
, _("Print"));
1516 // Page selection buttons group.
1517 if (m_buttonFlags
& wxPREVIEW_FIRST
)
1519 sizer
.AddButton(wxID_PREVIEW_FIRST
, wxART_GOTO_FIRST
, _("First page"));
1522 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
1524 sizer
.AddButton(wxID_PREVIEW_PREVIOUS
, wxART_GO_BACK
, _("Previous page"));
1527 if (m_buttonFlags
& wxPREVIEW_GOTO
)
1529 m_currentPageText
= new wxPrintPageTextCtrl(this);
1530 sizer
.Add(m_currentPageText
);
1532 m_maxPageText
= new wxPrintPageMaxCtrl(this);
1533 sizer
.Add(m_maxPageText
);
1536 if (m_buttonFlags
& wxPREVIEW_NEXT
)
1538 sizer
.AddButton(wxID_PREVIEW_NEXT
, wxART_GO_FORWARD
, _("Next page"));
1541 if (m_buttonFlags
& wxPREVIEW_LAST
)
1543 sizer
.AddButton(wxID_PREVIEW_LAST
, wxART_GOTO_LAST
, _("Last page"));
1548 // Zoom controls group.
1549 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
1551 sizer
.AddButton(wxID_PREVIEW_ZOOM_OUT
, wxART_MINUS
, _("Zoom Out"));
1553 wxString choices
[] =
1555 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1556 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1557 wxT("120%"), wxT("150%"), wxT("200%")
1559 int n
= WXSIZEOF(choices
);
1561 m_zoomControl
= new wxChoice( this, wxID_PREVIEW_ZOOM
, wxDefaultPosition
, wxSize(70,wxDefaultCoord
), n
, choices
, 0 );
1562 sizer
.Add(m_zoomControl
);
1563 SetZoomControl(m_printPreview
->GetZoom());
1565 sizer
.AddButton(wxID_PREVIEW_ZOOM_IN
, wxART_PLUS
, _("Zoom In"));
1570 // Close button group (single button again).
1571 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("&Close"));
1572 sizer
.AddAtEnd(m_closeButton
);
1575 void wxPreviewControlBar::SetPageInfo(int minPage
, int maxPage
)
1577 if ( m_currentPageText
)
1578 m_currentPageText
->SetPageInfo(minPage
, maxPage
);
1580 if ( m_maxPageText
)
1581 m_maxPageText
->SetMaxPage(maxPage
);
1584 void wxPreviewControlBar::SetZoomControl(int zoom
)
1588 int n
, count
= m_zoomControl
->GetCount();
1590 for (n
=0; n
<count
; n
++)
1592 if (m_zoomControl
->GetString(n
).BeforeFirst(wxT('%')).ToLong(&val
) &&
1593 (val
>= long(zoom
)))
1595 m_zoomControl
->SetSelection(n
);
1600 m_zoomControl
->SetSelection(count
-1);
1604 int wxPreviewControlBar::GetZoomControl()
1606 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxEmptyString
))
1609 if (m_zoomControl
->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val
))
1621 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
1623 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
1624 EVT_CHAR_HOOK(wxPreviewFrame::OnChar
)
1625 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
1628 void wxPreviewFrame::OnChar(wxKeyEvent
&event
)
1630 if ( event
.GetKeyCode() == WXK_ESCAPE
)
1640 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxWindow
*parent
, const wxString
& title
,
1641 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
1642 wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
, name
)
1644 m_printPreview
= preview
;
1645 m_controlBar
= NULL
;
1646 m_previewCanvas
= NULL
;
1647 m_windowDisabler
= NULL
;
1648 m_modalityKind
= wxPreviewFrame_NonModal
;
1650 // Give the application icon
1652 wxFrame
* topFrame
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
);
1654 SetIcons(topFrame
->GetIcons());
1658 wxPreviewFrame::~wxPreviewFrame()
1660 wxPrintout
*printout
= m_printPreview
->GetPrintout();
1664 m_printPreview
->SetPrintout(NULL
);
1665 m_printPreview
->SetCanvas(NULL
);
1666 m_printPreview
->SetFrame(NULL
);
1669 m_previewCanvas
->SetPreview(NULL
);
1670 delete m_printPreview
;
1673 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
1675 // Reenable any windows we disabled by undoing whatever we did in our
1677 switch ( m_modalityKind
)
1679 case wxPreviewFrame_AppModal
:
1680 delete m_windowDisabler
;
1681 m_windowDisabler
= NULL
;
1684 case wxPreviewFrame_WindowModal
:
1686 GetParent()->Enable();
1689 case wxPreviewFrame_NonModal
:
1696 void wxPreviewFrame::InitializeWithModality(wxPreviewFrameModalityKind kind
)
1704 m_printPreview
->SetCanvas(m_previewCanvas
);
1705 m_printPreview
->SetFrame(this);
1707 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
1709 item0
->Add( m_controlBar
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1710 item0
->Add( m_previewCanvas
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
, 5 );
1712 SetAutoLayout( true );
1715 m_modalityKind
= kind
;
1716 switch ( m_modalityKind
)
1718 case wxPreviewFrame_AppModal
:
1719 // Disable everything.
1720 m_windowDisabler
= new wxWindowDisabler( this );
1723 case wxPreviewFrame_WindowModal
:
1724 // Disable our parent if we have one.
1726 GetParent()->Disable();
1729 case wxPreviewFrame_NonModal
:
1730 // Nothing to do, we don't need to disable any windows.
1734 if ( m_modalityKind
!= wxPreviewFrame_NonModal
)
1736 // Behave like modal dialogs, don't show in taskbar. This implies
1737 // removing the minimize box, because minimizing windows without
1738 // taskbar entry is confusing.
1739 SetWindowStyle((GetWindowStyle() & ~wxMINIMIZE_BOX
) | wxFRAME_NO_TASKBAR
);
1744 m_printPreview
->AdjustScrollbars(m_previewCanvas
);
1745 m_previewCanvas
->SetFocus();
1746 m_controlBar
->SetFocus();
1749 void wxPreviewFrame::CreateCanvas()
1751 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
1754 void wxPreviewFrame::CreateControlBar()
1756 long buttons
= wxPREVIEW_DEFAULT
;
1757 if (m_printPreview
->GetPrintoutForPrinting())
1758 buttons
|= wxPREVIEW_PRINT
;
1760 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this);
1761 m_controlBar
->CreateButtons();
1768 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
1770 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1771 wxPrintout
*printoutForPrinting
,
1775 m_printDialogData
= (*data
);
1777 Init(printout
, printoutForPrinting
);
1780 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
1781 wxPrintout
*printoutForPrinting
,
1782 wxPrintDialogData
*data
)
1785 m_printDialogData
= (*data
);
1787 Init(printout
, printoutForPrinting
);
1790 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
1791 wxPrintout
*printoutForPrinting
)
1794 m_previewPrintout
= printout
;
1795 if (m_previewPrintout
)
1796 m_previewPrintout
->SetPreview(static_cast<wxPrintPreview
*>(this));
1798 m_printPrintout
= printoutForPrinting
;
1800 m_previewCanvas
= NULL
;
1801 m_previewFrame
= NULL
;
1802 m_previewBitmap
= NULL
;
1803 m_previewFailed
= false;
1807 m_leftMargin
= 2*wxSizerFlags::GetDefaultBorder();
1810 m_printingPrepared
= false;
1815 wxPrintPreviewBase::~wxPrintPreviewBase()
1817 if (m_previewPrintout
)
1818 delete m_previewPrintout
;
1819 if (m_previewBitmap
)
1820 delete m_previewBitmap
;
1821 if (m_printPrintout
)
1822 delete m_printPrintout
;
1825 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
1827 if (m_currentPage
== pageNum
)
1830 m_currentPage
= pageNum
;
1832 InvalidatePreviewBitmap();
1834 if (m_previewCanvas
)
1836 AdjustScrollbars(m_previewCanvas
);
1838 m_previewCanvas
->Refresh();
1839 m_previewCanvas
->SetFocus();
1844 int wxPrintPreviewBase::GetCurrentPage() const
1845 { return m_currentPage
; }
1846 void wxPrintPreviewBase::SetPrintout(wxPrintout
*printout
)
1847 { m_previewPrintout
= printout
; }
1848 wxPrintout
*wxPrintPreviewBase::GetPrintout() const
1849 { return m_previewPrintout
; }
1850 wxPrintout
*wxPrintPreviewBase::GetPrintoutForPrinting() const
1851 { return m_printPrintout
; }
1852 void wxPrintPreviewBase::SetFrame(wxFrame
*frame
)
1853 { m_previewFrame
= frame
; }
1854 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas
*canvas
)
1855 { m_previewCanvas
= canvas
; }
1856 wxFrame
*wxPrintPreviewBase::GetFrame() const
1857 { return m_previewFrame
; }
1858 wxPreviewCanvas
*wxPrintPreviewBase::GetCanvas() const
1859 { return m_previewCanvas
; }
1861 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas
*canvas
, wxRect
& pageRect
, wxRect
& paperRect
)
1863 // Calculate the rectangles for the printable area of the page and the
1864 // entire paper as they appear on the canvas on-screen.
1865 int canvasWidth
, canvasHeight
;
1866 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
1868 float zoomScale
= float(m_currentZoom
) / 100;
1869 float screenPrintableWidth
= zoomScale
* m_pageWidth
* m_previewScaleX
;
1870 float screenPrintableHeight
= zoomScale
* m_pageHeight
* m_previewScaleY
;
1872 wxRect devicePaperRect
= m_previewPrintout
->GetPaperRectPixels();
1873 wxCoord devicePrintableWidth
, devicePrintableHeight
;
1874 m_previewPrintout
->GetPageSizePixels(&devicePrintableWidth
, &devicePrintableHeight
);
1875 float scaleX
= screenPrintableWidth
/ devicePrintableWidth
;
1876 float scaleY
= screenPrintableHeight
/ devicePrintableHeight
;
1877 paperRect
.width
= wxCoord(scaleX
* devicePaperRect
.width
);
1878 paperRect
.height
= wxCoord(scaleY
* devicePaperRect
.height
);
1880 paperRect
.x
= wxCoord((canvasWidth
- paperRect
.width
)/ 2.0);
1881 if (paperRect
.x
< m_leftMargin
)
1882 paperRect
.x
= m_leftMargin
;
1883 paperRect
.y
= wxCoord((canvasHeight
- paperRect
.height
)/ 2.0);
1884 if (paperRect
.y
< m_topMargin
)
1885 paperRect
.y
= m_topMargin
;
1887 pageRect
.x
= paperRect
.x
- wxCoord(scaleX
* devicePaperRect
.x
);
1888 pageRect
.y
= paperRect
.y
- wxCoord(scaleY
* devicePaperRect
.y
);
1889 pageRect
.width
= wxCoord(screenPrintableWidth
);
1890 pageRect
.height
= wxCoord(screenPrintableHeight
);
1894 void wxPrintPreviewBase::InvalidatePreviewBitmap()
1896 wxDELETE(m_previewBitmap
);
1897 // if there was a problem with rendering the preview, try again now
1898 // that it changed in some way (less memory may be needed, for example):
1899 m_previewFailed
= false;
1902 bool wxPrintPreviewBase::UpdatePageRendering()
1904 if ( m_previewBitmap
)
1907 if ( m_previewFailed
)
1910 if ( !RenderPage(m_currentPage
) )
1912 m_previewFailed
= true; // don't waste time failing again
1919 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
1921 DrawBlankPage(canvas
, dc
);
1923 if (!m_previewBitmap
)
1928 wxRect pageRect
, paperRect
;
1929 CalcRects(canvas
, pageRect
, paperRect
);
1931 temp_dc
.SelectObject(*m_previewBitmap
);
1933 dc
.Blit(pageRect
.x
, pageRect
.y
,
1934 m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
1936 temp_dc
.SelectObject(wxNullBitmap
);
1940 // Adjusts the scrollbars for the current scale
1941 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas
*canvas
)
1946 wxRect pageRect
, paperRect
;
1947 CalcRects(canvas
, pageRect
, paperRect
);
1948 int totalWidth
= paperRect
.width
+ 2 * m_leftMargin
;
1949 int totalHeight
= paperRect
.height
+ 2 * m_topMargin
;
1950 int scrollUnitsX
= totalWidth
/ 10;
1951 int scrollUnitsY
= totalHeight
/ 10;
1952 wxSize virtualSize
= canvas
->GetVirtualSize();
1953 if (virtualSize
.GetWidth() != totalWidth
|| virtualSize
.GetHeight() != totalHeight
)
1954 canvas
->SetScrollbars(10, 10, scrollUnitsX
, scrollUnitsY
, 0, 0, true);
1957 bool wxPrintPreviewBase::RenderPageIntoDC(wxDC
& dc
, int pageNum
)
1959 m_previewPrintout
->SetDC(&dc
);
1960 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
1962 // Need to delay OnPreparePrinting() until here, so we have enough
1963 // information and a wxDC.
1964 if (!m_printingPrepared
)
1966 m_printingPrepared
= true;
1968 m_previewPrintout
->OnPreparePrinting();
1970 m_previewPrintout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
1972 // Update the wxPreviewControlBar page range display.
1973 if ( m_previewFrame
)
1975 wxPreviewControlBar
* const
1976 controlBar
= ((wxPreviewFrame
*)m_previewFrame
)->GetControlBar();
1978 controlBar
->SetPageInfo(m_minPage
, m_maxPage
);
1982 m_previewPrintout
->OnBeginPrinting();
1984 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
1986 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
1990 m_previewPrintout
->OnPrintPage(pageNum
);
1991 m_previewPrintout
->OnEndDocument();
1992 m_previewPrintout
->OnEndPrinting();
1994 m_previewPrintout
->SetDC(NULL
);
1999 bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap
& bmp
, int pageNum
)
2001 wxMemoryDC memoryDC
;
2002 memoryDC
.SelectObject(bmp
);
2005 return RenderPageIntoDC(memoryDC
, pageNum
);
2008 bool wxPrintPreviewBase::RenderPage(int pageNum
)
2012 if (!m_previewCanvas
)
2014 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
2018 wxRect pageRect
, paperRect
;
2019 CalcRects(m_previewCanvas
, pageRect
, paperRect
);
2021 if (!m_previewBitmap
)
2023 m_previewBitmap
= new wxBitmap(pageRect
.width
, pageRect
.height
);
2025 if (!m_previewBitmap
|| !m_previewBitmap
->IsOk())
2027 InvalidatePreviewBitmap();
2028 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2033 if ( !RenderPageIntoBitmap(*m_previewBitmap
, pageNum
) )
2035 InvalidatePreviewBitmap();
2036 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
2043 status
= wxString::Format(_("Page %d of %d"), pageNum
, m_maxPage
);
2045 status
= wxString::Format(_("Page %d"), pageNum
);
2048 m_previewFrame
->SetStatusText(status
);
2054 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2056 wxRect pageRect
, paperRect
;
2058 CalcRects(canvas
, pageRect
, paperRect
);
2060 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
2061 wxCoord shadowOffset
= 4;
2063 dc
.SetPen(*wxBLACK_PEN
);
2064 dc
.SetBrush(*wxBLACK_BRUSH
);
2065 dc
.DrawRectangle(paperRect
.x
+ shadowOffset
, paperRect
.y
+ paperRect
.height
+ 1,
2066 paperRect
.width
, shadowOffset
);
2068 dc
.DrawRectangle(paperRect
.x
+ paperRect
.width
, paperRect
.y
+ shadowOffset
,
2069 shadowOffset
, paperRect
.height
);
2071 // Draw blank page allowing for 1-pixel border AROUND the actual paper
2072 dc
.SetPen(*wxBLACK_PEN
);
2073 dc
.SetBrush(*wxWHITE_BRUSH
);
2074 dc
.DrawRectangle(paperRect
.x
- 2, paperRect
.y
- 1,
2075 paperRect
.width
+ 3, paperRect
.height
+ 2);
2080 void wxPrintPreviewBase::SetZoom(int percent
)
2082 if (m_currentZoom
== percent
)
2085 m_currentZoom
= percent
;
2087 InvalidatePreviewBitmap();
2089 if (m_previewCanvas
)
2091 AdjustScrollbars(m_previewCanvas
);
2092 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
2093 m_previewCanvas
->ClearBackground();
2094 m_previewCanvas
->Refresh();
2095 m_previewCanvas
->SetFocus();
2099 wxPrintDialogData
& wxPrintPreviewBase::GetPrintDialogData()
2101 return m_printDialogData
;
2104 int wxPrintPreviewBase::GetZoom() const
2105 { return m_currentZoom
; }
2106 int wxPrintPreviewBase::GetMaxPage() const
2107 { return m_maxPage
; }
2108 int wxPrintPreviewBase::GetMinPage() const
2109 { return m_minPage
; }
2110 bool wxPrintPreviewBase::IsOk() const
2112 void wxPrintPreviewBase::SetOk(bool ok
)
2115 //----------------------------------------------------------------------------
2117 //----------------------------------------------------------------------------
2119 IMPLEMENT_CLASS(wxPrintPreview
, wxPrintPreviewBase
)
2121 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2122 wxPrintout
*printoutForPrinting
,
2123 wxPrintDialogData
*data
) :
2124 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2126 m_pimpl
= wxPrintFactory::GetFactory()->
2127 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2130 wxPrintPreview::wxPrintPreview(wxPrintout
*printout
,
2131 wxPrintout
*printoutForPrinting
,
2132 wxPrintData
*data
) :
2133 wxPrintPreviewBase( printout
, printoutForPrinting
, data
)
2135 m_pimpl
= wxPrintFactory::GetFactory()->
2136 CreatePrintPreview( printout
, printoutForPrinting
, data
);
2139 wxPrintPreview::~wxPrintPreview()
2143 // don't delete twice
2144 m_printPrintout
= NULL
;
2145 m_previewPrintout
= NULL
;
2146 m_previewBitmap
= NULL
;
2149 bool wxPrintPreview::SetCurrentPage(int pageNum
)
2151 return m_pimpl
->SetCurrentPage( pageNum
);
2154 int wxPrintPreview::GetCurrentPage() const
2156 return m_pimpl
->GetCurrentPage();
2159 void wxPrintPreview::SetPrintout(wxPrintout
*printout
)
2161 m_pimpl
->SetPrintout( printout
);
2164 wxPrintout
*wxPrintPreview::GetPrintout() const
2166 return m_pimpl
->GetPrintout();
2169 wxPrintout
*wxPrintPreview::GetPrintoutForPrinting() const
2171 return m_pimpl
->GetPrintoutForPrinting();
2174 void wxPrintPreview::SetFrame(wxFrame
*frame
)
2176 m_pimpl
->SetFrame( frame
);
2179 void wxPrintPreview::SetCanvas(wxPreviewCanvas
*canvas
)
2181 m_pimpl
->SetCanvas( canvas
);
2184 wxFrame
*wxPrintPreview::GetFrame() const
2186 return m_pimpl
->GetFrame();
2189 wxPreviewCanvas
*wxPrintPreview::GetCanvas() const
2191 return m_pimpl
->GetCanvas();
2194 bool wxPrintPreview::PaintPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2196 return m_pimpl
->PaintPage( canvas
, dc
);
2199 bool wxPrintPreview::UpdatePageRendering()
2201 return m_pimpl
->UpdatePageRendering();
2204 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas
*canvas
, wxDC
& dc
)
2206 return m_pimpl
->DrawBlankPage( canvas
, dc
);
2209 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas
*canvas
)
2211 m_pimpl
->AdjustScrollbars( canvas
);
2214 bool wxPrintPreview::RenderPage(int pageNum
)
2216 return m_pimpl
->RenderPage( pageNum
);
2219 void wxPrintPreview::SetZoom(int percent
)
2221 m_pimpl
->SetZoom( percent
);
2224 int wxPrintPreview::GetZoom() const
2226 return m_pimpl
->GetZoom();
2229 wxPrintDialogData
& wxPrintPreview::GetPrintDialogData()
2231 return m_pimpl
->GetPrintDialogData();
2234 int wxPrintPreview::GetMaxPage() const
2236 return m_pimpl
->GetMaxPage();
2239 int wxPrintPreview::GetMinPage() const
2241 return m_pimpl
->GetMinPage();
2244 bool wxPrintPreview::IsOk() const
2246 return m_pimpl
->IsOk();
2249 void wxPrintPreview::SetOk(bool ok
)
2251 m_pimpl
->SetOk( ok
);
2254 bool wxPrintPreview::Print(bool interactive
)
2256 return m_pimpl
->Print( interactive
);
2259 void wxPrintPreview::DetermineScaling()
2261 m_pimpl
->DetermineScaling();
2264 #endif // wxUSE_PRINTING_ARCHITECTURE