remove just added wxCoordRound() (see patch 1586499)
[wxWidgets.git] / src / common / prntbase.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/prntbase.cpp
3 // Purpose: Printing framework base class implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_PRINTING_ARCHITECTURE
20
21 #include "wx/dcprint.h"
22
23 #ifndef WX_PRECOMP
24 #if defined(__WXMSW__)
25 #include "wx/msw/wrapcdlg.h"
26 #endif // MSW
27 #include "wx/utils.h"
28 #include "wx/dc.h"
29 #include "wx/app.h"
30 #include "wx/math.h"
31 #include "wx/msgdlg.h"
32 #include "wx/layout.h"
33 #include "wx/choice.h"
34 #include "wx/button.h"
35 #include "wx/settings.h"
36 #include "wx/dcmemory.h"
37 #include "wx/stattext.h"
38 #include "wx/intl.h"
39 #include "wx/textdlg.h"
40 #include "wx/sizer.h"
41 #include "wx/module.h"
42 #endif // !WX_PRECOMP
43
44 #include "wx/prntbase.h"
45 #include "wx/printdlg.h"
46 #include "wx/print.h"
47 #include "wx/dcprint.h"
48
49 #include <stdlib.h>
50 #include <string.h>
51
52 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
53 #include "wx/msw/printdlg.h"
54 #elif defined(__WXMAC__)
55 #include "wx/mac/printdlg.h"
56 #include "wx/mac/private/print.h"
57 #else
58 #include "wx/generic/prntdlgg.h"
59 #include "wx/dcps.h"
60 #endif
61
62 #ifdef __WXMSW__
63 #ifndef __WIN32__
64 #include <print.h>
65 #endif
66 #endif // __WXMSW__
67
68 //----------------------------------------------------------------------------
69 // wxPrintFactory
70 //----------------------------------------------------------------------------
71
72 wxPrintFactory *wxPrintFactory::m_factory = NULL;
73
74 void wxPrintFactory::SetPrintFactory( wxPrintFactory *factory )
75 {
76 if (wxPrintFactory::m_factory)
77 delete wxPrintFactory::m_factory;
78
79 wxPrintFactory::m_factory = factory;
80 }
81
82 wxPrintFactory *wxPrintFactory::GetFactory()
83 {
84 if (!wxPrintFactory::m_factory)
85 wxPrintFactory::m_factory = new wxNativePrintFactory;
86
87 return wxPrintFactory::m_factory;
88 }
89
90 //----------------------------------------------------------------------------
91 // wxNativePrintFactory
92 //----------------------------------------------------------------------------
93
94 wxPrinterBase *wxNativePrintFactory::CreatePrinter( wxPrintDialogData *data )
95 {
96 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
97 return new wxWindowsPrinter( data );
98 #elif defined(__WXMAC__)
99 return new wxMacPrinter( data );
100 #elif defined(__WXPM__)
101 return new wxOS2Printer( data );
102 #else
103 return new wxPostScriptPrinter( data );
104 #endif
105 }
106
107 wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
108 wxPrintout *printout, wxPrintDialogData *data )
109 {
110 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
111 return new wxWindowsPrintPreview( preview, printout, data );
112 #elif defined(__WXMAC__)
113 return new wxMacPrintPreview( preview, printout, data );
114 #elif defined(__WXPM__)
115 return new wxOS2PrintPreview( preview, printout, data );
116 #else
117 return new wxPostScriptPrintPreview( preview, printout, data );
118 #endif
119 }
120
121 wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
122 wxPrintout *printout, wxPrintData *data )
123 {
124 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
125 return new wxWindowsPrintPreview( preview, printout, data );
126 #elif defined(__WXMAC__)
127 return new wxMacPrintPreview( preview, printout, data );
128 #elif defined(__WXPM__)
129 return new wxOS2PrintPreview( preview, printout, data );
130 #else
131 return new wxPostScriptPrintPreview( preview, printout, data );
132 #endif
133 }
134
135 wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
136 wxPrintDialogData *data )
137 {
138 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
139 return new wxWindowsPrintDialog( parent, data );
140 #elif defined(__WXMAC__)
141 return new wxMacPrintDialog( parent, data );
142 #else
143 return new wxGenericPrintDialog( parent, data );
144 #endif
145 }
146
147 wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
148 wxPrintData *data )
149 {
150 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
151 return new wxWindowsPrintDialog( parent, data );
152 #elif defined(__WXMAC__)
153 return new wxMacPrintDialog( parent, data );
154 #else
155 return new wxGenericPrintDialog( parent, data );
156 #endif
157 }
158
159 wxPageSetupDialogBase *wxNativePrintFactory::CreatePageSetupDialog( wxWindow *parent,
160 wxPageSetupDialogData *data )
161 {
162 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
163 return new wxWindowsPageSetupDialog( parent, data );
164 #elif defined(__WXMAC__)
165 return new wxMacPageSetupDialog( parent, data );
166 #else
167 return new wxGenericPageSetupDialog( parent, data );
168 #endif
169 }
170
171 bool wxNativePrintFactory::HasPrintSetupDialog()
172 {
173 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
174 return false;
175 #elif defined(__WXMAC__)
176 return false;
177 #else
178 // Only here do we need to provide the print setup
179 // dialog ourselves, the other platforms either have
180 // none, don't make it accessible or let you configure
181 // the printer from the wxPrintDialog anyway.
182 return true;
183 #endif
184
185 }
186
187 wxDialog *wxNativePrintFactory::CreatePrintSetupDialog( wxWindow *parent,
188 wxPrintData *data )
189 {
190 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
191 wxUnusedVar(parent);
192 wxUnusedVar(data);
193 return NULL;
194 #elif defined(__WXMAC__)
195 wxUnusedVar(parent);
196 wxUnusedVar(data);
197 return NULL;
198 #else
199 // Only here do we need to provide the print setup
200 // dialog ourselves, the other platforms either have
201 // none, don't make it accessible or let you configure
202 // the printer from the wxPrintDialog anyway.
203 return new wxGenericPrintSetupDialog( parent, data );
204 #endif
205 }
206
207 wxDC* wxNativePrintFactory::CreatePrinterDC( const wxPrintData& data )
208 {
209 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
210 return new wxPrinterDC(data);
211 #elif defined(__WXMAC__)
212 return new wxPrinterDC(data);
213 #else
214 return new wxPostScriptDC(data);
215 #endif
216 }
217
218 bool wxNativePrintFactory::HasOwnPrintToFile()
219 {
220 // Only relevant for PostScript and here the
221 // setup dialog provides no "print to file"
222 // option. In the GNOME setup dialog, the
223 // setup dialog has its own print to file.
224 return false;
225 }
226
227 bool wxNativePrintFactory::HasPrinterLine()
228 {
229 // Only relevant for PostScript for now
230 return true;
231 }
232
233 wxString wxNativePrintFactory::CreatePrinterLine()
234 {
235 // Only relevant for PostScript for now
236
237 // We should query "lpstat -d" here
238 return _("Generic PostScript");
239 }
240
241 bool wxNativePrintFactory::HasStatusLine()
242 {
243 // Only relevant for PostScript for now
244 return true;
245 }
246
247 wxString wxNativePrintFactory::CreateStatusLine()
248 {
249 // Only relevant for PostScript for now
250
251 // We should query "lpstat -r" or "lpstat -p" here
252 return _("Ready");
253 }
254
255 wxPrintNativeDataBase *wxNativePrintFactory::CreatePrintNativeData()
256 {
257 #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
258 return new wxWindowsPrintNativeData;
259 #elif defined(__WXMAC__)
260 return new wxMacCarbonPrintData;
261 #else
262 return new wxPostScriptPrintNativeData;
263 #endif
264 }
265
266 //----------------------------------------------------------------------------
267 // wxPrintNativeDataBase
268 //----------------------------------------------------------------------------
269
270 IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase, wxObject)
271
272 wxPrintNativeDataBase::wxPrintNativeDataBase()
273 {
274 m_ref = 1;
275 }
276
277 //----------------------------------------------------------------------------
278 // wxPrintFactoryModule
279 //----------------------------------------------------------------------------
280
281 class wxPrintFactoryModule: public wxModule
282 {
283 public:
284 wxPrintFactoryModule() {}
285 bool OnInit() { return true; }
286 void OnExit() { wxPrintFactory::SetPrintFactory( NULL ); }
287
288 private:
289 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule)
290 };
291
292 IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule, wxModule)
293
294 //----------------------------------------------------------------------------
295 // wxPrinterBase
296 //----------------------------------------------------------------------------
297
298 IMPLEMENT_CLASS(wxPrinterBase, wxObject)
299
300 wxPrinterBase::wxPrinterBase(wxPrintDialogData *data)
301 {
302 m_currentPrintout = (wxPrintout *) NULL;
303 sm_abortWindow = (wxWindow *) NULL;
304 sm_abortIt = false;
305 if (data)
306 m_printDialogData = (*data);
307 sm_lastError = wxPRINTER_NO_ERROR;
308 }
309
310 wxWindow *wxPrinterBase::sm_abortWindow = (wxWindow *) NULL;
311 bool wxPrinterBase::sm_abortIt = false;
312 wxPrinterError wxPrinterBase::sm_lastError = wxPRINTER_NO_ERROR;
313
314 wxPrinterBase::~wxPrinterBase()
315 {
316 }
317
318 wxWindow *wxPrinterBase::CreateAbortWindow(wxWindow *parent, wxPrintout * printout)
319 {
320 wxPrintAbortDialog *dialog = new wxPrintAbortDialog(parent, _("Printing ") , wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE);
321
322 wxBoxSizer *button_sizer = new wxBoxSizer( wxVERTICAL );
323 button_sizer->Add( new wxStaticText(dialog, wxID_ANY, _("Please wait while printing\n") + printout->GetTitle() ), 0, wxALL, 10 );
324 button_sizer->Add( new wxButton( dialog, wxID_CANCEL, wxT("Cancel") ), 0, wxALL | wxALIGN_CENTER, 10 );
325
326 dialog->SetAutoLayout( true );
327 dialog->SetSizer( button_sizer );
328
329 button_sizer->Fit(dialog);
330 button_sizer->SetSizeHints (dialog) ;
331
332 return dialog;
333 }
334
335 void wxPrinterBase::ReportError(wxWindow *parent, wxPrintout *WXUNUSED(printout), const wxString& message)
336 {
337 wxMessageBox(message, _("Printing Error"), wxOK, parent);
338 }
339
340 wxPrintDialogData& wxPrinterBase::GetPrintDialogData() const
341 {
342 return (wxPrintDialogData&) m_printDialogData;
343 }
344
345 //----------------------------------------------------------------------------
346 // wxPrinter
347 //----------------------------------------------------------------------------
348
349 IMPLEMENT_CLASS(wxPrinter, wxPrinterBase)
350
351 wxPrinter::wxPrinter(wxPrintDialogData *data)
352 {
353 m_pimpl = wxPrintFactory::GetFactory()->CreatePrinter( data );
354 }
355
356 wxPrinter::~wxPrinter()
357 {
358 delete m_pimpl;
359 }
360
361 wxWindow *wxPrinter::CreateAbortWindow(wxWindow *parent, wxPrintout *printout)
362 {
363 return m_pimpl->CreateAbortWindow( parent, printout );
364 }
365
366 void wxPrinter::ReportError(wxWindow *parent, wxPrintout *printout, const wxString& message)
367 {
368 m_pimpl->ReportError( parent, printout, message );
369 }
370
371 bool wxPrinter::Setup(wxWindow *parent)
372 {
373 return m_pimpl->Setup( parent );
374 }
375
376 bool wxPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
377 {
378 return m_pimpl->Print( parent, printout, prompt );
379 }
380
381 wxDC* wxPrinter::PrintDialog(wxWindow *parent)
382 {
383 return m_pimpl->PrintDialog( parent );
384 }
385
386 wxPrintDialogData& wxPrinter::GetPrintDialogData() const
387 {
388 return m_pimpl->GetPrintDialogData();
389 }
390
391 // ---------------------------------------------------------------------------
392 // wxPrintDialogBase: the dialog for printing.
393 // ---------------------------------------------------------------------------
394
395 IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase, wxDialog)
396
397 wxPrintDialogBase::wxPrintDialogBase(wxWindow *parent,
398 wxWindowID id,
399 const wxString &title,
400 const wxPoint &pos,
401 const wxSize &size,
402 long style)
403 : wxDialog( parent, id, title.empty() ? wxString(_("Print")) : title,
404 pos, size, style )
405 {
406 }
407
408 // ---------------------------------------------------------------------------
409 // wxPrintDialog: the dialog for printing
410 // ---------------------------------------------------------------------------
411
412 IMPLEMENT_CLASS(wxPrintDialog, wxObject)
413
414 wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintDialogData* data)
415 {
416 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
417 }
418
419 wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintData* data)
420 {
421 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
422 }
423
424 wxPrintDialog::~wxPrintDialog()
425 {
426 delete m_pimpl;
427 }
428
429 int wxPrintDialog::ShowModal()
430 {
431 return m_pimpl->ShowModal();
432 }
433
434 wxPrintDialogData& wxPrintDialog::GetPrintDialogData()
435 {
436 return m_pimpl->GetPrintDialogData();
437 }
438
439 wxPrintData& wxPrintDialog::GetPrintData()
440 {
441 return m_pimpl->GetPrintData();
442 }
443
444 wxDC *wxPrintDialog::GetPrintDC()
445 {
446 return m_pimpl->GetPrintDC();
447 }
448
449 // ---------------------------------------------------------------------------
450 // wxPageSetupDialogBase: the page setup dialog
451 // ---------------------------------------------------------------------------
452
453 IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase, wxDialog)
454
455 wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow *parent,
456 wxWindowID id,
457 const wxString &title,
458 const wxPoint &pos,
459 const wxSize &size,
460 long style)
461 : wxDialog( parent, id, title.empty() ? wxString(_("Page setup")) : title,
462 pos, size, style )
463 {
464 }
465
466 // ---------------------------------------------------------------------------
467 // wxPageSetupDialog: the page setup dialog
468 // ---------------------------------------------------------------------------
469
470 IMPLEMENT_CLASS(wxPageSetupDialog, wxObject)
471
472 wxPageSetupDialog::wxPageSetupDialog(wxWindow *parent, wxPageSetupDialogData *data )
473 {
474 m_pimpl = wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent, data );
475 }
476
477 wxPageSetupDialog::~wxPageSetupDialog()
478 {
479 delete m_pimpl;
480 }
481
482 int wxPageSetupDialog::ShowModal()
483 {
484 return m_pimpl->ShowModal();
485 }
486
487 wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupDialogData()
488 {
489 return m_pimpl->GetPageSetupDialogData();
490 }
491
492 // old name
493 wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupData()
494 {
495 return m_pimpl->GetPageSetupDialogData();
496 }
497
498 //----------------------------------------------------------------------------
499 // wxPrintAbortDialog
500 //----------------------------------------------------------------------------
501
502 BEGIN_EVENT_TABLE(wxPrintAbortDialog, wxDialog)
503 EVT_BUTTON(wxID_CANCEL, wxPrintAbortDialog::OnCancel)
504 END_EVENT_TABLE()
505
506 void wxPrintAbortDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
507 {
508 wxPrinterBase::sm_abortIt = true;
509 wxPrinterBase::sm_abortWindow->Show(false);
510 wxPrinterBase::sm_abortWindow->Close(true);
511 wxPrinterBase::sm_abortWindow = (wxWindow *) NULL;
512 }
513
514 //----------------------------------------------------------------------------
515 // wxPrintout
516 //----------------------------------------------------------------------------
517
518 IMPLEMENT_ABSTRACT_CLASS(wxPrintout, wxObject)
519
520 wxPrintout::wxPrintout(const wxString& title)
521 {
522 m_printoutTitle = title ;
523 m_printoutDC = (wxDC *) NULL;
524 m_pageWidthMM = 0;
525 m_pageHeightMM = 0;
526 m_pageWidthPixels = 0;
527 m_pageHeightPixels = 0;
528 m_PPIScreenX = 0;
529 m_PPIScreenY = 0;
530 m_PPIPrinterX = 0;
531 m_PPIPrinterY = 0;
532 m_isPreview = false;
533 }
534
535 wxPrintout::~wxPrintout()
536 {
537 }
538
539 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage), int WXUNUSED(endPage))
540 {
541 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle);
542 }
543
544 void wxPrintout::OnEndDocument()
545 {
546 GetDC()->EndDoc();
547 }
548
549 void wxPrintout::OnBeginPrinting()
550 {
551 }
552
553 void wxPrintout::OnEndPrinting()
554 {
555 }
556
557 bool wxPrintout::HasPage(int page)
558 {
559 return (page == 1);
560 }
561
562 void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toPage)
563 {
564 *minPage = 1;
565 *maxPage = 32000;
566 *fromPage = 1;
567 *toPage = 1;
568 }
569
570 void wxPrintout::FitThisSizeToPaper(const wxSize& imageSize)
571 {
572 // Set the DC scale and origin so that the given image size fits within the
573 // entire page and the origin is at the top left corner of the page. Note
574 // that with most printers, portions of the page will be non-printable. Use
575 // this if you're managing your own page margins.
576 if (!m_printoutDC) return;
577 wxRect paperRect = GetPaperRectPixels();
578 wxCoord pw, ph;
579 GetPageSizePixels(&pw, &ph);
580 wxCoord w, h;
581 m_printoutDC->GetSize(&w, &h);
582 float scaleX = ((float(paperRect.width) * w) / (float(pw) * imageSize.x));
583 float scaleY = ((float(paperRect.height) * h) / (float(ph) * imageSize.y));
584 float actualScale = wxMin(scaleX, scaleY);
585 m_printoutDC->SetUserScale(actualScale, actualScale);
586 m_printoutDC->SetDeviceOrigin(0, 0);
587 wxRect logicalPaperRect = GetLogicalPaperRect();
588 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
589 }
590
591 void wxPrintout::FitThisSizeToPage(const wxSize& imageSize)
592 {
593 // Set the DC scale and origin so that the given image size fits within the
594 // printable area of the page and the origin is at the top left corner of
595 // the printable area.
596 if (!m_printoutDC) return;
597 int w, h;
598 m_printoutDC->GetSize(&w, &h);
599 float scaleX = float(w) / imageSize.x;
600 float scaleY = float(h) / imageSize.y;
601 float actualScale = wxMin(scaleX, scaleY);
602 m_printoutDC->SetUserScale(actualScale, actualScale);
603 m_printoutDC->SetDeviceOrigin(0, 0);
604 }
605
606 void wxPrintout::FitThisSizeToPageMargins(const wxSize& imageSize, const wxPageSetupDialogData& pageSetupData)
607 {
608 // Set the DC scale and origin so that the given image size fits within the
609 // page margins defined in the given wxPageSetupDialogData object and the
610 // origin is at the top left corner of the page margins.
611 if (!m_printoutDC) return;
612 wxRect paperRect = GetPaperRectPixels();
613 wxCoord pw, ph;
614 GetPageSizePixels(&pw, &ph);
615 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
616 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
617 wxCoord mw, mh;
618 GetPageSizeMM(&mw, &mh);
619 float mmToDeviceX = float(pw) / mw;
620 float mmToDeviceY = float(ph) / mh;
621 wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x),
622 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
623 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
624 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
625 wxCoord w, h;
626 m_printoutDC->GetSize(&w, &h);
627 float scaleX = (float(pageMarginsRect.width) * w) / (float(pw) * imageSize.x);
628 float scaleY = (float(pageMarginsRect.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 logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
633 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
634 }
635
636 void wxPrintout::MapScreenSizeToPaper()
637 {
638 // Set the DC scale so that an image on the screen is the same size on the
639 // paper and the origin is at the top left of the paper. Note that with most
640 // printers, portions of the page will be cut off. Use this if you're
641 // managing your own page margins.
642 if (!m_printoutDC) return;
643 MapScreenSizeToPage();
644 wxRect logicalPaperRect = GetLogicalPaperRect();
645 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
646 }
647
648 void wxPrintout::MapScreenSizeToPage()
649 {
650 // Set the DC scale and origin so that an image on the screen is the same
651 // size on the paper and the origin is at the top left of the printable area.
652 if (!m_printoutDC) return;
653 int ppiScreenX, ppiScreenY;
654 GetPPIScreen(&ppiScreenX, &ppiScreenY);
655 int ppiPrinterX, ppiPrinterY;
656 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
657 int w, h;
658 m_printoutDC->GetSize(&w, &h);
659 int pageSizePixelsX, pageSizePixelsY;
660 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
661 float userScaleX = (float(ppiPrinterX) * w) / (float(ppiScreenX) * pageSizePixelsX);
662 float userScaleY = (float(ppiPrinterY) * h) / (float(ppiScreenY) * pageSizePixelsY);
663 m_printoutDC->SetUserScale(userScaleX, userScaleY);
664 m_printoutDC->SetDeviceOrigin(0, 0);
665 }
666
667 void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData& pageSetupData)
668 {
669 // Set the DC scale so that an image on the screen is the same size on the
670 // paper and the origin is at the top left of the page margins defined by
671 // the given wxPageSetupDialogData object.
672 if (!m_printoutDC) return;
673 MapScreenSizeToPage();
674 wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
675 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
676 }
677
678 void wxPrintout::MapScreenSizeToDevice()
679 {
680 // Set the DC scale so that a screen pixel is the same size as a device
681 // pixel and the origin is at the top left of the printable area.
682 if (!m_printoutDC) return;
683 int w, h;
684 m_printoutDC->GetSize(&w, &h);
685 int pageSizePixelsX, pageSizePixelsY;
686 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
687 float userScaleX = float(w) / pageSizePixelsX;
688 float userScaleY = float(h) / pageSizePixelsY;
689 m_printoutDC->SetUserScale(userScaleX, userScaleY);
690 m_printoutDC->SetDeviceOrigin(0, 0);
691 }
692
693 wxRect wxPrintout::GetLogicalPaperRect() const
694 {
695 // Return the rectangle in logical units that corresponds to the paper
696 // rectangle.
697 wxRect paperRect = GetPaperRectPixels();
698 wxCoord pw, ph;
699 GetPageSizePixels(&pw, &ph);
700 wxCoord w, h;
701 m_printoutDC->GetSize(&w, &h);
702 if (w == pw && h == ph) {
703 // this DC matches the printed page, so no scaling
704 return wxRect(m_printoutDC->DeviceToLogicalX(paperRect.x),
705 m_printoutDC->DeviceToLogicalY(paperRect.y),
706 m_printoutDC->DeviceToLogicalXRel(paperRect.width),
707 m_printoutDC->DeviceToLogicalYRel(paperRect.height));
708 }
709 // This DC doesn't match the printed page, so we have to scale.
710 float scaleX = float(w) / pw;
711 float scaleY = float(h) / ph;
712 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(paperRect.x * scaleX)),
713 m_printoutDC->DeviceToLogicalY(wxRound(paperRect.y * scaleY)),
714 m_printoutDC->DeviceToLogicalXRel(wxRound(paperRect.width * scaleX)),
715 m_printoutDC->DeviceToLogicalYRel(wxRound(paperRect.height * scaleY)));
716 }
717
718 wxRect wxPrintout::GetLogicalPageRect() const
719 {
720 // Return the rectangle in logical units that corresponds to the printable
721 // area.
722 int w, h;
723 m_printoutDC->GetSize(&w, &h);
724 return wxRect(m_printoutDC->DeviceToLogicalX(0),
725 m_printoutDC->DeviceToLogicalY(0),
726 m_printoutDC->DeviceToLogicalXRel(w),
727 m_printoutDC->DeviceToLogicalYRel(h));
728 }
729
730 wxRect wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData& pageSetupData) const
731 {
732 // Return the rectangle in logical units that corresponds to the region
733 // within the page margins as specified by the given wxPageSetupDialogData
734 // object.
735 wxRect paperRect = GetPaperRectPixels();
736 wxCoord pw, ph;
737 GetPageSizePixels(&pw, &ph);
738 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
739 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
740 wxCoord mw, mh;
741 GetPageSizeMM(&mw, &mh);
742 float mmToDeviceX = float(pw) / mw;
743 float mmToDeviceY = float(ph) / mh;
744 wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x),
745 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
746 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
747 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
748 wxCoord w, h;
749 m_printoutDC->GetSize(&w, &h);
750 if (w == pw && h == ph) {
751 // this DC matches the printed page, so no scaling
752 return wxRect(m_printoutDC->DeviceToLogicalX(pageMarginsRect.x),
753 m_printoutDC->DeviceToLogicalY(pageMarginsRect.y),
754 m_printoutDC->DeviceToLogicalXRel(pageMarginsRect.width),
755 m_printoutDC->DeviceToLogicalYRel(pageMarginsRect.height));
756 }
757 // This DC doesn't match the printed page, so we have to scale.
758 float scaleX = float(w) / pw;
759 float scaleY = float(h) / ph;
760 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(pageMarginsRect.x * scaleX)),
761 m_printoutDC->DeviceToLogicalY(wxRound(pageMarginsRect.y * scaleY)),
762 m_printoutDC->DeviceToLogicalXRel(wxRound(pageMarginsRect.width * scaleX)),
763 m_printoutDC->DeviceToLogicalYRel(wxRound(pageMarginsRect.height * scaleY)));
764 }
765
766 void wxPrintout::SetLogicalOrigin(wxCoord x, wxCoord y)
767 {
768 // Set the device origin by specifying a point in logical coordinates.
769 m_printoutDC->SetDeviceOrigin(m_printoutDC->LogicalToDeviceX(x),
770 m_printoutDC->LogicalToDeviceY(y));
771 }
772
773 void wxPrintout::OffsetLogicalOrigin(wxCoord xoff, wxCoord yoff)
774 {
775 // Offset the device origin by a specified distance in device coordinates.
776 wxCoord x = m_printoutDC->LogicalToDeviceX(0);
777 wxCoord y = m_printoutDC->LogicalToDeviceY(0);
778 m_printoutDC->SetDeviceOrigin(x + m_printoutDC->LogicalToDeviceXRel(xoff),
779 y + m_printoutDC->LogicalToDeviceYRel(yoff));
780 }
781
782
783 //----------------------------------------------------------------------------
784 // wxPreviewCanvas
785 //----------------------------------------------------------------------------
786
787 IMPLEMENT_CLASS(wxPreviewCanvas, wxWindow)
788
789 BEGIN_EVENT_TABLE(wxPreviewCanvas, wxScrolledWindow)
790 EVT_PAINT(wxPreviewCanvas::OnPaint)
791 EVT_CHAR(wxPreviewCanvas::OnChar)
792 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged)
793 #if wxUSE_MOUSEWHEEL
794 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel)
795 #endif
796 END_EVENT_TABLE()
797
798 // VZ: the current code doesn't refresh properly without
799 // wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
800 // really horrible flicker when resizing the preview frame, but without
801 // this style it simply doesn't work correctly at all...
802 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase *preview, wxWindow *parent,
803 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
804 wxScrolledWindow(parent, wxID_ANY, pos, size, style | wxFULL_REPAINT_ON_RESIZE, name)
805 {
806 m_printPreview = preview;
807 #ifdef __WXMAC__
808 // The app workspace colour is always white, but we should have
809 // a contrast with the page.
810 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
811 #elif defined(__WXGTK__)
812 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
813 #else
814 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
815 #endif
816 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
817
818 SetScrollbars(10, 10, 100, 100);
819 }
820
821 wxPreviewCanvas::~wxPreviewCanvas()
822 {
823 }
824
825 void wxPreviewCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
826 {
827 wxPaintDC dc(this);
828 PrepareDC( dc );
829
830 /*
831 #ifdef __WXGTK__
832 if (!GetUpdateRegion().IsEmpty())
833 dc.SetClippingRegion( GetUpdateRegion() );
834 #endif
835 */
836
837 if (m_printPreview)
838 {
839 m_printPreview->PaintPage(this, dc);
840 }
841 }
842
843 // Responds to colour changes, and passes event on to children.
844 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent& event)
845 {
846 #ifdef __WXMAC__
847 // The app workspace colour is always white, but we should have
848 // a contrast with the page.
849 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
850 #elif defined(__WXGTK__)
851 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
852 #else
853 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
854 #endif
855 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
856 Refresh();
857
858 // Propagate the event to the non-top-level children
859 wxWindow::OnSysColourChanged(event);
860 }
861
862 void wxPreviewCanvas::OnChar(wxKeyEvent &event)
863 {
864 wxPreviewControlBar* controlBar = ((wxPreviewFrame*) GetParent())->GetControlBar();
865 if (event.GetKeyCode() == WXK_ESCAPE)
866 {
867 ((wxPreviewFrame*) GetParent())->Close(true);
868 return;
869 }
870 else if (event.GetKeyCode() == WXK_TAB)
871 {
872 controlBar->OnGoto();
873 return;
874 }
875 else if (event.GetKeyCode() == WXK_RETURN)
876 {
877 controlBar->OnPrint();
878 return;
879 }
880
881 if (!event.ControlDown())
882 {
883 event.Skip();
884 return;
885 }
886
887 switch(event.GetKeyCode())
888 {
889 case WXK_PAGEDOWN:
890 controlBar->OnNext(); break;
891 case WXK_PAGEUP:
892 controlBar->OnPrevious(); break;
893 case WXK_HOME:
894 controlBar->OnFirst(); break;
895 case WXK_END:
896 controlBar->OnLast(); break;
897 default:
898 event.Skip();
899 }
900 }
901
902 #if wxUSE_MOUSEWHEEL
903
904 void wxPreviewCanvas::OnMouseWheel(wxMouseEvent& event)
905 {
906 wxPreviewControlBar *
907 controlBar = wxStaticCast(GetParent(), wxPreviewFrame)->GetControlBar();
908
909 if ( controlBar )
910 {
911 if ( event.ControlDown() && event.GetWheelRotation() != 0 )
912 {
913 int currentZoom = controlBar->GetZoomControl();
914
915 int delta;
916 if ( currentZoom < 100 )
917 delta = 5;
918 else if ( currentZoom <= 120 )
919 delta = 10;
920 else
921 delta = 50;
922
923 if ( event.GetWheelRotation() > 0 )
924 delta = -delta;
925
926 int newZoom = currentZoom + delta;
927 if ( newZoom < 10 )
928 newZoom = 10;
929 if ( newZoom > 200 )
930 newZoom = 200;
931 if ( newZoom != currentZoom )
932 {
933 controlBar->SetZoomControl(newZoom);
934 m_printPreview->SetZoom(newZoom);
935 Refresh();
936 }
937 return;
938 }
939 }
940
941 event.Skip();
942 }
943
944 #endif // wxUSE_MOUSEWHEEL
945
946 //----------------------------------------------------------------------------
947 // wxPreviewControlBar
948 //----------------------------------------------------------------------------
949
950 IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
951
952 BEGIN_EVENT_TABLE(wxPreviewControlBar, wxPanel)
953 EVT_BUTTON(wxID_PREVIEW_CLOSE, wxPreviewControlBar::OnWindowClose)
954 EVT_BUTTON(wxID_PREVIEW_PRINT, wxPreviewControlBar::OnPrintButton)
955 EVT_BUTTON(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnPreviousButton)
956 EVT_BUTTON(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnNextButton)
957 EVT_BUTTON(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnFirstButton)
958 EVT_BUTTON(wxID_PREVIEW_LAST, wxPreviewControlBar::OnLastButton)
959 EVT_BUTTON(wxID_PREVIEW_GOTO, wxPreviewControlBar::OnGotoButton)
960 EVT_CHOICE(wxID_PREVIEW_ZOOM, wxPreviewControlBar::OnZoom)
961 EVT_PAINT(wxPreviewControlBar::OnPaint)
962 END_EVENT_TABLE()
963
964 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
965 wxWindow *parent, const wxPoint& pos, const wxSize& size,
966 long style, const wxString& name):
967 wxPanel(parent, wxID_ANY, pos, size, style, name)
968 {
969 m_printPreview = preview;
970 m_closeButton = (wxButton *) NULL;
971 m_nextPageButton = (wxButton *) NULL;
972 m_previousPageButton = (wxButton *) NULL;
973 m_printButton = (wxButton *) NULL;
974 m_zoomControl = (wxChoice *) NULL;
975 m_buttonFlags = buttons;
976 }
977
978 wxPreviewControlBar::~wxPreviewControlBar()
979 {
980 }
981
982 void wxPreviewControlBar::OnPaint(wxPaintEvent& WXUNUSED(event))
983 {
984 wxPaintDC dc(this);
985
986 int w, h;
987 GetSize(&w, &h);
988 dc.SetPen(*wxBLACK_PEN);
989 dc.SetBrush(*wxTRANSPARENT_BRUSH);
990 dc.DrawLine( 0, h-1, w, h-1 );
991 }
992
993 void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
994 {
995 wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
996 frame->Close(true);
997 }
998
999 void wxPreviewControlBar::OnPrint(void)
1000 {
1001 wxPrintPreviewBase *preview = GetPrintPreview();
1002 preview->Print(true);
1003 }
1004
1005 void wxPreviewControlBar::OnNext(void)
1006 {
1007 wxPrintPreviewBase *preview = GetPrintPreview();
1008 if (preview)
1009 {
1010 int currentPage = preview->GetCurrentPage();
1011 if ((preview->GetMaxPage() > 0) &&
1012 (currentPage < preview->GetMaxPage()) &&
1013 preview->GetPrintout()->HasPage(currentPage + 1))
1014 {
1015 preview->SetCurrentPage(currentPage + 1);
1016 }
1017 }
1018 }
1019
1020 void wxPreviewControlBar::OnPrevious(void)
1021 {
1022 wxPrintPreviewBase *preview = GetPrintPreview();
1023 if (preview)
1024 {
1025 int currentPage = preview->GetCurrentPage();
1026 if ((preview->GetMinPage() > 0) &&
1027 (currentPage > preview->GetMinPage()) &&
1028 preview->GetPrintout()->HasPage(currentPage - 1))
1029 {
1030 preview->SetCurrentPage(currentPage - 1);
1031 }
1032 }
1033 }
1034
1035 void wxPreviewControlBar::OnFirst(void)
1036 {
1037 wxPrintPreviewBase *preview = GetPrintPreview();
1038 if (preview)
1039 {
1040 int currentPage = preview->GetMinPage();
1041 if (preview->GetPrintout()->HasPage(currentPage))
1042 {
1043 preview->SetCurrentPage(currentPage);
1044 }
1045 }
1046 }
1047
1048 void wxPreviewControlBar::OnLast(void)
1049 {
1050 wxPrintPreviewBase *preview = GetPrintPreview();
1051 if (preview)
1052 {
1053 int currentPage = preview->GetMaxPage();
1054 if (preview->GetPrintout()->HasPage(currentPage))
1055 {
1056 preview->SetCurrentPage(currentPage);
1057 }
1058 }
1059 }
1060
1061 void wxPreviewControlBar::OnGoto(void)
1062 {
1063 wxPrintPreviewBase *preview = GetPrintPreview();
1064 if (preview)
1065 {
1066 long currentPage;
1067
1068 if (preview->GetMinPage() > 0)
1069 {
1070 wxString strPrompt;
1071 wxString strPage;
1072
1073 strPrompt.Printf( _("Enter a page number between %d and %d:"),
1074 preview->GetMinPage(), preview->GetMaxPage());
1075 strPage.Printf( wxT("%d"), preview->GetCurrentPage() );
1076
1077 strPage =
1078 wxGetTextFromUser( strPrompt, _("Goto Page"), strPage, GetParent());
1079
1080 if ( strPage.ToLong( &currentPage ) )
1081 if (preview->GetPrintout()->HasPage(currentPage))
1082 {
1083 preview->SetCurrentPage(currentPage);
1084 }
1085 }
1086 }
1087 }
1088
1089 void wxPreviewControlBar::OnZoom(wxCommandEvent& WXUNUSED(event))
1090 {
1091 int zoom = GetZoomControl();
1092 if (GetPrintPreview())
1093 GetPrintPreview()->SetZoom(zoom);
1094 }
1095
1096 void wxPreviewControlBar::CreateButtons()
1097 {
1098 SetSize(0, 0, 400, 40);
1099
1100 wxBoxSizer *item0 = new wxBoxSizer( wxHORIZONTAL );
1101
1102 m_closeButton = new wxButton( this, wxID_PREVIEW_CLOSE, _("&Close"), wxDefaultPosition, wxDefaultSize, 0 );
1103 item0->Add( m_closeButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1104
1105 if (m_buttonFlags & wxPREVIEW_PRINT)
1106 {
1107 m_printButton = new wxButton( this, wxID_PREVIEW_PRINT, _("&Print..."), wxDefaultPosition, wxDefaultSize, 0 );
1108 item0->Add( m_printButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1109 }
1110
1111 // Exact-fit buttons are too tiny on wxUniversal
1112 int navButtonStyle;
1113 wxSize navButtonSize;
1114 #ifdef __WXUNIVERSAL__
1115 navButtonStyle = 0;
1116 navButtonSize = wxSize(40, m_closeButton->GetSize().y);
1117 #else
1118 navButtonStyle = wxBU_EXACTFIT;
1119 navButtonSize = wxDefaultSize;
1120 #endif
1121
1122 if (m_buttonFlags & wxPREVIEW_FIRST)
1123 {
1124 m_firstPageButton = new wxButton( this, wxID_PREVIEW_FIRST, _("|<<"), wxDefaultPosition, navButtonSize, navButtonStyle );
1125 item0->Add( m_firstPageButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1126 }
1127
1128 if (m_buttonFlags & wxPREVIEW_PREVIOUS)
1129 {
1130 m_previousPageButton = new wxButton( this, wxID_PREVIEW_PREVIOUS, _("<<"), wxDefaultPosition, navButtonSize, navButtonStyle );
1131 item0->Add( m_previousPageButton, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 );
1132 }
1133
1134 if (m_buttonFlags & wxPREVIEW_NEXT)
1135 {
1136 m_nextPageButton = new wxButton( this, wxID_PREVIEW_NEXT, _(">>"), wxDefaultPosition, navButtonSize, navButtonStyle );
1137 item0->Add( m_nextPageButton, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 );
1138 }
1139
1140 if (m_buttonFlags & wxPREVIEW_LAST)
1141 {
1142 m_lastPageButton = new wxButton( this, wxID_PREVIEW_LAST, _(">>|"), wxDefaultPosition, navButtonSize, navButtonStyle );
1143 item0->Add( m_lastPageButton, 0, wxALIGN_CENTRE|wxRIGHT|wxTOP|wxBOTTOM, 5 );
1144 }
1145
1146 if (m_buttonFlags & wxPREVIEW_GOTO)
1147 {
1148 m_gotoPageButton = new wxButton( this, wxID_PREVIEW_GOTO, _("&Goto..."), wxDefaultPosition, wxDefaultSize, 0 );
1149 item0->Add( m_gotoPageButton, 0, wxALIGN_CENTRE|wxALL, 5 );
1150 }
1151
1152 if (m_buttonFlags & wxPREVIEW_ZOOM)
1153 {
1154 wxString choices[] =
1155 {
1156 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1157 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1158 wxT("120%"), wxT("150%"), wxT("200%")
1159 };
1160 int n = WXSIZEOF(choices);
1161
1162 m_zoomControl = new wxChoice( this, wxID_PREVIEW_ZOOM, wxDefaultPosition, wxSize(70,wxDefaultCoord), n, choices, 0 );
1163 item0->Add( m_zoomControl, 0, wxALIGN_CENTRE|wxALL, 5 );
1164 SetZoomControl(m_printPreview->GetZoom());
1165 }
1166
1167 SetSizer(item0);
1168 item0->Fit(this);
1169 }
1170
1171 void wxPreviewControlBar::SetZoomControl(int zoom)
1172 {
1173 if (m_zoomControl)
1174 {
1175 int n, count = m_zoomControl->GetCount();
1176 long val;
1177 for (n=0; n<count; n++)
1178 {
1179 if (m_zoomControl->GetString(n).BeforeFirst(wxT('%')).ToLong(&val) &&
1180 (val >= long(zoom)))
1181 {
1182 m_zoomControl->SetSelection(n);
1183 return;
1184 }
1185 }
1186
1187 m_zoomControl->SetSelection(count-1);
1188 }
1189 }
1190
1191 int wxPreviewControlBar::GetZoomControl()
1192 {
1193 if (m_zoomControl && (m_zoomControl->GetStringSelection() != wxEmptyString))
1194 {
1195 long val;
1196 if (m_zoomControl->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val))
1197 return int(val);
1198 }
1199
1200 return 0;
1201 }
1202
1203
1204 /*
1205 * Preview frame
1206 */
1207
1208 IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
1209
1210 BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
1211 EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
1212 END_EVENT_TABLE()
1213
1214 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
1215 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
1216 wxFrame(parent, wxID_ANY, title, pos, size, style, name)
1217 {
1218 m_printPreview = preview;
1219 m_controlBar = NULL;
1220 m_previewCanvas = NULL;
1221 m_windowDisabler = NULL;
1222
1223 // Give the application icon
1224 #ifdef __WXMSW__
1225 wxFrame* topFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
1226 if (topFrame)
1227 SetIcon(topFrame->GetIcon());
1228 #endif
1229 }
1230
1231 wxPreviewFrame::~wxPreviewFrame()
1232 {
1233 }
1234
1235 void wxPreviewFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
1236 {
1237 if (m_windowDisabler)
1238 delete m_windowDisabler;
1239
1240 // Need to delete the printout and the print preview
1241 wxPrintout *printout = m_printPreview->GetPrintout();
1242 if (printout)
1243 {
1244 delete printout;
1245 m_printPreview->SetPrintout(NULL);
1246 m_printPreview->SetCanvas(NULL);
1247 m_printPreview->SetFrame(NULL);
1248 }
1249 delete m_printPreview;
1250
1251 Destroy();
1252 }
1253
1254 void wxPreviewFrame::Initialize()
1255 {
1256 #if wxUSE_STATUSBAR
1257 CreateStatusBar();
1258 #endif
1259 CreateCanvas();
1260 CreateControlBar();
1261
1262 m_printPreview->SetCanvas(m_previewCanvas);
1263 m_printPreview->SetFrame(this);
1264
1265 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
1266
1267 item0->Add( m_controlBar, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1268 item0->Add( m_previewCanvas, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1269
1270 SetAutoLayout( true );
1271 SetSizer( item0 );
1272
1273 m_windowDisabler = new wxWindowDisabler(this);
1274
1275 Layout();
1276
1277 m_printPreview->AdjustScrollbars(m_previewCanvas);
1278 m_previewCanvas->SetFocus();
1279 m_controlBar->SetFocus();
1280 }
1281
1282 void wxPreviewFrame::CreateCanvas()
1283 {
1284 m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
1285 }
1286
1287 void wxPreviewFrame::CreateControlBar()
1288 {
1289 long buttons = wxPREVIEW_DEFAULT;
1290 if (m_printPreview->GetPrintoutForPrinting())
1291 buttons |= wxPREVIEW_PRINT;
1292
1293 m_controlBar = new wxPreviewControlBar(m_printPreview, buttons, this, wxPoint(0,0), wxSize(400, 40));
1294 m_controlBar->CreateButtons();
1295 }
1296
1297 /*
1298 * Print preview
1299 */
1300
1301 IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
1302
1303 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1304 wxPrintout *printoutForPrinting,
1305 wxPrintData *data)
1306 {
1307 if (data)
1308 m_printDialogData = (*data);
1309
1310 Init(printout, printoutForPrinting);
1311 }
1312
1313 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1314 wxPrintout *printoutForPrinting,
1315 wxPrintDialogData *data)
1316 {
1317 if (data)
1318 m_printDialogData = (*data);
1319
1320 Init(printout, printoutForPrinting);
1321 }
1322
1323 void wxPrintPreviewBase::Init(wxPrintout *printout,
1324 wxPrintout *printoutForPrinting)
1325 {
1326 m_isOk = true;
1327 m_previewPrintout = printout;
1328 if (m_previewPrintout)
1329 m_previewPrintout->SetIsPreview(true);
1330
1331 m_printPrintout = printoutForPrinting;
1332
1333 m_previewCanvas = NULL;
1334 m_previewFrame = NULL;
1335 m_previewBitmap = NULL;
1336 m_currentPage = 1;
1337 m_currentZoom = 70;
1338 m_topMargin = 40;
1339 m_leftMargin = 40;
1340 m_pageWidth = 0;
1341 m_pageHeight = 0;
1342 m_printingPrepared = false;
1343 m_minPage = 1;
1344 m_maxPage = 1;
1345 }
1346
1347 wxPrintPreviewBase::~wxPrintPreviewBase()
1348 {
1349 if (m_previewPrintout)
1350 delete m_previewPrintout;
1351 if (m_previewBitmap)
1352 delete m_previewBitmap;
1353 if (m_printPrintout)
1354 delete m_printPrintout;
1355 }
1356
1357 bool wxPrintPreviewBase::SetCurrentPage(int pageNum)
1358 {
1359 if (m_currentPage == pageNum)
1360 return true;
1361
1362 m_currentPage = pageNum;
1363 if (m_previewBitmap)
1364 {
1365 delete m_previewBitmap;
1366 m_previewBitmap = NULL;
1367 }
1368
1369 if (m_previewCanvas)
1370 {
1371 AdjustScrollbars(m_previewCanvas);
1372
1373 if (!RenderPage(pageNum))
1374 return false;
1375 m_previewCanvas->Refresh();
1376 m_previewCanvas->SetFocus();
1377 }
1378 return true;
1379 }
1380
1381 int wxPrintPreviewBase::GetCurrentPage() const
1382 { return m_currentPage; }
1383 void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
1384 { m_previewPrintout = printout; }
1385 wxPrintout *wxPrintPreviewBase::GetPrintout() const
1386 { return m_previewPrintout; }
1387 wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
1388 { return m_printPrintout; }
1389 void wxPrintPreviewBase::SetFrame(wxFrame *frame)
1390 { m_previewFrame = frame; }
1391 void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
1392 { m_previewCanvas = canvas; }
1393 wxFrame *wxPrintPreviewBase::GetFrame() const
1394 { return m_previewFrame; }
1395 wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
1396 { return m_previewCanvas; }
1397
1398 void wxPrintPreviewBase::CalcRects(wxPreviewCanvas *canvas, wxRect& pageRect, wxRect& paperRect)
1399 {
1400 // Calculate the rectangles for the printable area of the page and the
1401 // entire paper as they appear on the canvas on-screen.
1402 int canvasWidth, canvasHeight;
1403 canvas->GetSize(&canvasWidth, &canvasHeight);
1404
1405 float zoomScale = float(m_currentZoom) / 100;
1406 float screenPrintableWidth = zoomScale * m_pageWidth * m_previewScaleX;
1407 float screenPrintableHeight = zoomScale * m_pageHeight * m_previewScaleY;
1408
1409 wxRect devicePaperRect = m_previewPrintout->GetPaperRectPixels();
1410 wxCoord devicePrintableWidth, devicePrintableHeight;
1411 m_previewPrintout->GetPageSizePixels(&devicePrintableWidth, &devicePrintableHeight);
1412 float scaleX = screenPrintableWidth / devicePrintableWidth;
1413 float scaleY = screenPrintableHeight / devicePrintableHeight;
1414 paperRect.width = wxCoord(scaleX * devicePaperRect.width);
1415 paperRect.height = wxCoord(scaleY * devicePaperRect.height);
1416
1417 paperRect.x = wxCoord((canvasWidth - paperRect.width)/ 2.0);
1418 if (paperRect.x < m_leftMargin)
1419 paperRect.x = m_leftMargin;
1420 paperRect.y = wxCoord((canvasHeight - paperRect.height)/ 2.0);
1421 if (paperRect.y < m_topMargin)
1422 paperRect.y = m_topMargin;
1423
1424 pageRect.x = paperRect.x - wxCoord(scaleX * devicePaperRect.x);
1425 pageRect.y = paperRect.y - wxCoord(scaleY * devicePaperRect.y);
1426 pageRect.width = wxCoord(screenPrintableWidth);
1427 pageRect.height = wxCoord(screenPrintableHeight);
1428 }
1429
1430
1431 bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
1432 {
1433 DrawBlankPage(canvas, dc);
1434
1435 if (!m_previewBitmap)
1436 if (!RenderPage(m_currentPage))
1437 return false;
1438 if (!m_previewBitmap)
1439 return false;
1440 if (!canvas)
1441 return false;
1442
1443 wxRect pageRect, paperRect;
1444 CalcRects(canvas, pageRect, paperRect);
1445 wxMemoryDC temp_dc;
1446 temp_dc.SelectObject(*m_previewBitmap);
1447
1448 dc.Blit(pageRect.x, pageRect.y,
1449 m_previewBitmap->GetWidth(), m_previewBitmap->GetHeight(), &temp_dc, 0, 0);
1450
1451 temp_dc.SelectObject(wxNullBitmap);
1452 return true;
1453 }
1454
1455 // Adjusts the scrollbars for the current scale
1456 void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas *canvas)
1457 {
1458 if (!canvas)
1459 return ;
1460
1461 wxRect pageRect, paperRect;
1462 CalcRects(canvas, pageRect, paperRect);
1463 int totalWidth = paperRect.width + 2 * m_leftMargin;
1464 int totalHeight = paperRect.height + 2 * m_topMargin;
1465 int scrollUnitsX = totalWidth / 10;
1466 int scrollUnitsY = totalHeight / 10;
1467 wxSize virtualSize = canvas->GetVirtualSize();
1468 if (virtualSize.GetWidth() != totalWidth || virtualSize.GetHeight() != totalHeight)
1469 canvas->SetScrollbars(10, 10, scrollUnitsX, scrollUnitsY, 0, 0, true);
1470 }
1471
1472 bool wxPrintPreviewBase::RenderPage(int pageNum)
1473 {
1474 wxBusyCursor busy;
1475
1476 if (!m_previewCanvas)
1477 {
1478 wxFAIL_MSG(_T("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
1479 return false;
1480 }
1481
1482 wxRect pageRect, paperRect;
1483 CalcRects(m_previewCanvas, pageRect, paperRect);
1484
1485 if (!m_previewBitmap)
1486 {
1487 m_previewBitmap = new wxBitmap(pageRect.width, pageRect.height);
1488
1489 if (!m_previewBitmap || !m_previewBitmap->Ok())
1490 {
1491 if (m_previewBitmap) {
1492 delete m_previewBitmap;
1493 m_previewBitmap = NULL;
1494 }
1495 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
1496 return false;
1497 }
1498 }
1499
1500 wxMemoryDC memoryDC;
1501 memoryDC.SelectObject(*m_previewBitmap);
1502
1503 memoryDC.Clear();
1504
1505 m_previewPrintout->SetDC(&memoryDC);
1506 m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
1507
1508 // Need to delay OnPreparePrinting until here, so we have enough information.
1509 if (!m_printingPrepared)
1510 {
1511 m_previewPrintout->OnPreparePrinting();
1512 int selFrom, selTo;
1513 m_previewPrintout->GetPageInfo(&m_minPage, &m_maxPage, &selFrom, &selTo);
1514 m_printingPrepared = true;
1515 }
1516
1517 m_previewPrintout->OnBeginPrinting();
1518
1519 if (!m_previewPrintout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
1520 {
1521 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK);
1522
1523 memoryDC.SelectObject(wxNullBitmap);
1524
1525 delete m_previewBitmap;
1526 m_previewBitmap = NULL;
1527 return false;
1528 }
1529
1530 m_previewPrintout->OnPrintPage(pageNum);
1531 m_previewPrintout->OnEndDocument();
1532 m_previewPrintout->OnEndPrinting();
1533
1534 m_previewPrintout->SetDC(NULL);
1535
1536 memoryDC.SelectObject(wxNullBitmap);
1537
1538 #if wxUSE_STATUSBAR
1539 wxString status;
1540 if (m_maxPage != 0)
1541 status = wxString::Format(_("Page %d of %d"), pageNum, m_maxPage);
1542 else
1543 status = wxString::Format(_("Page %d"), pageNum);
1544
1545 if (m_previewFrame)
1546 m_previewFrame->SetStatusText(status);
1547 #endif
1548
1549 return true;
1550 }
1551
1552 bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
1553 {
1554 wxRect pageRect, paperRect;
1555
1556 CalcRects(canvas, pageRect, paperRect);
1557
1558 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
1559 wxCoord shadowOffset = 4;
1560
1561 dc.SetPen(*wxBLACK_PEN);
1562 dc.SetBrush(*wxBLACK_BRUSH);
1563 dc.DrawRectangle(paperRect.x + shadowOffset, paperRect.y + paperRect.height + 1,
1564 paperRect.width, shadowOffset);
1565
1566 dc.DrawRectangle(paperRect.x + paperRect.width, paperRect.y + shadowOffset,
1567 shadowOffset, paperRect.height);
1568
1569 // Draw blank page allowing for 1-pixel border AROUND the actual paper
1570 dc.SetPen(*wxBLACK_PEN);
1571 dc.SetBrush(*wxWHITE_BRUSH);
1572 dc.DrawRectangle(paperRect.x - 2, paperRect.y - 1,
1573 paperRect.width + 3, paperRect.height + 2);
1574
1575 return true;
1576 }
1577
1578 void wxPrintPreviewBase::SetZoom(int percent)
1579 {
1580 if (m_currentZoom == percent)
1581 return;
1582
1583 m_currentZoom = percent;
1584 if (m_previewBitmap)
1585 {
1586 delete m_previewBitmap;
1587 m_previewBitmap = NULL;
1588 }
1589
1590 if (m_previewCanvas)
1591 {
1592 AdjustScrollbars(m_previewCanvas);
1593 RenderPage(m_currentPage);
1594 ((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
1595 m_previewCanvas->ClearBackground();
1596 m_previewCanvas->Refresh();
1597 m_previewCanvas->SetFocus();
1598 }
1599 }
1600
1601 wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
1602 {
1603 return m_printDialogData;
1604 }
1605
1606 int wxPrintPreviewBase::GetZoom() const
1607 { return m_currentZoom; }
1608 int wxPrintPreviewBase::GetMaxPage() const
1609 { return m_maxPage; }
1610 int wxPrintPreviewBase::GetMinPage() const
1611 { return m_minPage; }
1612 bool wxPrintPreviewBase::IsOk() const
1613 { return m_isOk; }
1614 void wxPrintPreviewBase::SetOk(bool ok)
1615 { m_isOk = ok; }
1616
1617 //----------------------------------------------------------------------------
1618 // wxPrintPreview
1619 //----------------------------------------------------------------------------
1620
1621 IMPLEMENT_CLASS(wxPrintPreview, wxPrintPreviewBase)
1622
1623 wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1624 wxPrintout *printoutForPrinting,
1625 wxPrintDialogData *data) :
1626 wxPrintPreviewBase( printout, printoutForPrinting, data )
1627 {
1628 m_pimpl = wxPrintFactory::GetFactory()->
1629 CreatePrintPreview( printout, printoutForPrinting, data );
1630 }
1631
1632 wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1633 wxPrintout *printoutForPrinting,
1634 wxPrintData *data ) :
1635 wxPrintPreviewBase( printout, printoutForPrinting, data )
1636 {
1637 m_pimpl = wxPrintFactory::GetFactory()->
1638 CreatePrintPreview( printout, printoutForPrinting, data );
1639 }
1640
1641 wxPrintPreview::~wxPrintPreview()
1642 {
1643 delete m_pimpl;
1644
1645 // don't delete twice
1646 m_printPrintout = NULL;
1647 m_previewPrintout = NULL;
1648 m_previewBitmap = NULL;
1649 }
1650
1651 bool wxPrintPreview::SetCurrentPage(int pageNum)
1652 {
1653 return m_pimpl->SetCurrentPage( pageNum );
1654 }
1655
1656 int wxPrintPreview::GetCurrentPage() const
1657 {
1658 return m_pimpl->GetCurrentPage();
1659 }
1660
1661 void wxPrintPreview::SetPrintout(wxPrintout *printout)
1662 {
1663 m_pimpl->SetPrintout( printout );
1664 }
1665
1666 wxPrintout *wxPrintPreview::GetPrintout() const
1667 {
1668 return m_pimpl->GetPrintout();
1669 }
1670
1671 wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
1672 {
1673 return m_pimpl->GetPrintoutForPrinting();
1674 }
1675
1676 void wxPrintPreview::SetFrame(wxFrame *frame)
1677 {
1678 m_pimpl->SetFrame( frame );
1679 }
1680
1681 void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
1682 {
1683 m_pimpl->SetCanvas( canvas );
1684 }
1685
1686 wxFrame *wxPrintPreview::GetFrame() const
1687 {
1688 return m_pimpl->GetFrame();
1689 }
1690
1691 wxPreviewCanvas *wxPrintPreview::GetCanvas() const
1692 {
1693 return m_pimpl->GetCanvas();
1694 }
1695
1696 bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
1697 {
1698 return m_pimpl->PaintPage( canvas, dc );
1699 }
1700
1701 bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
1702 {
1703 return m_pimpl->DrawBlankPage( canvas, dc );
1704 }
1705
1706 void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas *canvas)
1707 {
1708 m_pimpl->AdjustScrollbars( canvas );
1709 }
1710
1711 bool wxPrintPreview::RenderPage(int pageNum)
1712 {
1713 return m_pimpl->RenderPage( pageNum );
1714 }
1715
1716 void wxPrintPreview::SetZoom(int percent)
1717 {
1718 m_pimpl->SetZoom( percent );
1719 }
1720
1721 int wxPrintPreview::GetZoom() const
1722 {
1723 return m_pimpl->GetZoom();
1724 }
1725
1726 wxPrintDialogData& wxPrintPreview::GetPrintDialogData()
1727 {
1728 return m_pimpl->GetPrintDialogData();
1729 }
1730
1731 int wxPrintPreview::GetMaxPage() const
1732 {
1733 return m_pimpl->GetMaxPage();
1734 }
1735
1736 int wxPrintPreview::GetMinPage() const
1737 {
1738 return m_pimpl->GetMinPage();
1739 }
1740
1741 bool wxPrintPreview::IsOk() const
1742 {
1743 return m_pimpl->Ok();
1744 }
1745
1746 void wxPrintPreview::SetOk(bool ok)
1747 {
1748 m_pimpl->SetOk( ok );
1749 }
1750
1751 bool wxPrintPreview::Print(bool interactive)
1752 {
1753 return m_pimpl->Print( interactive );
1754 }
1755
1756 void wxPrintPreview::DetermineScaling()
1757 {
1758 m_pimpl->DetermineScaling();
1759 }
1760
1761 #endif // wxUSE_PRINTING_ARCHITECTURE