]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/prntbase.cpp
Better compatibility with old files when creating an image cache
[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/bmpbuttn.h"
36 #include "wx/settings.h"
37 #include "wx/dcmemory.h"
38 #include "wx/dcclient.h"
39 #include "wx/stattext.h"
40 #include "wx/intl.h"
41 #include "wx/textdlg.h"
42 #include "wx/sizer.h"
43 #include "wx/module.h"
44#endif // !WX_PRECOMP
45
46#include "wx/prntbase.h"
47#include "wx/printdlg.h"
48#include "wx/print.h"
49#include "wx/dcprint.h"
50#include "wx/artprov.h"
51
52#include <stdlib.h>
53#include <string.h>
54
55#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
56#include "wx/msw/printdlg.h"
57#include "wx/msw/dcprint.h"
58#elif defined(__WXMAC__)
59#include "wx/osx/printdlg.h"
60#include "wx/osx/private/print.h"
61#include "wx/osx/dcprint.h"
62#elif defined(__WXPM__)
63#include "wx/os2/dcprint.h"
64#include "wx/generic/prntdlgg.h"
65#else
66#include "wx/generic/prntdlgg.h"
67#include "wx/dcps.h"
68#endif
69
70#ifdef __WXMSW__
71 #ifndef __WIN32__
72 #include <print.h>
73 #endif
74#endif // __WXMSW__
75
76//----------------------------------------------------------------------------
77// wxPrintFactory
78//----------------------------------------------------------------------------
79
80wxPrintFactory *wxPrintFactory::m_factory = NULL;
81
82void wxPrintFactory::SetPrintFactory( wxPrintFactory *factory )
83{
84 if (wxPrintFactory::m_factory)
85 delete wxPrintFactory::m_factory;
86
87 wxPrintFactory::m_factory = factory;
88}
89
90wxPrintFactory *wxPrintFactory::GetFactory()
91{
92 if (!wxPrintFactory::m_factory)
93 wxPrintFactory::m_factory = new wxNativePrintFactory;
94
95 return wxPrintFactory::m_factory;
96}
97
98//----------------------------------------------------------------------------
99// wxNativePrintFactory
100//----------------------------------------------------------------------------
101
102wxPrinterBase *wxNativePrintFactory::CreatePrinter( wxPrintDialogData *data )
103{
104#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
105 return new wxWindowsPrinter( data );
106#elif defined(__WXMAC__)
107 return new wxMacPrinter( data );
108#elif defined(__WXPM__)
109 return new wxOS2Printer( data );
110#else
111 return new wxPostScriptPrinter( data );
112#endif
113}
114
115wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
116 wxPrintout *printout, wxPrintDialogData *data )
117{
118#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
119 return new wxWindowsPrintPreview( preview, printout, data );
120#elif defined(__WXMAC__)
121 return new wxMacPrintPreview( preview, printout, data );
122#elif defined(__WXPM__)
123 return new wxOS2PrintPreview( preview, printout, data );
124#else
125 return new wxPostScriptPrintPreview( preview, printout, data );
126#endif
127}
128
129wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
130 wxPrintout *printout, wxPrintData *data )
131{
132#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
133 return new wxWindowsPrintPreview( preview, printout, data );
134#elif defined(__WXMAC__)
135 return new wxMacPrintPreview( preview, printout, data );
136#elif defined(__WXPM__)
137 return new wxOS2PrintPreview( preview, printout, data );
138#else
139 return new wxPostScriptPrintPreview( preview, printout, data );
140#endif
141}
142
143wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
144 wxPrintDialogData *data )
145{
146#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
147 return new wxWindowsPrintDialog( parent, data );
148#elif defined(__WXMAC__)
149 return new wxMacPrintDialog( parent, data );
150#else
151 return new wxGenericPrintDialog( parent, data );
152#endif
153}
154
155wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
156 wxPrintData *data )
157{
158#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
159 return new wxWindowsPrintDialog( parent, data );
160#elif defined(__WXMAC__)
161 return new wxMacPrintDialog( parent, data );
162#else
163 return new wxGenericPrintDialog( parent, data );
164#endif
165}
166
167wxPageSetupDialogBase *wxNativePrintFactory::CreatePageSetupDialog( wxWindow *parent,
168 wxPageSetupDialogData *data )
169{
170#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
171 return new wxWindowsPageSetupDialog( parent, data );
172#elif defined(__WXMAC__)
173 return new wxMacPageSetupDialog( parent, data );
174#else
175 return new wxGenericPageSetupDialog( parent, data );
176#endif
177}
178
179bool wxNativePrintFactory::HasPrintSetupDialog()
180{
181#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
182 return false;
183#elif defined(__WXMAC__)
184 return false;
185#else
186 // Only here do we need to provide the print setup
187 // dialog ourselves, the other platforms either have
188 // none, don't make it accessible or let you configure
189 // the printer from the wxPrintDialog anyway.
190 return true;
191#endif
192
193}
194
195wxDialog *wxNativePrintFactory::CreatePrintSetupDialog( wxWindow *parent,
196 wxPrintData *data )
197{
198#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
199 wxUnusedVar(parent);
200 wxUnusedVar(data);
201 return NULL;
202#elif defined(__WXMAC__)
203 wxUnusedVar(parent);
204 wxUnusedVar(data);
205 return NULL;
206#else
207 // Only here do we need to provide the print setup
208 // dialog ourselves, the other platforms either have
209 // none, don't make it accessible or let you configure
210 // the printer from the wxPrintDialog anyway.
211 return new wxGenericPrintSetupDialog( parent, data );
212#endif
213}
214
215wxDCImpl* wxNativePrintFactory::CreatePrinterDCImpl( wxPrinterDC *owner, const wxPrintData& data )
216{
217#if defined(__WXGTK__) || defined(__WXMOTIF__) || ( defined(__WXUNIVERSAL__) && !defined(__WXMAC__) )
218 return new wxPostScriptDCImpl( owner, data );
219#else
220 return new wxPrinterDCImpl( owner, data );
221#endif
222}
223
224bool wxNativePrintFactory::HasOwnPrintToFile()
225{
226 // Only relevant for PostScript and here the
227 // setup dialog provides no "print to file"
228 // option. In the GNOME setup dialog, the
229 // setup dialog has its own print to file.
230 return false;
231}
232
233bool wxNativePrintFactory::HasPrinterLine()
234{
235 // Only relevant for PostScript for now
236 return true;
237}
238
239wxString wxNativePrintFactory::CreatePrinterLine()
240{
241 // Only relevant for PostScript for now
242
243 // We should query "lpstat -d" here
244 return _("Generic PostScript");
245}
246
247bool wxNativePrintFactory::HasStatusLine()
248{
249 // Only relevant for PostScript for now
250 return true;
251}
252
253wxString wxNativePrintFactory::CreateStatusLine()
254{
255 // Only relevant for PostScript for now
256
257 // We should query "lpstat -r" or "lpstat -p" here
258 return _("Ready");
259}
260
261wxPrintNativeDataBase *wxNativePrintFactory::CreatePrintNativeData()
262{
263#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
264 return new wxWindowsPrintNativeData;
265#elif defined(__WXMAC__)
266 return wxOSXCreatePrintData();
267#else
268 return new wxPostScriptPrintNativeData;
269#endif
270}
271
272//----------------------------------------------------------------------------
273// wxPrintNativeDataBase
274//----------------------------------------------------------------------------
275
276IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase, wxObject)
277
278wxPrintNativeDataBase::wxPrintNativeDataBase()
279{
280 m_ref = 1;
281}
282
283//----------------------------------------------------------------------------
284// wxPrintFactoryModule
285//----------------------------------------------------------------------------
286
287class wxPrintFactoryModule: public wxModule
288{
289public:
290 wxPrintFactoryModule() {}
291 bool OnInit() { return true; }
292 void OnExit() { wxPrintFactory::SetPrintFactory( NULL ); }
293
294private:
295 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule)
296};
297
298IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule, wxModule)
299
300//----------------------------------------------------------------------------
301// wxPrinterBase
302//----------------------------------------------------------------------------
303
304IMPLEMENT_CLASS(wxPrinterBase, wxObject)
305
306wxPrinterBase::wxPrinterBase(wxPrintDialogData *data)
307{
308 m_currentPrintout = NULL;
309 sm_abortWindow = NULL;
310 sm_abortIt = false;
311 if (data)
312 m_printDialogData = (*data);
313 sm_lastError = wxPRINTER_NO_ERROR;
314}
315
316wxWindow *wxPrinterBase::sm_abortWindow = NULL;
317bool wxPrinterBase::sm_abortIt = false;
318wxPrinterError wxPrinterBase::sm_lastError = wxPRINTER_NO_ERROR;
319
320wxPrinterBase::~wxPrinterBase()
321{
322}
323
324wxPrintAbortDialog *wxPrinterBase::CreateAbortWindow(wxWindow *parent, wxPrintout * printout)
325{
326 return new wxPrintAbortDialog(parent, printout->GetTitle());
327}
328
329void wxPrinterBase::ReportError(wxWindow *parent, wxPrintout *WXUNUSED(printout), const wxString& message)
330{
331 wxMessageBox(message, _("Printing Error"), wxOK, parent);
332}
333
334wxPrintDialogData& wxPrinterBase::GetPrintDialogData() const
335{
336 return (wxPrintDialogData&) m_printDialogData;
337}
338
339//----------------------------------------------------------------------------
340// wxPrinter
341//----------------------------------------------------------------------------
342
343IMPLEMENT_CLASS(wxPrinter, wxPrinterBase)
344
345wxPrinter::wxPrinter(wxPrintDialogData *data)
346{
347 m_pimpl = wxPrintFactory::GetFactory()->CreatePrinter( data );
348}
349
350wxPrinter::~wxPrinter()
351{
352 delete m_pimpl;
353}
354
355wxPrintAbortDialog *wxPrinter::CreateAbortWindow(wxWindow *parent, wxPrintout *printout)
356{
357 return m_pimpl->CreateAbortWindow( parent, printout );
358}
359
360void wxPrinter::ReportError(wxWindow *parent, wxPrintout *printout, const wxString& message)
361{
362 m_pimpl->ReportError( parent, printout, message );
363}
364
365bool wxPrinter::Setup(wxWindow *parent)
366{
367 return m_pimpl->Setup( parent );
368}
369
370bool wxPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
371{
372 if ( !prompt && m_printDialogData.GetToPage() == 0 )
373 {
374 // If the dialog is not shown, set the pages range to print everything
375 // by default (as otherwise we wouldn't print anything at all which is
376 // certainly not a reasonable default behaviour).
377 int minPage, maxPage, selFrom, selTo;
378 printout->GetPageInfo(&minPage, &maxPage, &selFrom, &selTo);
379
380 wxPrintDialogData& pdd = m_pimpl->GetPrintDialogData();
381 pdd.SetFromPage(minPage);
382 pdd.SetToPage(maxPage);
383 }
384
385 return m_pimpl->Print( parent, printout, prompt );
386}
387
388wxDC* wxPrinter::PrintDialog(wxWindow *parent)
389{
390 return m_pimpl->PrintDialog( parent );
391}
392
393wxPrintDialogData& wxPrinter::GetPrintDialogData() const
394{
395 return m_pimpl->GetPrintDialogData();
396}
397
398// ---------------------------------------------------------------------------
399// wxPrintDialogBase: the dialog for printing.
400// ---------------------------------------------------------------------------
401
402IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase, wxDialog)
403
404wxPrintDialogBase::wxPrintDialogBase(wxWindow *parent,
405 wxWindowID id,
406 const wxString &title,
407 const wxPoint &pos,
408 const wxSize &size,
409 long style)
410 : wxDialog( parent, id, title.empty() ? wxString(_("Print")) : title,
411 pos, size, style )
412{
413}
414
415// ---------------------------------------------------------------------------
416// wxPrintDialog: the dialog for printing
417// ---------------------------------------------------------------------------
418
419IMPLEMENT_CLASS(wxPrintDialog, wxObject)
420
421wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintDialogData* data)
422{
423 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
424}
425
426wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintData* data)
427{
428 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
429}
430
431wxPrintDialog::~wxPrintDialog()
432{
433 delete m_pimpl;
434}
435
436int wxPrintDialog::ShowModal()
437{
438 return m_pimpl->ShowModal();
439}
440
441wxPrintDialogData& wxPrintDialog::GetPrintDialogData()
442{
443 return m_pimpl->GetPrintDialogData();
444}
445
446wxPrintData& wxPrintDialog::GetPrintData()
447{
448 return m_pimpl->GetPrintData();
449}
450
451wxDC *wxPrintDialog::GetPrintDC()
452{
453 return m_pimpl->GetPrintDC();
454}
455
456// ---------------------------------------------------------------------------
457// wxPageSetupDialogBase: the page setup dialog
458// ---------------------------------------------------------------------------
459
460IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase, wxDialog)
461
462wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow *parent,
463 wxWindowID id,
464 const wxString &title,
465 const wxPoint &pos,
466 const wxSize &size,
467 long style)
468 : wxDialog( parent, id, title.empty() ? wxString(_("Page setup")) : title,
469 pos, size, style )
470{
471}
472
473// ---------------------------------------------------------------------------
474// wxPageSetupDialog: the page setup dialog
475// ---------------------------------------------------------------------------
476
477IMPLEMENT_CLASS(wxPageSetupDialog, wxObject)
478
479wxPageSetupDialog::wxPageSetupDialog(wxWindow *parent, wxPageSetupDialogData *data )
480{
481 m_pimpl = wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent, data );
482}
483
484wxPageSetupDialog::~wxPageSetupDialog()
485{
486 delete m_pimpl;
487}
488
489int wxPageSetupDialog::ShowModal()
490{
491 return m_pimpl->ShowModal();
492}
493
494wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupDialogData()
495{
496 return m_pimpl->GetPageSetupDialogData();
497}
498
499// old name
500wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupData()
501{
502 return m_pimpl->GetPageSetupDialogData();
503}
504
505//----------------------------------------------------------------------------
506// wxPrintAbortDialog
507//----------------------------------------------------------------------------
508
509BEGIN_EVENT_TABLE(wxPrintAbortDialog, wxDialog)
510 EVT_BUTTON(wxID_CANCEL, wxPrintAbortDialog::OnCancel)
511END_EVENT_TABLE()
512
513wxPrintAbortDialog::wxPrintAbortDialog(wxWindow *parent,
514 const wxString& documentTitle,
515 const wxPoint& pos,
516 const wxSize& size,
517 long style,
518 const wxString& name)
519 : wxDialog(parent, wxID_ANY, _("Printing"), pos, size, style, name)
520{
521 wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
522 mainSizer->Add(new wxStaticText(this, wxID_ANY, _("Please wait while printing...")),
523 wxSizerFlags().Expand().DoubleBorder());
524
525 wxFlexGridSizer *gridSizer = new wxFlexGridSizer(2, wxSize(20, 0));
526 gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Document:")));
527 gridSizer->AddGrowableCol(1);
528 gridSizer->Add(new wxStaticText(this, wxID_ANY, documentTitle));
529 gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Progress:")));
530 m_progress = new wxStaticText(this, wxID_ANY, _("Preparing"));
531 m_progress->SetMinSize(wxSize(250, -1));
532 gridSizer->Add(m_progress);
533 mainSizer->Add(gridSizer, wxSizerFlags().Expand().DoubleBorder(wxLEFT | wxRIGHT));
534
535 mainSizer->Add(CreateStdDialogButtonSizer(wxCANCEL),
536 wxSizerFlags().Expand().DoubleBorder());
537
538 SetSizerAndFit(mainSizer);
539}
540
541void wxPrintAbortDialog::SetProgress(int currentPage, int totalPages,
542 int currentCopy, int totalCopies)
543{
544 wxString text;
545 text.Printf(_("Printing page %d of %d"), currentPage, totalPages);
546 if ( totalCopies > 1 )
547 text += wxString::Format(_(" (copy %d of %d)"), currentCopy, totalCopies);
548 m_progress->SetLabel(text);
549}
550
551void wxPrintAbortDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
552{
553 wxCHECK_RET( wxPrinterBase::sm_abortWindow != NULL, "OnCancel called twice" );
554
555 wxPrinterBase::sm_abortIt = true;
556 wxPrinterBase::sm_abortWindow->Destroy();
557 wxPrinterBase::sm_abortWindow = NULL;
558}
559
560//----------------------------------------------------------------------------
561// wxPrintout
562//----------------------------------------------------------------------------
563
564IMPLEMENT_ABSTRACT_CLASS(wxPrintout, wxObject)
565
566wxPrintout::wxPrintout(const wxString& title)
567{
568 m_printoutTitle = title ;
569 m_printoutDC = NULL;
570 m_pageWidthMM = 0;
571 m_pageHeightMM = 0;
572 m_pageWidthPixels = 0;
573 m_pageHeightPixels = 0;
574 m_PPIScreenX = 0;
575 m_PPIScreenY = 0;
576 m_PPIPrinterX = 0;
577 m_PPIPrinterY = 0;
578 m_preview = NULL;
579}
580
581wxPrintout::~wxPrintout()
582{
583}
584
585bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage), int WXUNUSED(endPage))
586{
587 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle);
588}
589
590void wxPrintout::OnEndDocument()
591{
592 GetDC()->EndDoc();
593}
594
595void wxPrintout::OnBeginPrinting()
596{
597}
598
599void wxPrintout::OnEndPrinting()
600{
601}
602
603bool wxPrintout::HasPage(int page)
604{
605 return (page == 1);
606}
607
608void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toPage)
609{
610 *minPage = 1;
611 *maxPage = 32000;
612 *fromPage = 1;
613 *toPage = 1;
614}
615
616void wxPrintout::FitThisSizeToPaper(const wxSize& imageSize)
617{
618 // Set the DC scale and origin so that the given image size fits within the
619 // entire page and the origin is at the top left corner of the page. Note
620 // that with most printers, portions of the page will be non-printable. Use
621 // this if you're managing your own page margins.
622 if (!m_printoutDC) return;
623 wxRect paperRect = GetPaperRectPixels();
624 wxCoord pw, ph;
625 GetPageSizePixels(&pw, &ph);
626 wxCoord w, h;
627 m_printoutDC->GetSize(&w, &h);
628 float scaleX = ((float(paperRect.width) * w) / (float(pw) * imageSize.x));
629 float scaleY = ((float(paperRect.height) * h) / (float(ph) * imageSize.y));
630 float actualScale = wxMin(scaleX, scaleY);
631 m_printoutDC->SetUserScale(actualScale, actualScale);
632 m_printoutDC->SetDeviceOrigin(0, 0);
633 wxRect logicalPaperRect = GetLogicalPaperRect();
634 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
635}
636
637void wxPrintout::FitThisSizeToPage(const wxSize& imageSize)
638{
639 // Set the DC scale and origin so that the given image size fits within the
640 // printable area of the page and the origin is at the top left corner of
641 // the printable area.
642 if (!m_printoutDC) return;
643 int w, h;
644 m_printoutDC->GetSize(&w, &h);
645 float scaleX = float(w) / imageSize.x;
646 float scaleY = float(h) / imageSize.y;
647 float actualScale = wxMin(scaleX, scaleY);
648 m_printoutDC->SetUserScale(actualScale, actualScale);
649 m_printoutDC->SetDeviceOrigin(0, 0);
650}
651
652void wxPrintout::FitThisSizeToPageMargins(const wxSize& imageSize, const wxPageSetupDialogData& pageSetupData)
653{
654 // Set the DC scale and origin so that the given image size fits within the
655 // page margins defined in the given wxPageSetupDialogData object and the
656 // origin is at the top left corner of the page margins.
657 if (!m_printoutDC) return;
658 wxRect paperRect = GetPaperRectPixels();
659 wxCoord pw, ph;
660 GetPageSizePixels(&pw, &ph);
661 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
662 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
663 wxCoord mw, mh;
664 GetPageSizeMM(&mw, &mh);
665 float mmToDeviceX = float(pw) / mw;
666 float mmToDeviceY = float(ph) / mh;
667 wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x),
668 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
669 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
670 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
671 wxCoord w, h;
672 m_printoutDC->GetSize(&w, &h);
673 float scaleX = (float(pageMarginsRect.width) * w) / (float(pw) * imageSize.x);
674 float scaleY = (float(pageMarginsRect.height) * h) / (float(ph) * imageSize.y);
675 float actualScale = wxMin(scaleX, scaleY);
676 m_printoutDC->SetUserScale(actualScale, actualScale);
677 m_printoutDC->SetDeviceOrigin(0, 0);
678 wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
679 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
680}
681
682void wxPrintout::MapScreenSizeToPaper()
683{
684 // Set the DC scale so that an image on the screen is the same size on the
685 // paper and the origin is at the top left of the paper. Note that with most
686 // printers, portions of the page will be cut off. Use this if you're
687 // managing your own page margins.
688 if (!m_printoutDC) return;
689 MapScreenSizeToPage();
690 wxRect logicalPaperRect = GetLogicalPaperRect();
691 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
692}
693
694void wxPrintout::MapScreenSizeToPage()
695{
696 // Set the DC scale and origin so that an image on the screen is the same
697 // size on the paper and the origin is at the top left of the printable area.
698 if (!m_printoutDC) return;
699 int ppiScreenX, ppiScreenY;
700 GetPPIScreen(&ppiScreenX, &ppiScreenY);
701 int ppiPrinterX, ppiPrinterY;
702 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
703 int w, h;
704 m_printoutDC->GetSize(&w, &h);
705 int pageSizePixelsX, pageSizePixelsY;
706 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
707 float userScaleX = (float(ppiPrinterX) * w) / (float(ppiScreenX) * pageSizePixelsX);
708 float userScaleY = (float(ppiPrinterY) * h) / (float(ppiScreenY) * pageSizePixelsY);
709 m_printoutDC->SetUserScale(userScaleX, userScaleY);
710 m_printoutDC->SetDeviceOrigin(0, 0);
711}
712
713void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData& pageSetupData)
714{
715 // Set the DC scale so that an image on the screen is the same size on the
716 // paper and the origin is at the top left of the page margins defined by
717 // the given wxPageSetupDialogData object.
718 if (!m_printoutDC) return;
719 MapScreenSizeToPage();
720 wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
721 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
722}
723
724void wxPrintout::MapScreenSizeToDevice()
725{
726 // Set the DC scale so that a screen pixel is the same size as a device
727 // pixel and the origin is at the top left of the printable area.
728 if (!m_printoutDC) return;
729 int w, h;
730 m_printoutDC->GetSize(&w, &h);
731 int pageSizePixelsX, pageSizePixelsY;
732 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
733 float userScaleX = float(w) / pageSizePixelsX;
734 float userScaleY = float(h) / pageSizePixelsY;
735 m_printoutDC->SetUserScale(userScaleX, userScaleY);
736 m_printoutDC->SetDeviceOrigin(0, 0);
737}
738
739wxRect wxPrintout::GetLogicalPaperRect() const
740{
741 // Return the rectangle in logical units that corresponds to the paper
742 // rectangle.
743 wxRect paperRect = GetPaperRectPixels();
744 wxCoord pw, ph;
745 GetPageSizePixels(&pw, &ph);
746 wxCoord w, h;
747 m_printoutDC->GetSize(&w, &h);
748 if (w == pw && h == ph) {
749 // this DC matches the printed page, so no scaling
750 return wxRect(m_printoutDC->DeviceToLogicalX(paperRect.x),
751 m_printoutDC->DeviceToLogicalY(paperRect.y),
752 m_printoutDC->DeviceToLogicalXRel(paperRect.width),
753 m_printoutDC->DeviceToLogicalYRel(paperRect.height));
754 }
755 // This DC doesn't match the printed page, so we have to scale.
756 float scaleX = float(w) / pw;
757 float scaleY = float(h) / ph;
758 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(paperRect.x * scaleX)),
759 m_printoutDC->DeviceToLogicalY(wxRound(paperRect.y * scaleY)),
760 m_printoutDC->DeviceToLogicalXRel(wxRound(paperRect.width * scaleX)),
761 m_printoutDC->DeviceToLogicalYRel(wxRound(paperRect.height * scaleY)));
762}
763
764wxRect wxPrintout::GetLogicalPageRect() const
765{
766 // Return the rectangle in logical units that corresponds to the printable
767 // area.
768 int w, h;
769 m_printoutDC->GetSize(&w, &h);
770 return wxRect(m_printoutDC->DeviceToLogicalX(0),
771 m_printoutDC->DeviceToLogicalY(0),
772 m_printoutDC->DeviceToLogicalXRel(w),
773 m_printoutDC->DeviceToLogicalYRel(h));
774}
775
776wxRect wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData& pageSetupData) const
777{
778 // Return the rectangle in logical units that corresponds to the region
779 // within the page margins as specified by the given wxPageSetupDialogData
780 // object.
781
782 // We get the paper size in device units and the margins in mm,
783 // so we need to calculate the conversion with this trick
784 wxCoord pw, ph;
785 GetPageSizePixels(&pw, &ph);
786 wxCoord mw, mh;
787 GetPageSizeMM(&mw, &mh);
788 float mmToDeviceX = float(pw) / mw;
789 float mmToDeviceY = float(ph) / mh;
790
791 // paper size in device units
792 wxRect paperRect = GetPaperRectPixels();
793
794 // margins in mm
795 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
796 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
797
798 // calculate margins in device units
799 wxRect pageMarginsRect(
800 paperRect.x + wxRound(mmToDeviceX * topLeft.x),
801 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
802 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
803 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
804
805 wxCoord w, h;
806 m_printoutDC->GetSize(&w, &h);
807 if (w == pw && h == ph)
808 {
809 // this DC matches the printed page, so no scaling
810 return wxRect(
811 m_printoutDC->DeviceToLogicalX(pageMarginsRect.x),
812 m_printoutDC->DeviceToLogicalY(pageMarginsRect.y),
813 m_printoutDC->DeviceToLogicalXRel(pageMarginsRect.width),
814 m_printoutDC->DeviceToLogicalYRel(pageMarginsRect.height));
815 }
816
817 // This DC doesn't match the printed page, so we have to scale.
818 float scaleX = float(w) / pw;
819 float scaleY = float(h) / ph;
820 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(pageMarginsRect.x * scaleX)),
821 m_printoutDC->DeviceToLogicalY(wxRound(pageMarginsRect.y * scaleY)),
822 m_printoutDC->DeviceToLogicalXRel(wxRound(pageMarginsRect.width * scaleX)),
823 m_printoutDC->DeviceToLogicalYRel(wxRound(pageMarginsRect.height * scaleY)));
824}
825
826void wxPrintout::SetLogicalOrigin(wxCoord x, wxCoord y)
827{
828 // Set the device origin by specifying a point in logical coordinates.
829 m_printoutDC->SetDeviceOrigin(
830 m_printoutDC->LogicalToDeviceX(x),
831 m_printoutDC->LogicalToDeviceY(y) );
832}
833
834void wxPrintout::OffsetLogicalOrigin(wxCoord xoff, wxCoord yoff)
835{
836 // Offset the device origin by a specified distance in device coordinates.
837 wxPoint dev_org = m_printoutDC->GetDeviceOrigin();
838 m_printoutDC->SetDeviceOrigin(
839 dev_org.x + m_printoutDC->LogicalToDeviceXRel(xoff),
840 dev_org.y + m_printoutDC->LogicalToDeviceYRel(yoff) );
841}
842
843
844//----------------------------------------------------------------------------
845// wxPreviewCanvas
846//----------------------------------------------------------------------------
847
848IMPLEMENT_CLASS(wxPreviewCanvas, wxWindow)
849
850BEGIN_EVENT_TABLE(wxPreviewCanvas, wxScrolledWindow)
851 EVT_PAINT(wxPreviewCanvas::OnPaint)
852 EVT_CHAR(wxPreviewCanvas::OnChar)
853 EVT_IDLE(wxPreviewCanvas::OnIdle)
854 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged)
855#if wxUSE_MOUSEWHEEL
856 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel)
857#endif
858END_EVENT_TABLE()
859
860// VZ: the current code doesn't refresh properly without
861// wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
862// really horrible flicker when resizing the preview frame, but without
863// this style it simply doesn't work correctly at all...
864wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase *preview, wxWindow *parent,
865 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
866wxScrolledWindow(parent, wxID_ANY, pos, size, style | wxFULL_REPAINT_ON_RESIZE, name)
867{
868 m_printPreview = preview;
869#ifdef __WXMAC__
870 // The app workspace colour is always white, but we should have
871 // a contrast with the page.
872 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
873#elif defined(__WXGTK__)
874 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
875#else
876 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
877#endif
878 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
879
880 SetScrollbars(10, 10, 100, 100);
881}
882
883wxPreviewCanvas::~wxPreviewCanvas()
884{
885}
886
887void wxPreviewCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
888{
889 wxPaintDC dc(this);
890 PrepareDC( dc );
891
892/*
893#ifdef __WXGTK__
894 if (!GetUpdateRegion().IsEmpty())
895 dc.SetClippingRegion( GetUpdateRegion() );
896#endif
897*/
898
899 if (m_printPreview)
900 {
901 m_printPreview->PaintPage(this, dc);
902 }
903}
904
905void wxPreviewCanvas::OnIdle(wxIdleEvent& event)
906{
907 event.Skip();
908
909 // prevent UpdatePageRendering() from being called recursively:
910 static bool s_inIdle = false;
911 if ( s_inIdle )
912 return;
913 s_inIdle = true;
914
915 if ( m_printPreview )
916 {
917 if ( m_printPreview->UpdatePageRendering() )
918 Refresh();
919 }
920
921 s_inIdle = false;
922}
923
924// Responds to colour changes, and passes event on to children.
925void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent& event)
926{
927#ifdef __WXMAC__
928 // The app workspace colour is always white, but we should have
929 // a contrast with the page.
930 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
931#elif defined(__WXGTK__)
932 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
933#else
934 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
935#endif
936 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
937 Refresh();
938
939 // Propagate the event to the non-top-level children
940 wxWindow::OnSysColourChanged(event);
941}
942
943void wxPreviewCanvas::OnChar(wxKeyEvent &event)
944{
945 wxPreviewControlBar* controlBar = ((wxPreviewFrame*) GetParent())->GetControlBar();
946 switch (event.GetKeyCode())
947 {
948 case WXK_RETURN:
949 controlBar->OnPrint();
950 return;
951 case (int)'+':
952 case WXK_NUMPAD_ADD:
953 case WXK_ADD:
954 controlBar->DoZoomIn();
955 return;
956 case (int)'-':
957 case WXK_NUMPAD_SUBTRACT:
958 case WXK_SUBTRACT:
959 controlBar->DoZoomOut();
960 return;
961 }
962
963 if (!event.ControlDown())
964 {
965 event.Skip();
966 return;
967 }
968
969 switch(event.GetKeyCode())
970 {
971 case WXK_PAGEDOWN:
972 controlBar->OnNext(); break;
973 case WXK_PAGEUP:
974 controlBar->OnPrevious(); break;
975 case WXK_HOME:
976 controlBar->OnFirst(); break;
977 case WXK_END:
978 controlBar->OnLast(); break;
979 default:
980 event.Skip();
981 }
982}
983
984#if wxUSE_MOUSEWHEEL
985
986void wxPreviewCanvas::OnMouseWheel(wxMouseEvent& event)
987{
988 wxPreviewControlBar *
989 controlBar = wxStaticCast(GetParent(), wxPreviewFrame)->GetControlBar();
990
991 if ( controlBar )
992 {
993 if ( event.ControlDown() && event.GetWheelRotation() != 0 )
994 {
995 int currentZoom = controlBar->GetZoomControl();
996
997 int delta;
998 if ( currentZoom < 100 )
999 delta = 5;
1000 else if ( currentZoom <= 120 )
1001 delta = 10;
1002 else
1003 delta = 50;
1004
1005 if ( event.GetWheelRotation() > 0 )
1006 delta = -delta;
1007
1008 int newZoom = currentZoom + delta;
1009 if ( newZoom < 10 )
1010 newZoom = 10;
1011 if ( newZoom > 200 )
1012 newZoom = 200;
1013 if ( newZoom != currentZoom )
1014 {
1015 controlBar->SetZoomControl(newZoom);
1016 m_printPreview->SetZoom(newZoom);
1017 Refresh();
1018 }
1019 return;
1020 }
1021 }
1022
1023 event.Skip();
1024}
1025
1026#endif // wxUSE_MOUSEWHEEL
1027
1028namespace
1029{
1030
1031// This is by the controls in the print preview as the maximal (and hence
1032// longest) page number we may have to display.
1033enum { MAX_PAGE_NUMBER = 99999 };
1034
1035} // anonymous namespace
1036
1037// ----------------------------------------------------------------------------
1038// wxPrintPageMaxCtrl
1039// ----------------------------------------------------------------------------
1040
1041// A simple static control showing the maximal number of pages.
1042class wxPrintPageMaxCtrl : public wxStaticText
1043{
1044public:
1045 wxPrintPageMaxCtrl(wxWindow *parent)
1046 : wxStaticText(
1047 parent,
1048 wxID_ANY,
1049 wxString(),
1050 wxDefaultPosition,
1051 wxSize
1052 (
1053 parent->GetTextExtent(MaxAsString(MAX_PAGE_NUMBER)).x,
1054 wxDefaultCoord
1055 ),
1056 wxST_NO_AUTORESIZE | wxALIGN_CENTRE
1057 )
1058 {
1059 }
1060
1061 // Set the maximal page to display once we really know what it is.
1062 void SetMaxPage(int maxPage)
1063 {
1064 SetLabel(MaxAsString(maxPage));
1065 }
1066
1067private:
1068 static wxString MaxAsString(int maxPage)
1069 {
1070 return wxString::Format("/ %d", maxPage);
1071 }
1072
1073 wxDECLARE_NO_COPY_CLASS(wxPrintPageMaxCtrl);
1074};
1075
1076// ----------------------------------------------------------------------------
1077// wxPrintPageTextCtrl
1078// ----------------------------------------------------------------------------
1079
1080// This text control contains the page number in the specified interval.
1081//
1082// Invalid pages are not accepted and the control contents is validated when it
1083// loses focus. Conversely, if the user changes the page to another valid one
1084// or presses Enter, OnGotoPage() method of the preview object will be called.
1085class wxPrintPageTextCtrl : public wxTextCtrl
1086{
1087public:
1088 wxPrintPageTextCtrl(wxPreviewControlBar *preview)
1089 : wxTextCtrl(preview,
1090 wxID_PREVIEW_GOTO,
1091 wxString(),
1092 wxDefaultPosition,
1093 // We use hardcoded maximal page number for the width
1094 // instead of fitting it to the values we can show because
1095 // the control looks uncomfortably narrow if the real page
1096 // number is just one or two digits.
1097 wxSize
1098 (
1099 preview->GetTextExtent(PageAsString(MAX_PAGE_NUMBER)).x,
1100 wxDefaultCoord
1101 ),
1102 wxTE_PROCESS_ENTER
1103#if wxUSE_VALIDATORS
1104 , wxTextValidator(wxFILTER_DIGITS)
1105#endif // wxUSE_VALIDATORS
1106 ),
1107 m_preview(preview)
1108 {
1109 m_minPage =
1110 m_maxPage =
1111 m_page = 1;
1112
1113 Connect(wxEVT_KILL_FOCUS,
1114 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus));
1115 Connect(wxEVT_COMMAND_TEXT_ENTER,
1116 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter));
1117 }
1118
1119 // Update the pages range, must be called after OnPreparePrinting() as
1120 // these values are not known before.
1121 void SetPageInfo(int minPage, int maxPage)
1122 {
1123 m_minPage = minPage;
1124 m_maxPage = maxPage;
1125
1126 // Show the first page by default.
1127 SetPageNumber(minPage);
1128 }
1129
1130 // Helpers to conveniently set or get the current page number. Return value
1131 // is 0 if the current controls contents is invalid.
1132 void SetPageNumber(int page)
1133 {
1134 wxASSERT( IsValidPage(page) );
1135
1136 SetValue(PageAsString(page));
1137 }
1138
1139 int GetPageNumber() const
1140 {
1141 long value;
1142 if ( !GetValue().ToLong(&value) || !IsValidPage(value) )
1143 return 0;
1144
1145 // Cast is safe because the value is less than (int) m_maxPage.
1146 return static_cast<int>(value);
1147 }
1148
1149private:
1150 static wxString PageAsString(int page)
1151 {
1152 return wxString::Format("%d", page);
1153 }
1154
1155 bool IsValidPage(int page) const
1156 {
1157 return page >= m_minPage && page <= m_maxPage;
1158 }
1159
1160 bool DoChangePage()
1161 {
1162 const int page = GetPageNumber();
1163
1164 if ( !page )
1165 return false;
1166
1167 if ( page != m_page )
1168 {
1169 // We have a valid page, remember it.
1170 m_page = page;
1171
1172 // And notify the owner about the change.
1173 m_preview->OnGotoPage();
1174 }
1175 //else: Nothing really changed.
1176
1177 return true;
1178 }
1179
1180 void OnKillFocus(wxFocusEvent& event)
1181 {
1182 if ( !DoChangePage() )
1183 {
1184 // The current contents is invalid so reset it back to the last
1185 // known good page index.
1186 SetPageNumber(m_page);
1187 }
1188
1189 event.Skip();
1190 }
1191
1192 void OnTextEnter(wxCommandEvent& WXUNUSED(event))
1193 {
1194 DoChangePage();
1195 }
1196
1197
1198 wxPreviewControlBar * const m_preview;
1199
1200 int m_minPage,
1201 m_maxPage;
1202
1203 // This is the last valid page value that we had, we revert to it if an
1204 // invalid page is entered.
1205 int m_page;
1206
1207 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl);
1208};
1209
1210//----------------------------------------------------------------------------
1211// wxPreviewControlBar
1212//----------------------------------------------------------------------------
1213
1214IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
1215
1216BEGIN_EVENT_TABLE(wxPreviewControlBar, wxPanel)
1217 EVT_BUTTON(wxID_PREVIEW_CLOSE, wxPreviewControlBar::OnWindowClose)
1218 EVT_BUTTON(wxID_PREVIEW_PRINT, wxPreviewControlBar::OnPrintButton)
1219 EVT_BUTTON(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnPreviousButton)
1220 EVT_BUTTON(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnNextButton)
1221 EVT_BUTTON(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnFirstButton)
1222 EVT_BUTTON(wxID_PREVIEW_LAST, wxPreviewControlBar::OnLastButton)
1223 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnZoomInButton)
1224 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnZoomOutButton)
1225
1226 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnUpdatePreviousButton)
1227 EVT_UPDATE_UI(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnUpdateNextButton)
1228 EVT_UPDATE_UI(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnUpdateFirstButton)
1229 EVT_UPDATE_UI(wxID_PREVIEW_LAST, wxPreviewControlBar::OnUpdateLastButton)
1230 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnUpdateZoomInButton)
1231 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnUpdateZoomOutButton)
1232
1233 EVT_CHOICE(wxID_PREVIEW_ZOOM, wxPreviewControlBar::OnZoomChoice)
1234 EVT_PAINT(wxPreviewControlBar::OnPaint)
1235
1236END_EVENT_TABLE()
1237
1238wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
1239 wxWindow *parent, const wxPoint& pos, const wxSize& size,
1240 long style, const wxString& name):
1241wxPanel(parent, wxID_ANY, pos, size, style, name)
1242{
1243 m_printPreview = preview;
1244 m_closeButton = NULL;
1245 m_zoomControl = NULL;
1246 m_currentPageText = NULL;
1247 m_maxPageText = NULL;
1248 m_buttonFlags = buttons;
1249}
1250
1251wxPreviewControlBar::~wxPreviewControlBar()
1252{
1253}
1254
1255void wxPreviewControlBar::OnPaint(wxPaintEvent& WXUNUSED(event))
1256{
1257 wxPaintDC dc(this);
1258
1259 int w, h;
1260 GetSize(&w, &h);
1261 dc.SetPen(*wxBLACK_PEN);
1262 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1263 dc.DrawLine( 0, h-1, w, h-1 );
1264}
1265
1266void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
1267{
1268 wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
1269 frame->Close(true);
1270}
1271
1272void wxPreviewControlBar::OnPrint(void)
1273{
1274 wxPrintPreviewBase *preview = GetPrintPreview();
1275 preview->Print(true);
1276}
1277
1278void wxPreviewControlBar::OnNext()
1279{
1280 if ( IsNextEnabled() )
1281 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1282}
1283
1284void wxPreviewControlBar::OnPrevious()
1285{
1286 if ( IsPreviousEnabled() )
1287 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1288}
1289
1290void wxPreviewControlBar::OnFirst()
1291{
1292 if ( IsFirstEnabled() )
1293 DoGotoPage(GetPrintPreview()->GetMinPage());
1294}
1295
1296void wxPreviewControlBar::OnLast()
1297{
1298 if ( IsLastEnabled() )
1299 DoGotoPage(GetPrintPreview()->GetMaxPage());
1300}
1301
1302bool wxPreviewControlBar::IsNextEnabled() const
1303{
1304 wxPrintPreviewBase *preview = GetPrintPreview();
1305 if ( !preview )
1306 return false;
1307
1308 const int currentPage = preview->GetCurrentPage();
1309 return currentPage < preview->GetMaxPage() &&
1310 preview->GetPrintout()->HasPage(currentPage + 1);
1311}
1312
1313bool wxPreviewControlBar::IsPreviousEnabled() const
1314{
1315 wxPrintPreviewBase *preview = GetPrintPreview();
1316 if ( !preview )
1317 return false;
1318
1319 const int currentPage = preview->GetCurrentPage();
1320 return currentPage > preview->GetMinPage() &&
1321 preview->GetPrintout()->HasPage(currentPage - 1);
1322}
1323
1324bool wxPreviewControlBar::IsFirstEnabled() const
1325{
1326 wxPrintPreviewBase *preview = GetPrintPreview();
1327 if (!preview)
1328 return false;
1329
1330 return preview->GetPrintout()->HasPage(preview->GetMinPage());
1331}
1332
1333bool wxPreviewControlBar::IsLastEnabled() const
1334{
1335 wxPrintPreviewBase *preview = GetPrintPreview();
1336 if (!preview)
1337 return false;
1338
1339 return preview->GetPrintout()->HasPage(preview->GetMaxPage());
1340}
1341
1342void wxPreviewControlBar::DoGotoPage(int page)
1343{
1344 wxPrintPreviewBase *preview = GetPrintPreview();
1345 wxCHECK_RET( preview, "Shouldn't be called if there is no preview." );
1346
1347 preview->SetCurrentPage(page);
1348
1349 if ( m_currentPageText )
1350 m_currentPageText->SetPageNumber(page);
1351}
1352
1353void wxPreviewControlBar::OnGotoPage()
1354{
1355 wxPrintPreviewBase *preview = GetPrintPreview();
1356 if (preview)
1357 {
1358 if (preview->GetMinPage() > 0)
1359 {
1360 long currentPage = m_currentPageText->GetPageNumber();
1361 if ( currentPage )
1362 {
1363 if (preview->GetPrintout()->HasPage(currentPage))
1364 {
1365 preview->SetCurrentPage(currentPage);
1366 }
1367 }
1368 }
1369 }
1370}
1371
1372void wxPreviewControlBar::DoZoom()
1373{
1374 int zoom = GetZoomControl();
1375 if (GetPrintPreview())
1376 GetPrintPreview()->SetZoom(zoom);
1377}
1378
1379bool wxPreviewControlBar::IsZoomInEnabled() const
1380{
1381 if ( !m_zoomControl )
1382 return false;
1383
1384 const unsigned sel = m_zoomControl->GetSelection();
1385 return sel < m_zoomControl->GetCount() - 1;
1386}
1387
1388bool wxPreviewControlBar::IsZoomOutEnabled() const
1389{
1390 return m_zoomControl && m_zoomControl->GetSelection() > 0;
1391}
1392
1393void wxPreviewControlBar::DoZoomIn()
1394{
1395 if (IsZoomInEnabled())
1396 {
1397 m_zoomControl->SetSelection(m_zoomControl->GetSelection() + 1);
1398 DoZoom();
1399 }
1400}
1401
1402void wxPreviewControlBar::DoZoomOut()
1403{
1404 if (IsZoomOutEnabled())
1405 {
1406 m_zoomControl->SetSelection(m_zoomControl->GetSelection() - 1);
1407 DoZoom();
1408 }
1409}
1410
1411namespace
1412{
1413
1414// Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1415// sequentially to it in the simplest way possible.
1416class SizerWithButtons
1417{
1418public:
1419 // Constructor creates the sizer that will hold the buttons and stores the
1420 // parent that will be used for their creation.
1421 SizerWithButtons(wxWindow *parent)
1422 : m_sizer(new wxBoxSizer(wxHORIZONTAL)),
1423 m_parent(parent)
1424 {
1425 m_hasContents =
1426 m_needsSeparator = false;
1427 }
1428
1429 // Destructor associates the sizer with the parent window.
1430 ~SizerWithButtons()
1431 {
1432 m_parent->SetSizer(m_sizer);
1433 m_sizer->Fit(m_parent);
1434 }
1435
1436
1437 // Add an arbitrary window to the sizer.
1438 void Add(wxWindow *win)
1439 {
1440 if ( m_needsSeparator )
1441 {
1442 m_needsSeparator = false;
1443
1444 m_sizer->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1445 }
1446
1447 m_hasContents = true;
1448
1449 m_sizer->Add(win,
1450 wxSizerFlags().Border(wxLEFT | wxTOP | wxBOTTOM).Center());
1451 }
1452
1453 // Add a button with the specified id, bitmap and tooltip.
1454 void AddButton(wxWindowID btnId,
1455 const wxArtID& artId,
1456 const wxString& tooltip)
1457 {
1458 // We don't use (smaller) images inside a button with a text label but
1459 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1460 // wxART_BUTTON here.
1461 wxBitmap bmp = wxArtProvider::GetBitmap(artId, wxART_TOOLBAR);
1462 wxBitmapButton * const btn = new wxBitmapButton(m_parent, btnId, bmp);
1463 btn->SetToolTip(tooltip);
1464
1465 Add(btn);
1466 }
1467
1468 // Add a control at the right end of the window. This should be called last
1469 // as everything else added after it will be added on the right side too.
1470 void AddAtEnd(wxWindow *win)
1471 {
1472 m_sizer->AddStretchSpacer();
1473 m_sizer->Add(win,
1474 wxSizerFlags().Border(wxTOP | wxBOTTOM | wxRIGHT).Center());
1475 }
1476
1477 // Indicates the end of a group of buttons, a separator will be added after
1478 // it.
1479 void EndOfGroup()
1480 {
1481 if ( m_hasContents )
1482 {
1483 m_needsSeparator = true;
1484 m_hasContents = false;
1485 }
1486 }
1487
1488private:
1489 wxSizer * const m_sizer;
1490 wxWindow * const m_parent;
1491
1492 // If true, we have some controls since the last group beginning. This is
1493 // used to avoid inserting two consecutive separators if EndOfGroup() is
1494 // called twice.
1495 bool m_hasContents;
1496
1497 // If true, a separator should be inserted before adding the next button.
1498 bool m_needsSeparator;
1499
1500 wxDECLARE_NO_COPY_CLASS(SizerWithButtons);
1501};
1502
1503} // anonymous namespace
1504
1505void wxPreviewControlBar::CreateButtons()
1506{
1507 SizerWithButtons sizer(this);
1508
1509 // Print button group (a single button).
1510 if (m_buttonFlags & wxPREVIEW_PRINT)
1511 {
1512 sizer.AddButton(wxID_PREVIEW_PRINT, wxART_PRINT, _("Print"));
1513 sizer.EndOfGroup();
1514 }
1515
1516 // Page selection buttons group.
1517 if (m_buttonFlags & wxPREVIEW_FIRST)
1518 {
1519 sizer.AddButton(wxID_PREVIEW_FIRST, wxART_GOTO_FIRST, _("First page"));
1520 }
1521
1522 if (m_buttonFlags & wxPREVIEW_PREVIOUS)
1523 {
1524 sizer.AddButton(wxID_PREVIEW_PREVIOUS, wxART_GO_BACK, _("Previous page"));
1525 }
1526
1527 if (m_buttonFlags & wxPREVIEW_GOTO)
1528 {
1529 m_currentPageText = new wxPrintPageTextCtrl(this);
1530 sizer.Add(m_currentPageText);
1531
1532 m_maxPageText = new wxPrintPageMaxCtrl(this);
1533 sizer.Add(m_maxPageText);
1534 }
1535
1536 if (m_buttonFlags & wxPREVIEW_NEXT)
1537 {
1538 sizer.AddButton(wxID_PREVIEW_NEXT, wxART_GO_FORWARD, _("Next page"));
1539 }
1540
1541 if (m_buttonFlags & wxPREVIEW_LAST)
1542 {
1543 sizer.AddButton(wxID_PREVIEW_LAST, wxART_GOTO_LAST, _("Last page"));
1544 }
1545
1546 sizer.EndOfGroup();
1547
1548 // Zoom controls group.
1549 if (m_buttonFlags & wxPREVIEW_ZOOM)
1550 {
1551 sizer.AddButton(wxID_PREVIEW_ZOOM_OUT, wxART_MINUS, _("Zoom Out"));
1552
1553 wxString choices[] =
1554 {
1555 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
1556 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1557 wxT("120%"), wxT("150%"), wxT("200%")
1558 };
1559 int n = WXSIZEOF(choices);
1560
1561 m_zoomControl = new wxChoice( this, wxID_PREVIEW_ZOOM, wxDefaultPosition, wxSize(70,wxDefaultCoord), n, choices, 0 );
1562 sizer.Add(m_zoomControl);
1563 SetZoomControl(m_printPreview->GetZoom());
1564
1565 sizer.AddButton(wxID_PREVIEW_ZOOM_IN, wxART_PLUS, _("Zoom In"));
1566
1567 sizer.EndOfGroup();
1568 }
1569
1570 // Close button group (single button again).
1571 m_closeButton = new wxButton(this, wxID_PREVIEW_CLOSE, _("&Close"));
1572 sizer.AddAtEnd(m_closeButton);
1573}
1574
1575void wxPreviewControlBar::SetPageInfo(int minPage, int maxPage)
1576{
1577 if ( m_currentPageText )
1578 m_currentPageText->SetPageInfo(minPage, maxPage);
1579
1580 if ( m_maxPageText )
1581 m_maxPageText->SetMaxPage(maxPage);
1582}
1583
1584void wxPreviewControlBar::SetZoomControl(int zoom)
1585{
1586 if (m_zoomControl)
1587 {
1588 int n, count = m_zoomControl->GetCount();
1589 long val;
1590 for (n=0; n<count; n++)
1591 {
1592 if (m_zoomControl->GetString(n).BeforeFirst(wxT('%')).ToLong(&val) &&
1593 (val >= long(zoom)))
1594 {
1595 m_zoomControl->SetSelection(n);
1596 return;
1597 }
1598 }
1599
1600 m_zoomControl->SetSelection(count-1);
1601 }
1602}
1603
1604int wxPreviewControlBar::GetZoomControl()
1605{
1606 if (m_zoomControl && (m_zoomControl->GetStringSelection() != wxEmptyString))
1607 {
1608 long val;
1609 if (m_zoomControl->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val))
1610 return int(val);
1611 }
1612
1613 return 0;
1614}
1615
1616
1617/*
1618* Preview frame
1619*/
1620
1621IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
1622
1623BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
1624 EVT_CHAR_HOOK(wxPreviewFrame::OnChar)
1625 EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
1626END_EVENT_TABLE()
1627
1628void wxPreviewFrame::OnChar(wxKeyEvent &event)
1629{
1630 if ( event.GetKeyCode() == WXK_ESCAPE )
1631 {
1632 Close(true);
1633 }
1634 else
1635 {
1636 event.Skip();
1637 }
1638}
1639
1640wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
1641 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
1642wxFrame(parent, wxID_ANY, title, pos, size, style, name)
1643{
1644 m_printPreview = preview;
1645 m_controlBar = NULL;
1646 m_previewCanvas = NULL;
1647 m_windowDisabler = NULL;
1648 m_modalityKind = wxPreviewFrame_NonModal;
1649
1650 // Give the application icon
1651#ifdef __WXMSW__
1652 wxFrame* topFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
1653 if (topFrame)
1654 SetIcons(topFrame->GetIcons());
1655#endif
1656}
1657
1658wxPreviewFrame::~wxPreviewFrame()
1659{
1660 wxPrintout *printout = m_printPreview->GetPrintout();
1661 if (printout)
1662 {
1663 delete printout;
1664 m_printPreview->SetPrintout(NULL);
1665 m_printPreview->SetCanvas(NULL);
1666 m_printPreview->SetFrame(NULL);
1667 }
1668
1669 m_previewCanvas->SetPreview(NULL);
1670 delete m_printPreview;
1671}
1672
1673void wxPreviewFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
1674{
1675 // Reenable any windows we disabled by undoing whatever we did in our
1676 // Initialize().
1677 switch ( m_modalityKind )
1678 {
1679 case wxPreviewFrame_AppModal:
1680 delete m_windowDisabler;
1681 m_windowDisabler = NULL;
1682 break;
1683
1684 case wxPreviewFrame_WindowModal:
1685 if ( GetParent() )
1686 GetParent()->Enable();
1687 break;
1688
1689 case wxPreviewFrame_NonModal:
1690 break;
1691 }
1692
1693 Destroy();
1694}
1695
1696void wxPreviewFrame::InitializeWithModality(wxPreviewFrameModalityKind kind)
1697{
1698#if wxUSE_STATUSBAR
1699 CreateStatusBar();
1700#endif
1701 CreateCanvas();
1702 CreateControlBar();
1703
1704 m_printPreview->SetCanvas(m_previewCanvas);
1705 m_printPreview->SetFrame(this);
1706
1707 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
1708
1709 item0->Add( m_controlBar, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1710 item0->Add( m_previewCanvas, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1711
1712 SetAutoLayout( true );
1713 SetSizer( item0 );
1714
1715 m_modalityKind = kind;
1716 switch ( m_modalityKind )
1717 {
1718 case wxPreviewFrame_AppModal:
1719 // Disable everything.
1720 m_windowDisabler = new wxWindowDisabler( this );
1721 break;
1722
1723 case wxPreviewFrame_WindowModal:
1724 // Disable our parent if we have one.
1725 if ( GetParent() )
1726 GetParent()->Disable();
1727 break;
1728
1729 case wxPreviewFrame_NonModal:
1730 // Nothing to do, we don't need to disable any windows.
1731 break;
1732 }
1733
1734 if ( m_modalityKind != wxPreviewFrame_NonModal )
1735 {
1736 // Behave like modal dialogs, don't show in taskbar. This implies
1737 // removing the minimize box, because minimizing windows without
1738 // taskbar entry is confusing.
1739 SetWindowStyle((GetWindowStyle() & ~wxMINIMIZE_BOX) | wxFRAME_NO_TASKBAR);
1740 }
1741
1742 Layout();
1743
1744 m_printPreview->AdjustScrollbars(m_previewCanvas);
1745 m_previewCanvas->SetFocus();
1746 m_controlBar->SetFocus();
1747}
1748
1749void wxPreviewFrame::CreateCanvas()
1750{
1751 m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
1752}
1753
1754void wxPreviewFrame::CreateControlBar()
1755{
1756 long buttons = wxPREVIEW_DEFAULT;
1757 if (m_printPreview->GetPrintoutForPrinting())
1758 buttons |= wxPREVIEW_PRINT;
1759
1760 m_controlBar = new wxPreviewControlBar(m_printPreview, buttons, this);
1761 m_controlBar->CreateButtons();
1762}
1763
1764/*
1765* Print preview
1766*/
1767
1768IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
1769
1770wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1771 wxPrintout *printoutForPrinting,
1772 wxPrintData *data)
1773{
1774 if (data)
1775 m_printDialogData = (*data);
1776
1777 Init(printout, printoutForPrinting);
1778}
1779
1780wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1781 wxPrintout *printoutForPrinting,
1782 wxPrintDialogData *data)
1783{
1784 if (data)
1785 m_printDialogData = (*data);
1786
1787 Init(printout, printoutForPrinting);
1788}
1789
1790void wxPrintPreviewBase::Init(wxPrintout *printout,
1791 wxPrintout *printoutForPrinting)
1792{
1793 m_isOk = true;
1794 m_previewPrintout = printout;
1795 if (m_previewPrintout)
1796 m_previewPrintout->SetPreview(static_cast<wxPrintPreview *>(this));
1797
1798 m_printPrintout = printoutForPrinting;
1799
1800 m_previewCanvas = NULL;
1801 m_previewFrame = NULL;
1802 m_previewBitmap = NULL;
1803 m_previewFailed = false;
1804 m_currentPage = 1;
1805 m_currentZoom = 70;
1806 m_topMargin =
1807 m_leftMargin = 2*wxSizerFlags::GetDefaultBorder();
1808 m_pageWidth = 0;
1809 m_pageHeight = 0;
1810 m_printingPrepared = false;
1811 m_minPage = 1;
1812 m_maxPage = 1;
1813}
1814
1815wxPrintPreviewBase::~wxPrintPreviewBase()
1816{
1817 if (m_previewPrintout)
1818 delete m_previewPrintout;
1819 if (m_previewBitmap)
1820 delete m_previewBitmap;
1821 if (m_printPrintout)
1822 delete m_printPrintout;
1823}
1824
1825bool wxPrintPreviewBase::SetCurrentPage(int pageNum)
1826{
1827 if (m_currentPage == pageNum)
1828 return true;
1829
1830 m_currentPage = pageNum;
1831
1832 InvalidatePreviewBitmap();
1833
1834 if (m_previewCanvas)
1835 {
1836 AdjustScrollbars(m_previewCanvas);
1837
1838 m_previewCanvas->Refresh();
1839 m_previewCanvas->SetFocus();
1840 }
1841 return true;
1842}
1843
1844int wxPrintPreviewBase::GetCurrentPage() const
1845 { return m_currentPage; }
1846void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
1847 { m_previewPrintout = printout; }
1848wxPrintout *wxPrintPreviewBase::GetPrintout() const
1849 { return m_previewPrintout; }
1850wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
1851 { return m_printPrintout; }
1852void wxPrintPreviewBase::SetFrame(wxFrame *frame)
1853 { m_previewFrame = frame; }
1854void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
1855 { m_previewCanvas = canvas; }
1856wxFrame *wxPrintPreviewBase::GetFrame() const
1857 { return m_previewFrame; }
1858wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
1859 { return m_previewCanvas; }
1860
1861void wxPrintPreviewBase::CalcRects(wxPreviewCanvas *canvas, wxRect& pageRect, wxRect& paperRect)
1862{
1863 // Calculate the rectangles for the printable area of the page and the
1864 // entire paper as they appear on the canvas on-screen.
1865 int canvasWidth, canvasHeight;
1866 canvas->GetSize(&canvasWidth, &canvasHeight);
1867
1868 float zoomScale = float(m_currentZoom) / 100;
1869 float screenPrintableWidth = zoomScale * m_pageWidth * m_previewScaleX;
1870 float screenPrintableHeight = zoomScale * m_pageHeight * m_previewScaleY;
1871
1872 wxRect devicePaperRect = m_previewPrintout->GetPaperRectPixels();
1873 wxCoord devicePrintableWidth, devicePrintableHeight;
1874 m_previewPrintout->GetPageSizePixels(&devicePrintableWidth, &devicePrintableHeight);
1875 float scaleX = screenPrintableWidth / devicePrintableWidth;
1876 float scaleY = screenPrintableHeight / devicePrintableHeight;
1877 paperRect.width = wxCoord(scaleX * devicePaperRect.width);
1878 paperRect.height = wxCoord(scaleY * devicePaperRect.height);
1879
1880 paperRect.x = wxCoord((canvasWidth - paperRect.width)/ 2.0);
1881 if (paperRect.x < m_leftMargin)
1882 paperRect.x = m_leftMargin;
1883 paperRect.y = wxCoord((canvasHeight - paperRect.height)/ 2.0);
1884 if (paperRect.y < m_topMargin)
1885 paperRect.y = m_topMargin;
1886
1887 pageRect.x = paperRect.x - wxCoord(scaleX * devicePaperRect.x);
1888 pageRect.y = paperRect.y - wxCoord(scaleY * devicePaperRect.y);
1889 pageRect.width = wxCoord(screenPrintableWidth);
1890 pageRect.height = wxCoord(screenPrintableHeight);
1891}
1892
1893
1894void wxPrintPreviewBase::InvalidatePreviewBitmap()
1895{
1896 wxDELETE(m_previewBitmap);
1897 // if there was a problem with rendering the preview, try again now
1898 // that it changed in some way (less memory may be needed, for example):
1899 m_previewFailed = false;
1900}
1901
1902bool wxPrintPreviewBase::UpdatePageRendering()
1903{
1904 if ( m_previewBitmap )
1905 return false;
1906
1907 if ( m_previewFailed )
1908 return false;
1909
1910 if ( !RenderPage(m_currentPage) )
1911 {
1912 m_previewFailed = true; // don't waste time failing again
1913 return false;
1914 }
1915
1916 return true;
1917}
1918
1919bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
1920{
1921 DrawBlankPage(canvas, dc);
1922
1923 if (!m_previewBitmap)
1924 return false;
1925 if (!canvas)
1926 return false;
1927
1928 wxRect pageRect, paperRect;
1929 CalcRects(canvas, pageRect, paperRect);
1930 wxMemoryDC temp_dc;
1931 temp_dc.SelectObject(*m_previewBitmap);
1932
1933 dc.Blit(pageRect.x, pageRect.y,
1934 m_previewBitmap->GetWidth(), m_previewBitmap->GetHeight(), &temp_dc, 0, 0);
1935
1936 temp_dc.SelectObject(wxNullBitmap);
1937 return true;
1938}
1939
1940// Adjusts the scrollbars for the current scale
1941void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas *canvas)
1942{
1943 if (!canvas)
1944 return ;
1945
1946 wxRect pageRect, paperRect;
1947 CalcRects(canvas, pageRect, paperRect);
1948 int totalWidth = paperRect.width + 2 * m_leftMargin;
1949 int totalHeight = paperRect.height + 2 * m_topMargin;
1950 int scrollUnitsX = totalWidth / 10;
1951 int scrollUnitsY = totalHeight / 10;
1952 wxSize virtualSize = canvas->GetVirtualSize();
1953 if (virtualSize.GetWidth() != totalWidth || virtualSize.GetHeight() != totalHeight)
1954 canvas->SetScrollbars(10, 10, scrollUnitsX, scrollUnitsY, 0, 0, true);
1955}
1956
1957bool wxPrintPreviewBase::RenderPageIntoDC(wxDC& dc, int pageNum)
1958{
1959 m_previewPrintout->SetDC(&dc);
1960 m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
1961
1962 // Need to delay OnPreparePrinting() until here, so we have enough
1963 // information and a wxDC.
1964 if (!m_printingPrepared)
1965 {
1966 m_printingPrepared = true;
1967
1968 m_previewPrintout->OnPreparePrinting();
1969 int selFrom, selTo;
1970 m_previewPrintout->GetPageInfo(&m_minPage, &m_maxPage, &selFrom, &selTo);
1971
1972 // Update the wxPreviewControlBar page range display.
1973 if ( m_previewFrame )
1974 {
1975 wxPreviewControlBar * const
1976 controlBar = ((wxPreviewFrame*)m_previewFrame)->GetControlBar();
1977 if ( controlBar )
1978 controlBar->SetPageInfo(m_minPage, m_maxPage);
1979 }
1980 }
1981
1982 m_previewPrintout->OnBeginPrinting();
1983
1984 if (!m_previewPrintout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
1985 {
1986 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK);
1987 return false;
1988 }
1989
1990 m_previewPrintout->OnPrintPage(pageNum);
1991 m_previewPrintout->OnEndDocument();
1992 m_previewPrintout->OnEndPrinting();
1993
1994 m_previewPrintout->SetDC(NULL);
1995
1996 return true;
1997}
1998
1999bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap& bmp, int pageNum)
2000{
2001 wxMemoryDC memoryDC;
2002 memoryDC.SelectObject(bmp);
2003 memoryDC.Clear();
2004
2005 return RenderPageIntoDC(memoryDC, pageNum);
2006}
2007
2008bool wxPrintPreviewBase::RenderPage(int pageNum)
2009{
2010 wxBusyCursor busy;
2011
2012 if (!m_previewCanvas)
2013 {
2014 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
2015 return false;
2016 }
2017
2018 wxRect pageRect, paperRect;
2019 CalcRects(m_previewCanvas, pageRect, paperRect);
2020
2021 if (!m_previewBitmap)
2022 {
2023 m_previewBitmap = new wxBitmap(pageRect.width, pageRect.height);
2024
2025 if (!m_previewBitmap || !m_previewBitmap->IsOk())
2026 {
2027 InvalidatePreviewBitmap();
2028 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
2029 return false;
2030 }
2031 }
2032
2033 if ( !RenderPageIntoBitmap(*m_previewBitmap, pageNum) )
2034 {
2035 InvalidatePreviewBitmap();
2036 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
2037 return false;
2038 }
2039
2040#if wxUSE_STATUSBAR
2041 wxString status;
2042 if (m_maxPage != 0)
2043 status = wxString::Format(_("Page %d of %d"), pageNum, m_maxPage);
2044 else
2045 status = wxString::Format(_("Page %d"), pageNum);
2046
2047 if (m_previewFrame)
2048 m_previewFrame->SetStatusText(status);
2049#endif
2050
2051 return true;
2052}
2053
2054bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
2055{
2056 wxRect pageRect, paperRect;
2057
2058 CalcRects(canvas, pageRect, paperRect);
2059
2060 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
2061 wxCoord shadowOffset = 4;
2062
2063 dc.SetPen(*wxBLACK_PEN);
2064 dc.SetBrush(*wxBLACK_BRUSH);
2065 dc.DrawRectangle(paperRect.x + shadowOffset, paperRect.y + paperRect.height + 1,
2066 paperRect.width, shadowOffset);
2067
2068 dc.DrawRectangle(paperRect.x + paperRect.width, paperRect.y + shadowOffset,
2069 shadowOffset, paperRect.height);
2070
2071 // Draw blank page allowing for 1-pixel border AROUND the actual paper
2072 dc.SetPen(*wxBLACK_PEN);
2073 dc.SetBrush(*wxWHITE_BRUSH);
2074 dc.DrawRectangle(paperRect.x - 2, paperRect.y - 1,
2075 paperRect.width + 3, paperRect.height + 2);
2076
2077 return true;
2078}
2079
2080void wxPrintPreviewBase::SetZoom(int percent)
2081{
2082 if (m_currentZoom == percent)
2083 return;
2084
2085 m_currentZoom = percent;
2086
2087 InvalidatePreviewBitmap();
2088
2089 if (m_previewCanvas)
2090 {
2091 AdjustScrollbars(m_previewCanvas);
2092 ((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
2093 m_previewCanvas->ClearBackground();
2094 m_previewCanvas->Refresh();
2095 m_previewCanvas->SetFocus();
2096 }
2097}
2098
2099wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
2100{
2101 return m_printDialogData;
2102}
2103
2104int wxPrintPreviewBase::GetZoom() const
2105{ return m_currentZoom; }
2106int wxPrintPreviewBase::GetMaxPage() const
2107{ return m_maxPage; }
2108int wxPrintPreviewBase::GetMinPage() const
2109{ return m_minPage; }
2110bool wxPrintPreviewBase::IsOk() const
2111{ return m_isOk; }
2112void wxPrintPreviewBase::SetOk(bool ok)
2113{ m_isOk = ok; }
2114
2115//----------------------------------------------------------------------------
2116// wxPrintPreview
2117//----------------------------------------------------------------------------
2118
2119IMPLEMENT_CLASS(wxPrintPreview, wxPrintPreviewBase)
2120
2121wxPrintPreview::wxPrintPreview(wxPrintout *printout,
2122 wxPrintout *printoutForPrinting,
2123 wxPrintDialogData *data) :
2124 wxPrintPreviewBase( printout, printoutForPrinting, data )
2125{
2126 m_pimpl = wxPrintFactory::GetFactory()->
2127 CreatePrintPreview( printout, printoutForPrinting, data );
2128}
2129
2130wxPrintPreview::wxPrintPreview(wxPrintout *printout,
2131 wxPrintout *printoutForPrinting,
2132 wxPrintData *data ) :
2133 wxPrintPreviewBase( printout, printoutForPrinting, data )
2134{
2135 m_pimpl = wxPrintFactory::GetFactory()->
2136 CreatePrintPreview( printout, printoutForPrinting, data );
2137}
2138
2139wxPrintPreview::~wxPrintPreview()
2140{
2141 delete m_pimpl;
2142
2143 // don't delete twice
2144 m_printPrintout = NULL;
2145 m_previewPrintout = NULL;
2146 m_previewBitmap = NULL;
2147}
2148
2149bool wxPrintPreview::SetCurrentPage(int pageNum)
2150{
2151 return m_pimpl->SetCurrentPage( pageNum );
2152}
2153
2154int wxPrintPreview::GetCurrentPage() const
2155{
2156 return m_pimpl->GetCurrentPage();
2157}
2158
2159void wxPrintPreview::SetPrintout(wxPrintout *printout)
2160{
2161 m_pimpl->SetPrintout( printout );
2162}
2163
2164wxPrintout *wxPrintPreview::GetPrintout() const
2165{
2166 return m_pimpl->GetPrintout();
2167}
2168
2169wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
2170{
2171 return m_pimpl->GetPrintoutForPrinting();
2172}
2173
2174void wxPrintPreview::SetFrame(wxFrame *frame)
2175{
2176 m_pimpl->SetFrame( frame );
2177}
2178
2179void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
2180{
2181 m_pimpl->SetCanvas( canvas );
2182}
2183
2184wxFrame *wxPrintPreview::GetFrame() const
2185{
2186 return m_pimpl->GetFrame();
2187}
2188
2189wxPreviewCanvas *wxPrintPreview::GetCanvas() const
2190{
2191 return m_pimpl->GetCanvas();
2192}
2193
2194bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
2195{
2196 return m_pimpl->PaintPage( canvas, dc );
2197}
2198
2199bool wxPrintPreview::UpdatePageRendering()
2200{
2201 return m_pimpl->UpdatePageRendering();
2202}
2203
2204bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
2205{
2206 return m_pimpl->DrawBlankPage( canvas, dc );
2207}
2208
2209void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas *canvas)
2210{
2211 m_pimpl->AdjustScrollbars( canvas );
2212}
2213
2214bool wxPrintPreview::RenderPage(int pageNum)
2215{
2216 return m_pimpl->RenderPage( pageNum );
2217}
2218
2219void wxPrintPreview::SetZoom(int percent)
2220{
2221 m_pimpl->SetZoom( percent );
2222}
2223
2224int wxPrintPreview::GetZoom() const
2225{
2226 return m_pimpl->GetZoom();
2227}
2228
2229wxPrintDialogData& wxPrintPreview::GetPrintDialogData()
2230{
2231 return m_pimpl->GetPrintDialogData();
2232}
2233
2234int wxPrintPreview::GetMaxPage() const
2235{
2236 return m_pimpl->GetMaxPage();
2237}
2238
2239int wxPrintPreview::GetMinPage() const
2240{
2241 return m_pimpl->GetMinPage();
2242}
2243
2244bool wxPrintPreview::IsOk() const
2245{
2246 return m_pimpl->IsOk();
2247}
2248
2249void wxPrintPreview::SetOk(bool ok)
2250{
2251 m_pimpl->SetOk( ok );
2252}
2253
2254bool wxPrintPreview::Print(bool interactive)
2255{
2256 return m_pimpl->Print( interactive );
2257}
2258
2259void wxPrintPreview::DetermineScaling()
2260{
2261 m_pimpl->DetermineScaling();
2262}
2263
2264#endif // wxUSE_PRINTING_ARCHITECTURE