]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/prntbase.cpp
Hopefully fixed misplaced printout in libgnomeprint.
[wxWidgets.git] / src / common / prntbase.cpp
... / ...
CommitLineData
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
72wxPrintFactory *wxPrintFactory::m_factory = NULL;
73
74void wxPrintFactory::SetPrintFactory( wxPrintFactory *factory )
75{
76 if (wxPrintFactory::m_factory)
77 delete wxPrintFactory::m_factory;
78
79 wxPrintFactory::m_factory = factory;
80}
81
82wxPrintFactory *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
94wxPrinterBase *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
107wxPrintPreviewBase *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
121wxPrintPreviewBase *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
135wxPrintDialogBase *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
147wxPrintDialogBase *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
159wxPageSetupDialogBase *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
171bool 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
187wxDialog *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
207wxDC* 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
218bool 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
227bool wxNativePrintFactory::HasPrinterLine()
228{
229 // Only relevant for PostScript for now
230 return true;
231}
232
233wxString wxNativePrintFactory::CreatePrinterLine()
234{
235 // Only relevant for PostScript for now
236
237 // We should query "lpstat -d" here
238 return _("Generic PostScript");
239}
240
241bool wxNativePrintFactory::HasStatusLine()
242{
243 // Only relevant for PostScript for now
244 return true;
245}
246
247wxString 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
255wxPrintNativeDataBase *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
270IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase, wxObject)
271
272wxPrintNativeDataBase::wxPrintNativeDataBase()
273{
274 m_ref = 1;
275}
276
277//----------------------------------------------------------------------------
278// wxPrintFactoryModule
279//----------------------------------------------------------------------------
280
281class wxPrintFactoryModule: public wxModule
282{
283public:
284 wxPrintFactoryModule() {}
285 bool OnInit() { return true; }
286 void OnExit() { wxPrintFactory::SetPrintFactory( NULL ); }
287
288private:
289 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule)
290};
291
292IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule, wxModule)
293
294//----------------------------------------------------------------------------
295// wxPrinterBase
296//----------------------------------------------------------------------------
297
298IMPLEMENT_CLASS(wxPrinterBase, wxObject)
299
300wxPrinterBase::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
310wxWindow *wxPrinterBase::sm_abortWindow = (wxWindow *) NULL;
311bool wxPrinterBase::sm_abortIt = false;
312wxPrinterError wxPrinterBase::sm_lastError = wxPRINTER_NO_ERROR;
313
314wxPrinterBase::~wxPrinterBase()
315{
316}
317
318wxWindow *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
335void wxPrinterBase::ReportError(wxWindow *parent, wxPrintout *WXUNUSED(printout), const wxString& message)
336{
337 wxMessageBox(message, _("Printing Error"), wxOK, parent);
338}
339
340wxPrintDialogData& wxPrinterBase::GetPrintDialogData() const
341{
342 return (wxPrintDialogData&) m_printDialogData;
343}
344
345//----------------------------------------------------------------------------
346// wxPrinter
347//----------------------------------------------------------------------------
348
349IMPLEMENT_CLASS(wxPrinter, wxPrinterBase)
350
351wxPrinter::wxPrinter(wxPrintDialogData *data)
352{
353 m_pimpl = wxPrintFactory::GetFactory()->CreatePrinter( data );
354}
355
356wxPrinter::~wxPrinter()
357{
358 delete m_pimpl;
359}
360
361wxWindow *wxPrinter::CreateAbortWindow(wxWindow *parent, wxPrintout *printout)
362{
363 return m_pimpl->CreateAbortWindow( parent, printout );
364}
365
366void wxPrinter::ReportError(wxWindow *parent, wxPrintout *printout, const wxString& message)
367{
368 m_pimpl->ReportError( parent, printout, message );
369}
370
371bool wxPrinter::Setup(wxWindow *parent)
372{
373 return m_pimpl->Setup( parent );
374}
375
376bool wxPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
377{
378 return m_pimpl->Print( parent, printout, prompt );
379}
380
381wxDC* wxPrinter::PrintDialog(wxWindow *parent)
382{
383 return m_pimpl->PrintDialog( parent );
384}
385
386wxPrintDialogData& wxPrinter::GetPrintDialogData() const
387{
388 return m_pimpl->GetPrintDialogData();
389}
390
391// ---------------------------------------------------------------------------
392// wxPrintDialogBase: the dialog for printing.
393// ---------------------------------------------------------------------------
394
395IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase, wxDialog)
396
397wxPrintDialogBase::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
412IMPLEMENT_CLASS(wxPrintDialog, wxObject)
413
414wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintDialogData* data)
415{
416 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
417}
418
419wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintData* data)
420{
421 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
422}
423
424wxPrintDialog::~wxPrintDialog()
425{
426 delete m_pimpl;
427}
428
429int wxPrintDialog::ShowModal()
430{
431 return m_pimpl->ShowModal();
432}
433
434wxPrintDialogData& wxPrintDialog::GetPrintDialogData()
435{
436 return m_pimpl->GetPrintDialogData();
437}
438
439wxPrintData& wxPrintDialog::GetPrintData()
440{
441 return m_pimpl->GetPrintData();
442}
443
444wxDC *wxPrintDialog::GetPrintDC()
445{
446 return m_pimpl->GetPrintDC();
447}
448
449// ---------------------------------------------------------------------------
450// wxPageSetupDialogBase: the page setup dialog
451// ---------------------------------------------------------------------------
452
453IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase, wxDialog)
454
455wxPageSetupDialogBase::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
470IMPLEMENT_CLASS(wxPageSetupDialog, wxObject)
471
472wxPageSetupDialog::wxPageSetupDialog(wxWindow *parent, wxPageSetupDialogData *data )
473{
474 m_pimpl = wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent, data );
475}
476
477wxPageSetupDialog::~wxPageSetupDialog()
478{
479 delete m_pimpl;
480}
481
482int wxPageSetupDialog::ShowModal()
483{
484 return m_pimpl->ShowModal();
485}
486
487wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupDialogData()
488{
489 return m_pimpl->GetPageSetupDialogData();
490}
491
492// old name
493wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupData()
494{
495 return m_pimpl->GetPageSetupDialogData();
496}
497
498//----------------------------------------------------------------------------
499// wxPrintAbortDialog
500//----------------------------------------------------------------------------
501
502BEGIN_EVENT_TABLE(wxPrintAbortDialog, wxDialog)
503 EVT_BUTTON(wxID_CANCEL, wxPrintAbortDialog::OnCancel)
504END_EVENT_TABLE()
505
506void 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
518IMPLEMENT_ABSTRACT_CLASS(wxPrintout, wxObject)
519
520wxPrintout::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
535wxPrintout::~wxPrintout()
536{
537}
538
539bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage), int WXUNUSED(endPage))
540{
541 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle);
542}
543
544void wxPrintout::OnEndDocument()
545{
546 GetDC()->EndDoc();
547}
548
549void wxPrintout::OnBeginPrinting()
550{
551}
552
553void wxPrintout::OnEndPrinting()
554{
555}
556
557bool wxPrintout::HasPage(int page)
558{
559 return (page == 1);
560}
561
562void 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
570void 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
591void 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
606void 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
636void 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
648void 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
667void 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
678void 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
693wxRect 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
718wxRect 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
730wxRect 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
766void 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
773void 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
787IMPLEMENT_CLASS(wxPreviewCanvas, wxWindow)
788
789BEGIN_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
796END_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...
802wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase *preview, wxWindow *parent,
803 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
804wxScrolledWindow(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
821wxPreviewCanvas::~wxPreviewCanvas()
822{
823}
824
825void 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.
844void 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
862void 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
904void 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
950IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
951
952BEGIN_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)
962END_EVENT_TABLE()
963
964wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
965 wxWindow *parent, const wxPoint& pos, const wxSize& size,
966 long style, const wxString& name):
967wxPanel(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
978wxPreviewControlBar::~wxPreviewControlBar()
979{
980}
981
982void 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
993void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
994{
995 wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
996 frame->Close(true);
997}
998
999void wxPreviewControlBar::OnPrint(void)
1000{
1001 wxPrintPreviewBase *preview = GetPrintPreview();
1002 preview->Print(true);
1003}
1004
1005void 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
1020void 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
1035void 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
1048void 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
1061void 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
1089void wxPreviewControlBar::OnZoom(wxCommandEvent& WXUNUSED(event))
1090{
1091 int zoom = GetZoomControl();
1092 if (GetPrintPreview())
1093 GetPrintPreview()->SetZoom(zoom);
1094}
1095
1096void 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
1171void 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
1191int 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
1208IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
1209
1210BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
1211 EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
1212END_EVENT_TABLE()
1213
1214wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
1215 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
1216wxFrame(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
1231wxPreviewFrame::~wxPreviewFrame()
1232{
1233}
1234
1235void 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
1254void 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
1282void wxPreviewFrame::CreateCanvas()
1283{
1284 m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
1285}
1286
1287void 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
1301IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
1302
1303wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1304 wxPrintout *printoutForPrinting,
1305 wxPrintData *data)
1306{
1307 if (data)
1308 m_printDialogData = (*data);
1309
1310 Init(printout, printoutForPrinting);
1311}
1312
1313wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1314 wxPrintout *printoutForPrinting,
1315 wxPrintDialogData *data)
1316{
1317 if (data)
1318 m_printDialogData = (*data);
1319
1320 Init(printout, printoutForPrinting);
1321}
1322
1323void 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
1347wxPrintPreviewBase::~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
1357bool 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
1381int wxPrintPreviewBase::GetCurrentPage() const
1382 { return m_currentPage; }
1383void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
1384 { m_previewPrintout = printout; }
1385wxPrintout *wxPrintPreviewBase::GetPrintout() const
1386 { return m_previewPrintout; }
1387wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
1388 { return m_printPrintout; }
1389void wxPrintPreviewBase::SetFrame(wxFrame *frame)
1390 { m_previewFrame = frame; }
1391void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
1392 { m_previewCanvas = canvas; }
1393wxFrame *wxPrintPreviewBase::GetFrame() const
1394 { return m_previewFrame; }
1395wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
1396 { return m_previewCanvas; }
1397
1398void 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
1431bool 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
1456void 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
1472bool 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
1552bool 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
1578void 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
1601wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
1602{
1603 return m_printDialogData;
1604}
1605
1606int wxPrintPreviewBase::GetZoom() const
1607{ return m_currentZoom; }
1608int wxPrintPreviewBase::GetMaxPage() const
1609{ return m_maxPage; }
1610int wxPrintPreviewBase::GetMinPage() const
1611{ return m_minPage; }
1612bool wxPrintPreviewBase::IsOk() const
1613{ return m_isOk; }
1614void wxPrintPreviewBase::SetOk(bool ok)
1615{ m_isOk = ok; }
1616
1617//----------------------------------------------------------------------------
1618// wxPrintPreview
1619//----------------------------------------------------------------------------
1620
1621IMPLEMENT_CLASS(wxPrintPreview, wxPrintPreviewBase)
1622
1623wxPrintPreview::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
1632wxPrintPreview::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
1641wxPrintPreview::~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
1651bool wxPrintPreview::SetCurrentPage(int pageNum)
1652{
1653 return m_pimpl->SetCurrentPage( pageNum );
1654}
1655
1656int wxPrintPreview::GetCurrentPage() const
1657{
1658 return m_pimpl->GetCurrentPage();
1659}
1660
1661void wxPrintPreview::SetPrintout(wxPrintout *printout)
1662{
1663 m_pimpl->SetPrintout( printout );
1664}
1665
1666wxPrintout *wxPrintPreview::GetPrintout() const
1667{
1668 return m_pimpl->GetPrintout();
1669}
1670
1671wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
1672{
1673 return m_pimpl->GetPrintoutForPrinting();
1674}
1675
1676void wxPrintPreview::SetFrame(wxFrame *frame)
1677{
1678 m_pimpl->SetFrame( frame );
1679}
1680
1681void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
1682{
1683 m_pimpl->SetCanvas( canvas );
1684}
1685
1686wxFrame *wxPrintPreview::GetFrame() const
1687{
1688 return m_pimpl->GetFrame();
1689}
1690
1691wxPreviewCanvas *wxPrintPreview::GetCanvas() const
1692{
1693 return m_pimpl->GetCanvas();
1694}
1695
1696bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
1697{
1698 return m_pimpl->PaintPage( canvas, dc );
1699}
1700
1701bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
1702{
1703 return m_pimpl->DrawBlankPage( canvas, dc );
1704}
1705
1706void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas *canvas)
1707{
1708 m_pimpl->AdjustScrollbars( canvas );
1709}
1710
1711bool wxPrintPreview::RenderPage(int pageNum)
1712{
1713 return m_pimpl->RenderPage( pageNum );
1714}
1715
1716void wxPrintPreview::SetZoom(int percent)
1717{
1718 m_pimpl->SetZoom( percent );
1719}
1720
1721int wxPrintPreview::GetZoom() const
1722{
1723 return m_pimpl->GetZoom();
1724}
1725
1726wxPrintDialogData& wxPrintPreview::GetPrintDialogData()
1727{
1728 return m_pimpl->GetPrintDialogData();
1729}
1730
1731int wxPrintPreview::GetMaxPage() const
1732{
1733 return m_pimpl->GetMaxPage();
1734}
1735
1736int wxPrintPreview::GetMinPage() const
1737{
1738 return m_pimpl->GetMinPage();
1739}
1740
1741bool wxPrintPreview::IsOk() const
1742{
1743 return m_pimpl->Ok();
1744}
1745
1746void wxPrintPreview::SetOk(bool ok)
1747{
1748 m_pimpl->SetOk( ok );
1749}
1750
1751bool wxPrintPreview::Print(bool interactive)
1752{
1753 return m_pimpl->Print( interactive );
1754}
1755
1756void wxPrintPreview::DetermineScaling()
1757{
1758 m_pimpl->DetermineScaling();
1759}
1760
1761#endif // wxUSE_PRINTING_ARCHITECTURE