]> git.saurik.com Git - wxWidgets.git/blame - src/common/prntbase.cpp
Better compatibility with old files when creating an image cache
[wxWidgets.git] / src / common / prntbase.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
cb7d7375 2// Name: src/common/prntbase.cpp
c801d85f
KB
3// Purpose: Printing framework base class implementation
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
55d99c7a 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
c801d85f
KB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
8898456d 16 #pragma hdrstop
c801d85f
KB
17#endif
18
d427503c
VZ
19#if wxUSE_PRINTING_ARCHITECTURE
20
6d50343d
WS
21#include "wx/dcprint.h"
22
c801d85f 23#ifndef WX_PRECOMP
57bd4c60
WS
24 #if defined(__WXMSW__)
25 #include "wx/msw/wrapcdlg.h"
26 #endif // MSW
8898456d
WS
27 #include "wx/utils.h"
28 #include "wx/dc.h"
29 #include "wx/app.h"
5a70d3f5 30 #include "wx/math.h"
8898456d
WS
31 #include "wx/msgdlg.h"
32 #include "wx/layout.h"
33 #include "wx/choice.h"
34 #include "wx/button.h"
424da8bd 35 #include "wx/bmpbuttn.h"
8898456d
WS
36 #include "wx/settings.h"
37 #include "wx/dcmemory.h"
23205be8 38 #include "wx/dcclient.h"
8898456d
WS
39 #include "wx/stattext.h"
40 #include "wx/intl.h"
41 #include "wx/textdlg.h"
42 #include "wx/sizer.h"
02761f6c 43 #include "wx/module.h"
2b5f62a0 44#endif // !WX_PRECOMP
c801d85f
KB
45
46#include "wx/prntbase.h"
c801d85f 47#include "wx/printdlg.h"
e81e3883 48#include "wx/print.h"
147bf263 49#include "wx/dcprint.h"
82579461 50#include "wx/artprov.h"
c801d85f
KB
51
52#include <stdlib.h>
53#include <string.h>
54
891daf8c
RR
55#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
56#include "wx/msw/printdlg.h"
888dde65 57#include "wx/msw/dcprint.h"
891daf8c 58#elif defined(__WXMAC__)
c933e267
SC
59#include "wx/osx/printdlg.h"
60#include "wx/osx/private/print.h"
61#include "wx/osx/dcprint.h"
7c71eb6a
SN
62#elif defined(__WXPM__)
63#include "wx/os2/dcprint.h"
64#include "wx/generic/prntdlgg.h"
891daf8c
RR
65#else
66#include "wx/generic/prntdlgg.h"
147bf263 67#include "wx/dcps.h"
891daf8c
RR
68#endif
69
2049ba38 70#ifdef __WXMSW__
d427503c
VZ
71 #ifndef __WIN32__
72 #include <print.h>
73 #endif
74#endif // __WXMSW__
c801d85f 75
e81e3883
RR
76//----------------------------------------------------------------------------
77// wxPrintFactory
78//----------------------------------------------------------------------------
79
80wxPrintFactory *wxPrintFactory::m_factory = NULL;
383f6abd 81
e81e3883 82void wxPrintFactory::SetPrintFactory( wxPrintFactory *factory )
383f6abd
WS
83{
84 if (wxPrintFactory::m_factory)
e81e3883 85 delete wxPrintFactory::m_factory;
383f6abd
WS
86
87 wxPrintFactory::m_factory = factory;
e81e3883 88}
c801d85f 89
e81e3883
RR
90wxPrintFactory *wxPrintFactory::GetFactory()
91{
92 if (!wxPrintFactory::m_factory)
383f6abd 93 wxPrintFactory::m_factory = new wxNativePrintFactory;
c801d85f 94
e81e3883
RR
95 return wxPrintFactory::m_factory;
96}
97
98//----------------------------------------------------------------------------
99// wxNativePrintFactory
100//----------------------------------------------------------------------------
101
102wxPrinterBase *wxNativePrintFactory::CreatePrinter( wxPrintDialogData *data )
383f6abd
WS
103{
104#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
e81e3883
RR
105 return new wxWindowsPrinter( data );
106#elif defined(__WXMAC__)
107 return new wxMacPrinter( data );
21708c73
SN
108#elif defined(__WXPM__)
109 return new wxOS2Printer( data );
e81e3883
RR
110#else
111 return new wxPostScriptPrinter( data );
112#endif
259c43f6 113}
e81e3883 114
383f6abd 115wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
e81e3883
RR
116 wxPrintout *printout, wxPrintDialogData *data )
117{
383f6abd 118#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
e81e3883
RR
119 return new wxWindowsPrintPreview( preview, printout, data );
120#elif defined(__WXMAC__)
121 return new wxMacPrintPreview( preview, printout, data );
21708c73
SN
122#elif defined(__WXPM__)
123 return new wxOS2PrintPreview( preview, printout, data );
e81e3883
RR
124#else
125 return new wxPostScriptPrintPreview( preview, printout, data );
126#endif
127}
128
383f6abd 129wxPrintPreviewBase *wxNativePrintFactory::CreatePrintPreview( wxPrintout *preview,
e81e3883
RR
130 wxPrintout *printout, wxPrintData *data )
131{
383f6abd 132#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
e81e3883
RR
133 return new wxWindowsPrintPreview( preview, printout, data );
134#elif defined(__WXMAC__)
135 return new wxMacPrintPreview( preview, printout, data );
21708c73
SN
136#elif defined(__WXPM__)
137 return new wxOS2PrintPreview( preview, printout, data );
e81e3883
RR
138#else
139 return new wxPostScriptPrintPreview( preview, printout, data );
140#endif
141}
142
2997ca30 143wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
c061373d
RR
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
2997ca30 155wxPrintDialogBase *wxNativePrintFactory::CreatePrintDialog( wxWindow *parent,
c061373d
RR
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
2997ca30 167wxPageSetupDialogBase *wxNativePrintFactory::CreatePageSetupDialog( wxWindow *parent,
891daf8c
RR
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
6038ec8e
RR
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
2997ca30 192
6038ec8e
RR
193}
194
2997ca30 195wxDialog *wxNativePrintFactory::CreatePrintSetupDialog( wxWindow *parent,
891daf8c 196 wxPrintData *data )
6038ec8e
RR
197{
198#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
ce403057
WS
199 wxUnusedVar(parent);
200 wxUnusedVar(data);
6038ec8e
RR
201 return NULL;
202#elif defined(__WXMAC__)
ce403057
WS
203 wxUnusedVar(parent);
204 wxUnusedVar(data);
6038ec8e
RR
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
888dde65 215wxDCImpl* wxNativePrintFactory::CreatePrinterDCImpl( wxPrinterDC *owner, const wxPrintData& data )
147bf263 216{
26eef304 217#if defined(__WXGTK__) || defined(__WXMOTIF__) || ( defined(__WXUNIVERSAL__) && !defined(__WXMAC__) )
888dde65 218 return new wxPostScriptDCImpl( owner, data );
147bf263 219#else
888dde65 220 return new wxPrinterDCImpl( owner, data );
147bf263
JS
221#endif
222}
223
6038ec8e
RR
224bool wxNativePrintFactory::HasOwnPrintToFile()
225{
226 // Only relevant for PostScript and here the
2997ca30 227 // setup dialog provides no "print to file"
6038ec8e
RR
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
2997ca30 242
6038ec8e
RR
243 // We should query "lpstat -d" here
244 return _("Generic PostScript");
245}
246
247bool wxNativePrintFactory::HasStatusLine()
248{
249 // Only relevant for PostScript for now
2997ca30 250 return true;
6038ec8e
RR
251}
252
253wxString wxNativePrintFactory::CreateStatusLine()
254{
255 // Only relevant for PostScript for now
2997ca30 256
6038ec8e
RR
257 // We should query "lpstat -r" or "lpstat -p" here
258 return _("Ready");
259}
260
8850cbd3
RR
261wxPrintNativeDataBase *wxNativePrintFactory::CreatePrintNativeData()
262{
263#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
264 return new wxWindowsPrintNativeData;
265#elif defined(__WXMAC__)
c347101b 266 return wxOSXCreatePrintData();
8850cbd3
RR
267#else
268 return new wxPostScriptPrintNativeData;
269#endif
270}
271
272//----------------------------------------------------------------------------
273// wxPrintNativeDataBase
274//----------------------------------------------------------------------------
275
276IMPLEMENT_ABSTRACT_CLASS(wxPrintNativeDataBase, wxObject)
277
278wxPrintNativeDataBase::wxPrintNativeDataBase()
2997ca30
WS
279{
280 m_ref = 1;
8850cbd3
RR
281}
282
0ab2de15
RR
283//----------------------------------------------------------------------------
284// wxPrintFactoryModule
285//----------------------------------------------------------------------------
286
287class wxPrintFactoryModule: public wxModule
288{
289public:
290 wxPrintFactoryModule() {}
291 bool OnInit() { return true; }
292 void OnExit() { wxPrintFactory::SetPrintFactory( NULL ); }
2997ca30 293
0ab2de15
RR
294private:
295 DECLARE_DYNAMIC_CLASS(wxPrintFactoryModule)
296};
297
298IMPLEMENT_DYNAMIC_CLASS(wxPrintFactoryModule, wxModule)
299
e81e3883
RR
300//----------------------------------------------------------------------------
301// wxPrinterBase
302//----------------------------------------------------------------------------
303
304IMPLEMENT_CLASS(wxPrinterBase, wxObject)
7bcb11d3
JS
305
306wxPrinterBase::wxPrinterBase(wxPrintDialogData *data)
c801d85f 307{
d3b9f782
VZ
308 m_currentPrintout = NULL;
309 sm_abortWindow = NULL;
7e548f6b 310 sm_abortIt = false;
7bcb11d3
JS
311 if (data)
312 m_printDialogData = (*data);
f6bcfd97 313 sm_lastError = wxPRINTER_NO_ERROR;
c801d85f
KB
314}
315
d3b9f782 316wxWindow *wxPrinterBase::sm_abortWindow = NULL;
7e548f6b 317bool wxPrinterBase::sm_abortIt = false;
f6bcfd97 318wxPrinterError wxPrinterBase::sm_lastError = wxPRINTER_NO_ERROR;
c801d85f 319
34da0970 320wxPrinterBase::~wxPrinterBase()
c801d85f
KB
321{
322}
323
446659ca 324wxPrintAbortDialog *wxPrinterBase::CreateAbortWindow(wxWindow *parent, wxPrintout * printout)
c801d85f 325{
1a19b321 326 return new wxPrintAbortDialog(parent, printout->GetTitle());
c801d85f
KB
327}
328
161f4f73 329void wxPrinterBase::ReportError(wxWindow *parent, wxPrintout *WXUNUSED(printout), const wxString& message)
c801d85f 330{
7bcb11d3 331 wxMessageBox(message, _("Printing Error"), wxOK, parent);
c801d85f
KB
332}
333
c061373d
RR
334wxPrintDialogData& wxPrinterBase::GetPrintDialogData() const
335{
336 return (wxPrintDialogData&) m_printDialogData;
337}
338
e81e3883
RR
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
446659ca 355wxPrintAbortDialog *wxPrinter::CreateAbortWindow(wxWindow *parent, wxPrintout *printout)
e81e3883
RR
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{
32eec436
VZ
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
e81e3883
RR
385 return m_pimpl->Print( parent, printout, prompt );
386}
387
388wxDC* wxPrinter::PrintDialog(wxWindow *parent)
389{
390 return m_pimpl->PrintDialog( parent );
391}
392
c061373d
RR
393wxPrintDialogData& wxPrinter::GetPrintDialogData() const
394{
395 return m_pimpl->GetPrintDialogData();
396}
397
398// ---------------------------------------------------------------------------
891daf8c 399// wxPrintDialogBase: the dialog for printing.
c061373d
RR
400// ---------------------------------------------------------------------------
401
891daf8c 402IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase, wxDialog)
c061373d 403
6ce8c562 404wxPrintDialogBase::wxPrintDialogBase(wxWindow *parent,
2997ca30 405 wxWindowID id,
6ce8c562
VZ
406 const wxString &title,
407 const wxPoint &pos,
408 const wxSize &size,
409 long style)
891daf8c
RR
410 : wxDialog( parent, id, title.empty() ? wxString(_("Print")) : title,
411 pos, size, style )
c061373d
RR
412{
413}
414
415// ---------------------------------------------------------------------------
891daf8c 416// wxPrintDialog: the dialog for printing
c061373d
RR
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}
891daf8c 450
c061373d
RR
451wxDC *wxPrintDialog::GetPrintDC()
452{
453 return m_pimpl->GetPrintDC();
454}
455
891daf8c
RR
456// ---------------------------------------------------------------------------
457// wxPageSetupDialogBase: the page setup dialog
458// ---------------------------------------------------------------------------
459
460IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase, wxDialog)
461
462wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow *parent,
2997ca30 463 wxWindowID id,
891daf8c
RR
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
e81e3883
RR
505//----------------------------------------------------------------------------
506// wxPrintAbortDialog
507//----------------------------------------------------------------------------
508
509BEGIN_EVENT_TABLE(wxPrintAbortDialog, wxDialog)
510 EVT_BUTTON(wxID_CANCEL, wxPrintAbortDialog::OnCancel)
511END_EVENT_TABLE()
512
1a19b321
VS
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{
e7aa9bb7
VS
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);
1a19b321
VS
549}
550
e81e3883
RR
551void wxPrintAbortDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
552{
ef344c36 553 wxCHECK_RET( wxPrinterBase::sm_abortWindow != NULL, "OnCancel called twice" );
84cabd36 554
e81e3883 555 wxPrinterBase::sm_abortIt = true;
861eef72 556 wxPrinterBase::sm_abortWindow->Destroy();
d3b9f782 557 wxPrinterBase::sm_abortWindow = NULL;
e81e3883
RR
558}
559
560//----------------------------------------------------------------------------
561// wxPrintout
562//----------------------------------------------------------------------------
563
564IMPLEMENT_ABSTRACT_CLASS(wxPrintout, wxObject)
7bcb11d3 565
34da0970 566wxPrintout::wxPrintout(const wxString& title)
c801d85f 567{
7bcb11d3 568 m_printoutTitle = title ;
d3b9f782 569 m_printoutDC = NULL;
7bcb11d3
JS
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;
1bd122dd 578 m_preview = NULL;
c801d85f
KB
579}
580
34da0970 581wxPrintout::~wxPrintout()
c801d85f 582{
c801d85f
KB
583}
584
585bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage), int WXUNUSED(endPage))
586{
fc799548 587 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle);
c801d85f
KB
588}
589
34da0970 590void wxPrintout::OnEndDocument()
c801d85f 591{
7bcb11d3 592 GetDC()->EndDoc();
c801d85f
KB
593}
594
34da0970 595void wxPrintout::OnBeginPrinting()
c801d85f
KB
596{
597}
598
34da0970 599void wxPrintout::OnEndPrinting()
c801d85f
KB
600{
601}
602
603bool wxPrintout::HasPage(int page)
604{
7bcb11d3 605 return (page == 1);
c801d85f
KB
606}
607
608void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toPage)
609{
7bcb11d3
JS
610 *minPage = 1;
611 *maxPage = 32000;
612 *fromPage = 1;
613 *toPage = 1;
c801d85f
KB
614}
615
f415cab9
JS
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);
03647350 631 m_printoutDC->SetUserScale(actualScale, actualScale);
f415cab9
JS
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);
03647350 648 m_printoutDC->SetUserScale(actualScale, actualScale);
f415cab9
JS
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;
5a70d3f5
VZ
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)));
f415cab9
JS
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);
03647350 676 m_printoutDC->SetUserScale(actualScale, actualScale);
f415cab9
JS
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;
03647350
VZ
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);
f415cab9
JS
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;
03647350
VZ
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;
f415cab9
JS
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
03647350
VZ
750 return wxRect(m_printoutDC->DeviceToLogicalX(paperRect.x),
751 m_printoutDC->DeviceToLogicalY(paperRect.y),
752 m_printoutDC->DeviceToLogicalXRel(paperRect.width),
f415cab9
JS
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;
03647350
VZ
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)),
5a70d3f5 761 m_printoutDC->DeviceToLogicalYRel(wxRound(paperRect.height * scaleY)));
f415cab9
JS
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);
03647350
VZ
770 return wxRect(m_printoutDC->DeviceToLogicalX(0),
771 m_printoutDC->DeviceToLogicalY(0),
772 m_printoutDC->DeviceToLogicalXRel(w),
f415cab9
JS
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.
03647350 781
02255e07
RR
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
f415cab9
JS
784 wxCoord pw, ph;
785 GetPageSizePixels(&pw, &ph);
f415cab9
JS
786 wxCoord mw, mh;
787 GetPageSizeMM(&mw, &mh);
788 float mmToDeviceX = float(pw) / mw;
789 float mmToDeviceY = float(ph) / mh;
02255e07 790
03647350 791 // paper size in device units
02255e07 792 wxRect paperRect = GetPaperRectPixels();
03647350 793
02255e07
RR
794 // margins in mm
795 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
796 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
03647350 797
02255e07
RR
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)),
5a70d3f5 803 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
03647350 804
f415cab9
JS
805 wxCoord w, h;
806 m_printoutDC->GetSize(&w, &h);
03647350 807 if (w == pw && h == ph)
02255e07 808 {
f415cab9 809 // this DC matches the printed page, so no scaling
02255e07 810 return wxRect(
03647350
VZ
811 m_printoutDC->DeviceToLogicalX(pageMarginsRect.x),
812 m_printoutDC->DeviceToLogicalY(pageMarginsRect.y),
813 m_printoutDC->DeviceToLogicalXRel(pageMarginsRect.width),
f415cab9
JS
814 m_printoutDC->DeviceToLogicalYRel(pageMarginsRect.height));
815 }
03647350 816
f415cab9
JS
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;
03647350
VZ
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)),
5a70d3f5 823 m_printoutDC->DeviceToLogicalYRel(wxRound(pageMarginsRect.height * scaleY)));
f415cab9
JS
824}
825
826void wxPrintout::SetLogicalOrigin(wxCoord x, wxCoord y)
827{
828 // Set the device origin by specifying a point in logical coordinates.
02255e07 829 m_printoutDC->SetDeviceOrigin(
03647350 830 m_printoutDC->LogicalToDeviceX(x),
02255e07 831 m_printoutDC->LogicalToDeviceY(y) );
f415cab9 832}
03647350 833
f415cab9
JS
834void wxPrintout::OffsetLogicalOrigin(wxCoord xoff, wxCoord yoff)
835{
836 // Offset the device origin by a specified distance in device coordinates.
02255e07
RR
837 wxPoint dev_org = m_printoutDC->GetDeviceOrigin();
838 m_printoutDC->SetDeviceOrigin(
03647350 839 dev_org.x + m_printoutDC->LogicalToDeviceXRel(xoff),
02255e07 840 dev_org.y + m_printoutDC->LogicalToDeviceYRel(yoff) );
f415cab9 841}
03647350 842
f415cab9 843
e81e3883
RR
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)
b88bf073 853 EVT_IDLE(wxPreviewCanvas::OnIdle)
e81e3883 854 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged)
fb6efdf2
VZ
855#if wxUSE_MOUSEWHEEL
856 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel)
857#endif
e81e3883 858END_EVENT_TABLE()
7bcb11d3 859
e9cafd42
VZ
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...
c801d85f 864wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase *preview, wxWindow *parent,
7bcb11d3 865 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
7e548f6b 866wxScrolledWindow(parent, wxID_ANY, pos, size, style | wxFULL_REPAINT_ON_RESIZE, name)
c801d85f 867{
7bcb11d3 868 m_printPreview = preview;
46b24ef9
JS
869#ifdef __WXMAC__
870 // The app workspace colour is always white, but we should have
871 // a contrast with the page.
ca5020c2 872 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
92b799e0
JS
873#elif defined(__WXGTK__)
874 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
46b24ef9
JS
875#else
876 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
e71fd398 877#endif
46b24ef9 878 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
8826f46f 879
d2b354f9 880 SetScrollbars(10, 10, 100, 100);
c801d85f
KB
881}
882
34da0970 883wxPreviewCanvas::~wxPreviewCanvas()
c801d85f
KB
884{
885}
886
887void wxPreviewCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
888{
7bcb11d3
JS
889 wxPaintDC dc(this);
890 PrepareDC( dc );
8826f46f 891
a56fcaaf 892/*
809934d2
RR
893#ifdef __WXGTK__
894 if (!GetUpdateRegion().IsEmpty())
895 dc.SetClippingRegion( GetUpdateRegion() );
896#endif
a56fcaaf 897*/
809934d2 898
7bcb11d3
JS
899 if (m_printPreview)
900 {
901 m_printPreview->PaintPage(this, dc);
902 }
c801d85f
KB
903}
904
b88bf073
VS
905void wxPreviewCanvas::OnIdle(wxIdleEvent& event)
906{
88b98787
VS
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
b88bf073
VS
915 if ( m_printPreview )
916 {
917 if ( m_printPreview->UpdatePageRendering() )
918 Refresh();
919 }
88b98787
VS
920
921 s_inIdle = false;
b88bf073
VS
922}
923
c801d85f
KB
924// Responds to colour changes, and passes event on to children.
925void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent& event)
926{
46b24ef9
JS
927#ifdef __WXMAC__
928 // The app workspace colour is always white, but we should have
929 // a contrast with the page.
ca5020c2 930 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
92b799e0
JS
931#elif defined(__WXGTK__)
932 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
46b24ef9
JS
933#else
934 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
e71fd398 935#endif
46b24ef9 936 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
7bcb11d3 937 Refresh();
8826f46f 938
7bcb11d3
JS
939 // Propagate the event to the non-top-level children
940 wxWindow::OnSysColourChanged(event);
c801d85f
KB
941}
942
d2b354f9
JS
943void wxPreviewCanvas::OnChar(wxKeyEvent &event)
944{
b38b0d22 945 wxPreviewControlBar* controlBar = ((wxPreviewFrame*) GetParent())->GetControlBar();
043c6705 946 switch (event.GetKeyCode())
d2b354f9 947 {
043c6705
VZ
948 case WXK_RETURN:
949 controlBar->OnPrint();
950 return;
82579461
VZ
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;
b38b0d22
JS
961 }
962
d2b354f9
JS
963 if (!event.ControlDown())
964 {
965 event.Skip();
966 return;
967 }
e71fd398 968
b38b0d22
JS
969 switch(event.GetKeyCode())
970 {
faa94f3e 971 case WXK_PAGEDOWN:
b38b0d22 972 controlBar->OnNext(); break;
faa94f3e 973 case WXK_PAGEUP:
b38b0d22
JS
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 }
d2b354f9
JS
982}
983
fb6efdf2
VZ
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
d7cfeeb4
VZ
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
82579461
VZ
1076// ----------------------------------------------------------------------------
1077// wxPrintPageTextCtrl
1078// ----------------------------------------------------------------------------
1079
d7cfeeb4
VZ
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.
82579461
VZ
1085class wxPrintPageTextCtrl : public wxTextCtrl
1086{
1087public:
d7cfeeb4 1088 wxPrintPageTextCtrl(wxPreviewControlBar *preview)
82579461
VZ
1089 : wxTextCtrl(preview,
1090 wxID_PREVIEW_GOTO,
d7cfeeb4 1091 wxString(),
82579461 1092 wxDefaultPosition,
d7cfeeb4
VZ
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 ),
82579461
VZ
1102 wxTE_PROCESS_ENTER
1103#if wxUSE_VALIDATORS
1104 , wxTextValidator(wxFILTER_DIGITS)
1105#endif // wxUSE_VALIDATORS
1106 ),
d7cfeeb4 1107 m_preview(preview)
82579461 1108 {
d7cfeeb4
VZ
1109 m_minPage =
1110 m_maxPage =
1111 m_page = 1;
82579461
VZ
1112
1113 Connect(wxEVT_KILL_FOCUS,
1114 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus));
1115 Connect(wxEVT_COMMAND_TEXT_ENTER,
1116 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter));
1117 }
1118
d7cfeeb4
VZ
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
82579461
VZ
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
d7cfeeb4
VZ
1200 int m_minPage,
1201 m_maxPage;
82579461
VZ
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
e81e3883
RR
1210//----------------------------------------------------------------------------
1211// wxPreviewControlBar
1212//----------------------------------------------------------------------------
1213
1214IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
c801d85f
KB
1215
1216BEGIN_EVENT_TABLE(wxPreviewControlBar, wxPanel)
8826f46f 1217 EVT_BUTTON(wxID_PREVIEW_CLOSE, wxPreviewControlBar::OnWindowClose)
90b6b974 1218 EVT_BUTTON(wxID_PREVIEW_PRINT, wxPreviewControlBar::OnPrintButton)
0f90ec93
KB
1219 EVT_BUTTON(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnPreviousButton)
1220 EVT_BUTTON(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnNextButton)
bf89b538
JS
1221 EVT_BUTTON(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnFirstButton)
1222 EVT_BUTTON(wxID_PREVIEW_LAST, wxPreviewControlBar::OnLastButton)
82579461
VZ
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)
8826f46f 1234 EVT_PAINT(wxPreviewControlBar::OnPaint)
82579461 1235
c801d85f 1236END_EVENT_TABLE()
7bcb11d3 1237
c801d85f 1238wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
7bcb11d3
JS
1239 wxWindow *parent, const wxPoint& pos, const wxSize& size,
1240 long style, const wxString& name):
7e548f6b 1241wxPanel(parent, wxID_ANY, pos, size, style, name)
c801d85f 1242{
7bcb11d3 1243 m_printPreview = preview;
d3b9f782 1244 m_closeButton = NULL;
d3b9f782 1245 m_zoomControl = NULL;
82579461 1246 m_currentPageText = NULL;
d7cfeeb4 1247 m_maxPageText = NULL;
7bcb11d3 1248 m_buttonFlags = buttons;
c801d85f
KB
1249}
1250
34da0970 1251wxPreviewControlBar::~wxPreviewControlBar()
c801d85f
KB
1252{
1253}
1254
1255void wxPreviewControlBar::OnPaint(wxPaintEvent& WXUNUSED(event))
1256{
7bcb11d3 1257 wxPaintDC dc(this);
8826f46f 1258
7bcb11d3
JS
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 );
c801d85f
KB
1264}
1265
c330a2cf 1266void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
c801d85f 1267{
7bcb11d3 1268 wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
7e548f6b 1269 frame->Close(true);
c801d85f
KB
1270}
1271
b38b0d22 1272void wxPreviewControlBar::OnPrint(void)
c801d85f 1273{
7bcb11d3 1274 wxPrintPreviewBase *preview = GetPrintPreview();
7e548f6b 1275 preview->Print(true);
c801d85f
KB
1276}
1277
82579461
VZ
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
c801d85f 1303{
7bcb11d3 1304 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1305 if ( !preview )
1306 return false;
1307
1308 const int currentPage = preview->GetCurrentPage();
1309 return currentPage < preview->GetMaxPage() &&
1310 preview->GetPrintout()->HasPage(currentPage + 1);
c801d85f
KB
1311}
1312
82579461 1313bool wxPreviewControlBar::IsPreviousEnabled() const
c801d85f 1314{
7bcb11d3 1315 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1316 if ( !preview )
1317 return false;
1318
1319 const int currentPage = preview->GetCurrentPage();
1320 return currentPage > preview->GetMinPage() &&
1321 preview->GetPrintout()->HasPage(currentPage - 1);
c801d85f
KB
1322}
1323
82579461 1324bool wxPreviewControlBar::IsFirstEnabled() const
bf89b538
JS
1325{
1326 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1327 if (!preview)
1328 return false;
1329
1330 return preview->GetPrintout()->HasPage(preview->GetMinPage());
bf89b538
JS
1331}
1332
82579461 1333bool wxPreviewControlBar::IsLastEnabled() const
bf89b538
JS
1334{
1335 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1336 if (!preview)
1337 return false;
1338
1339 return preview->GetPrintout()->HasPage(preview->GetMaxPage());
bf89b538
JS
1340}
1341
82579461
VZ
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()
bf89b538
JS
1354{
1355 wxPrintPreviewBase *preview = GetPrintPreview();
1356 if (preview)
1357 {
bf89b538
JS
1358 if (preview->GetMinPage() > 0)
1359 {
82579461
VZ
1360 long currentPage = m_currentPageText->GetPageNumber();
1361 if ( currentPage )
1362 {
bf89b538
JS
1363 if (preview->GetPrintout()->HasPage(currentPage))
1364 {
1365 preview->SetCurrentPage(currentPage);
1366 }
82579461 1367 }
bf89b538
JS
1368 }
1369 }
1370}
1371
82579461 1372void wxPreviewControlBar::DoZoom()
c801d85f 1373{
7bcb11d3
JS
1374 int zoom = GetZoomControl();
1375 if (GetPrintPreview())
1376 GetPrintPreview()->SetZoom(zoom);
c801d85f
KB
1377}
1378
82579461
VZ
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
34da0970 1505void wxPreviewControlBar::CreateButtons()
c801d85f 1506{
82579461 1507 SizerWithButtons sizer(this);
e71fd398 1508
82579461 1509 // Print button group (a single button).
7bcb11d3
JS
1510 if (m_buttonFlags & wxPREVIEW_PRINT)
1511 {
82579461
VZ
1512 sizer.AddButton(wxID_PREVIEW_PRINT, wxART_PRINT, _("Print"));
1513 sizer.EndOfGroup();
7bcb11d3 1514 }
e71fd398 1515
82579461 1516 // Page selection buttons group.
bf89b538
JS
1517 if (m_buttonFlags & wxPREVIEW_FIRST)
1518 {
82579461 1519 sizer.AddButton(wxID_PREVIEW_FIRST, wxART_GOTO_FIRST, _("First page"));
bf89b538 1520 }
e71fd398 1521
7bcb11d3
JS
1522 if (m_buttonFlags & wxPREVIEW_PREVIOUS)
1523 {
82579461 1524 sizer.AddButton(wxID_PREVIEW_PREVIOUS, wxART_GO_BACK, _("Previous page"));
7bcb11d3 1525 }
e71fd398 1526
82579461 1527 if (m_buttonFlags & wxPREVIEW_GOTO)
7bcb11d3 1528 {
d7cfeeb4 1529 m_currentPageText = new wxPrintPageTextCtrl(this);
82579461
VZ
1530 sizer.Add(m_currentPageText);
1531
d7cfeeb4
VZ
1532 m_maxPageText = new wxPrintPageMaxCtrl(this);
1533 sizer.Add(m_maxPageText);
bf89b538 1534 }
e71fd398 1535
82579461 1536 if (m_buttonFlags & wxPREVIEW_NEXT)
bf89b538 1537 {
82579461 1538 sizer.AddButton(wxID_PREVIEW_NEXT, wxART_GO_FORWARD, _("Next page"));
bf89b538 1539 }
e71fd398 1540
82579461 1541 if (m_buttonFlags & wxPREVIEW_LAST)
bf89b538 1542 {
82579461 1543 sizer.AddButton(wxID_PREVIEW_LAST, wxART_GOTO_LAST, _("Last page"));
7bcb11d3 1544 }
e71fd398 1545
82579461
VZ
1546 sizer.EndOfGroup();
1547
1548 // Zoom controls group.
7bcb11d3
JS
1549 if (m_buttonFlags & wxPREVIEW_ZOOM)
1550 {
82579461
VZ
1551 sizer.AddButton(wxID_PREVIEW_ZOOM_OUT, wxART_MINUS, _("Zoom Out"));
1552
e71fd398 1553 wxString choices[] =
c25ccf85 1554 {
2b5f62a0 1555 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
9dff8515
JS
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%")
c25ccf85 1558 };
c25ccf85 1559 int n = WXSIZEOF(choices);
e71fd398 1560
7e548f6b 1561 m_zoomControl = new wxChoice( this, wxID_PREVIEW_ZOOM, wxDefaultPosition, wxSize(70,wxDefaultCoord), n, choices, 0 );
82579461 1562 sizer.Add(m_zoomControl);
7bcb11d3 1563 SetZoomControl(m_printPreview->GetZoom());
82579461
VZ
1564
1565 sizer.AddButton(wxID_PREVIEW_ZOOM_IN, wxART_PLUS, _("Zoom In"));
1566
1567 sizer.EndOfGroup();
7bcb11d3 1568 }
8826f46f 1569
82579461
VZ
1570 // Close button group (single button again).
1571 m_closeButton = new wxButton(this, wxID_PREVIEW_CLOSE, _("&Close"));
1572 sizer.AddAtEnd(m_closeButton);
c801d85f
KB
1573}
1574
d7cfeeb4
VZ
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
c801d85f
KB
1584void wxPreviewControlBar::SetZoomControl(int zoom)
1585{
7bcb11d3 1586 if (m_zoomControl)
963907fa
RR
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 }
7e548f6b 1599
963907fa
RR
1600 m_zoomControl->SetSelection(count-1);
1601 }
c801d85f
KB
1602}
1603
34da0970 1604int wxPreviewControlBar::GetZoomControl()
c801d85f 1605{
963907fa 1606 if (m_zoomControl && (m_zoomControl->GetStringSelection() != wxEmptyString))
7bcb11d3 1607 {
963907fa
RR
1608 long val;
1609 if (m_zoomControl->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val))
1610 return int(val);
7bcb11d3 1611 }
7e548f6b 1612
963907fa 1613 return 0;
c801d85f
KB
1614}
1615
1616
1617/*
7bcb11d3
JS
1618* Preview frame
1619*/
c801d85f 1620
e81e3883
RR
1621IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
1622
e3065973 1623BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
043c6705 1624 EVT_CHAR_HOOK(wxPreviewFrame::OnChar)
0f90ec93 1625 EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
e3065973
JS
1626END_EVENT_TABLE()
1627
043c6705
VZ
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
a5ae8241 1640wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
7bcb11d3 1641 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
7e548f6b 1642wxFrame(parent, wxID_ANY, title, pos, size, style, name)
c801d85f 1643{
7bcb11d3
JS
1644 m_printPreview = preview;
1645 m_controlBar = NULL;
1646 m_previewCanvas = NULL;
7c995553 1647 m_windowDisabler = NULL;
6aacfc73 1648 m_modalityKind = wxPreviewFrame_NonModal;
46b24ef9 1649
a5ae8241 1650 // Give the application icon
46b24ef9
JS
1651#ifdef __WXMSW__
1652 wxFrame* topFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
1653 if (topFrame)
7ccf316e 1654 SetIcons(topFrame->GetIcons());
e71fd398 1655#endif
c801d85f
KB
1656}
1657
34da0970 1658wxPreviewFrame::~wxPreviewFrame()
c801d85f 1659{
7bcb11d3
JS
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 }
b88bf073
VS
1668
1669 m_previewCanvas->SetPreview(NULL);
6aacfc73
VZ
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 }
8826f46f 1692
7bcb11d3 1693 Destroy();
c801d85f
KB
1694}
1695
1e5ad6e1 1696void wxPreviewFrame::InitializeWithModality(wxPreviewFrameModalityKind kind)
c801d85f 1697{
3080bf59 1698#if wxUSE_STATUSBAR
7bcb11d3 1699 CreateStatusBar();
3080bf59 1700#endif
7bcb11d3
JS
1701 CreateCanvas();
1702 CreateControlBar();
8826f46f 1703
7bcb11d3
JS
1704 m_printPreview->SetCanvas(m_previewCanvas);
1705 m_printPreview->SetFrame(this);
8826f46f 1706
9dff8515 1707 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
8826f46f 1708
9dff8515
JS
1709 item0->Add( m_controlBar, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1710 item0->Add( m_previewCanvas, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
8826f46f 1711
7e548f6b 1712 SetAutoLayout( true );
9dff8515 1713 SetSizer( item0 );
8826f46f 1714
6aacfc73
VZ
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
46aa0c9e
VS
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.
6c0613fd 1739 SetWindowStyle((GetWindowStyle() & ~wxMINIMIZE_BOX) | wxFRAME_NO_TASKBAR);
46aa0c9e 1740 }
8826f46f 1741
7bcb11d3 1742 Layout();
e71fd398 1743
d2b354f9
JS
1744 m_printPreview->AdjustScrollbars(m_previewCanvas);
1745 m_previewCanvas->SetFocus();
1746 m_controlBar->SetFocus();
c801d85f
KB
1747}
1748
34da0970 1749void wxPreviewFrame::CreateCanvas()
c801d85f 1750{
7bcb11d3 1751 m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
c801d85f
KB
1752}
1753
34da0970 1754void wxPreviewFrame::CreateControlBar()
c801d85f 1755{
7bcb11d3
JS
1756 long buttons = wxPREVIEW_DEFAULT;
1757 if (m_printPreview->GetPrintoutForPrinting())
1758 buttons |= wxPREVIEW_PRINT;
8826f46f 1759
e562dfb1 1760 m_controlBar = new wxPreviewControlBar(m_printPreview, buttons, this);
7bcb11d3 1761 m_controlBar->CreateButtons();
c801d85f 1762}
7bcb11d3 1763
c801d85f 1764/*
7bcb11d3
JS
1765* Print preview
1766*/
c801d85f 1767
891daf8c
RR
1768IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
1769
8826f46f
VZ
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)
c801d85f 1792{
7e548f6b 1793 m_isOk = true;
7bcb11d3
JS
1794 m_previewPrintout = printout;
1795 if (m_previewPrintout)
1bd122dd 1796 m_previewPrintout->SetPreview(static_cast<wxPrintPreview *>(this));
8826f46f 1797
7bcb11d3 1798 m_printPrintout = printoutForPrinting;
8826f46f 1799
7bcb11d3
JS
1800 m_previewCanvas = NULL;
1801 m_previewFrame = NULL;
1802 m_previewBitmap = NULL;
88b98787 1803 m_previewFailed = false;
7bcb11d3 1804 m_currentPage = 1;
c25ccf85 1805 m_currentZoom = 70;
41e1c9d8
VZ
1806 m_topMargin =
1807 m_leftMargin = 2*wxSizerFlags::GetDefaultBorder();
7bcb11d3
JS
1808 m_pageWidth = 0;
1809 m_pageHeight = 0;
7e548f6b 1810 m_printingPrepared = false;
d2b354f9
JS
1811 m_minPage = 1;
1812 m_maxPage = 1;
c801d85f
KB
1813}
1814
34da0970 1815wxPrintPreviewBase::~wxPrintPreviewBase()
c801d85f 1816{
7bcb11d3
JS
1817 if (m_previewPrintout)
1818 delete m_previewPrintout;
1819 if (m_previewBitmap)
1820 delete m_previewBitmap;
1821 if (m_printPrintout)
1822 delete m_printPrintout;
c801d85f
KB
1823}
1824
1825bool wxPrintPreviewBase::SetCurrentPage(int pageNum)
1826{
7bcb11d3 1827 if (m_currentPage == pageNum)
7e548f6b 1828 return true;
8826f46f 1829
7bcb11d3 1830 m_currentPage = pageNum;
88b98787
VS
1831
1832 InvalidatePreviewBitmap();
e71fd398 1833
7bcb11d3
JS
1834 if (m_previewCanvas)
1835 {
d2b354f9 1836 AdjustScrollbars(m_previewCanvas);
e71fd398 1837
7bcb11d3 1838 m_previewCanvas->Refresh();
d2b354f9 1839 m_previewCanvas->SetFocus();
7bcb11d3 1840 }
7e548f6b 1841 return true;
c801d85f
KB
1842}
1843
383f6abd 1844int wxPrintPreviewBase::GetCurrentPage() const
259c43f6 1845 { return m_currentPage; }
383f6abd 1846void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
259c43f6 1847 { m_previewPrintout = printout; }
383f6abd 1848wxPrintout *wxPrintPreviewBase::GetPrintout() const
259c43f6 1849 { return m_previewPrintout; }
383f6abd 1850wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
259c43f6 1851 { return m_printPrintout; }
383f6abd 1852void wxPrintPreviewBase::SetFrame(wxFrame *frame)
259c43f6 1853 { m_previewFrame = frame; }
383f6abd 1854void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
259c43f6 1855 { m_previewCanvas = canvas; }
383f6abd 1856wxFrame *wxPrintPreviewBase::GetFrame() const
e81e3883 1857 { return m_previewFrame; }
383f6abd 1858wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
e81e3883
RR
1859 { return m_previewCanvas; }
1860
f415cab9
JS
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
88b98787
VS
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
b88bf073
VS
1902bool wxPrintPreviewBase::UpdatePageRendering()
1903{
1904 if ( m_previewBitmap )
1905 return false;
1906
88b98787
VS
1907 if ( m_previewFailed )
1908 return false;
1909
b88bf073 1910 if ( !RenderPage(m_currentPage) )
88b98787
VS
1911 {
1912 m_previewFailed = true; // don't waste time failing again
b88bf073 1913 return false;
88b98787 1914 }
b88bf073
VS
1915
1916 return true;
1917}
1918
d2b354f9 1919bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
c801d85f 1920{
7bcb11d3 1921 DrawBlankPage(canvas, dc);
8826f46f 1922
7bcb11d3 1923 if (!m_previewBitmap)
7e548f6b 1924 return false;
7bcb11d3 1925 if (!canvas)
7e548f6b 1926 return false;
8826f46f 1927
f415cab9
JS
1928 wxRect pageRect, paperRect;
1929 CalcRects(canvas, pageRect, paperRect);
7bcb11d3
JS
1930 wxMemoryDC temp_dc;
1931 temp_dc.SelectObject(*m_previewBitmap);
8826f46f 1932
03647350 1933 dc.Blit(pageRect.x, pageRect.y,
f415cab9 1934 m_previewBitmap->GetWidth(), m_previewBitmap->GetHeight(), &temp_dc, 0, 0);
8826f46f 1935
7bcb11d3 1936 temp_dc.SelectObject(wxNullBitmap);
7e548f6b 1937 return true;
c801d85f
KB
1938}
1939
d2b354f9
JS
1940// Adjusts the scrollbars for the current scale
1941void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas *canvas)
1942{
1943 if (!canvas)
1944 return ;
1945
f415cab9
JS
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;
d2b354f9
JS
1952 wxSize virtualSize = canvas->GetVirtualSize();
1953 if (virtualSize.GetWidth() != totalWidth || virtualSize.GetHeight() != totalHeight)
7e548f6b 1954 canvas->SetScrollbars(10, 10, scrollUnitsX, scrollUnitsY, 0, 0, true);
d2b354f9
JS
1955}
1956
25a3fca2
VS
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
d7cfeeb4 1963 // information and a wxDC.
25a3fca2
VS
1964 if (!m_printingPrepared)
1965 {
d7cfeeb4
VZ
1966 m_printingPrepared = true;
1967
25a3fca2
VS
1968 m_previewPrintout->OnPreparePrinting();
1969 int selFrom, selTo;
1970 m_previewPrintout->GetPageInfo(&m_minPage, &m_maxPage, &selFrom, &selTo);
d7cfeeb4
VZ
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 }
25a3fca2
VS
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
c801d85f
KB
2008bool wxPrintPreviewBase::RenderPage(int pageNum)
2009{
f6bcfd97
BP
2010 wxBusyCursor busy;
2011
7bcb11d3 2012 if (!m_previewCanvas)
c801d85f 2013 {
9a83f860 2014 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
7e548f6b 2015 return false;
c801d85f 2016 }
8826f46f 2017
f415cab9
JS
2018 wxRect pageRect, paperRect;
2019 CalcRects(m_previewCanvas, pageRect, paperRect);
8826f46f 2020
7bcb11d3
JS
2021 if (!m_previewBitmap)
2022 {
f415cab9
JS
2023 m_previewBitmap = new wxBitmap(pageRect.width, pageRect.height);
2024
a1b806b9 2025 if (!m_previewBitmap || !m_previewBitmap->IsOk())
7bcb11d3 2026 {
88b98787 2027 InvalidatePreviewBitmap();
7bcb11d3 2028 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
7e548f6b 2029 return false;
7bcb11d3
JS
2030 }
2031 }
8826f46f 2032
25a3fca2 2033 if ( !RenderPageIntoBitmap(*m_previewBitmap, pageNum) )
7bcb11d3 2034 {
88b98787 2035 InvalidatePreviewBitmap();
25a3fca2 2036 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
7e548f6b 2037 return false;
7bcb11d3 2038 }
8826f46f 2039
3080bf59
VZ
2040#if wxUSE_STATUSBAR
2041 wxString status;
7bcb11d3 2042 if (m_maxPage != 0)
7e548f6b 2043 status = wxString::Format(_("Page %d of %d"), pageNum, m_maxPage);
7bcb11d3 2044 else
7e548f6b 2045 status = wxString::Format(_("Page %d"), pageNum);
8826f46f 2046
7bcb11d3 2047 if (m_previewFrame)
3080bf59
VZ
2048 m_previewFrame->SetStatusText(status);
2049#endif
8826f46f 2050
7e548f6b 2051 return true;
c801d85f
KB
2052}
2053
d2b354f9 2054bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
c801d85f 2055{
f415cab9 2056 wxRect pageRect, paperRect;
8826f46f 2057
f415cab9 2058 CalcRects(canvas, pageRect, paperRect);
8826f46f 2059
f415cab9
JS
2060 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
2061 wxCoord shadowOffset = 4;
8826f46f 2062
7bcb11d3
JS
2063 dc.SetPen(*wxBLACK_PEN);
2064 dc.SetBrush(*wxBLACK_BRUSH);
f415cab9
JS
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);
8826f46f 2070
f415cab9 2071 // Draw blank page allowing for 1-pixel border AROUND the actual paper
7bcb11d3
JS
2072 dc.SetPen(*wxBLACK_PEN);
2073 dc.SetBrush(*wxWHITE_BRUSH);
03647350 2074 dc.DrawRectangle(paperRect.x - 2, paperRect.y - 1,
f415cab9 2075 paperRect.width + 3, paperRect.height + 2);
8826f46f 2076
7e548f6b 2077 return true;
2a47d3c1
JS
2078}
2079
7bcb11d3 2080void wxPrintPreviewBase::SetZoom(int percent)
2a47d3c1 2081{
7bcb11d3
JS
2082 if (m_currentZoom == percent)
2083 return;
8826f46f 2084
7bcb11d3 2085 m_currentZoom = percent;
88b98787
VS
2086
2087 InvalidatePreviewBitmap();
aff37a19 2088
7bcb11d3
JS
2089 if (m_previewCanvas)
2090 {
d2b354f9 2091 AdjustScrollbars(m_previewCanvas);
95724b1a 2092 ((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
e71fd398 2093 m_previewCanvas->ClearBackground();
7bcb11d3 2094 m_previewCanvas->Refresh();
d2b354f9 2095 m_previewCanvas->SetFocus();
7bcb11d3 2096 }
2a47d3c1
JS
2097}
2098
383f6abd
WS
2099wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
2100{
e81e3883
RR
2101 return m_printDialogData;
2102}
2103
383f6abd 2104int wxPrintPreviewBase::GetZoom() const
e81e3883 2105{ return m_currentZoom; }
383f6abd 2106int wxPrintPreviewBase::GetMaxPage() const
e81e3883 2107{ return m_maxPage; }
383f6abd 2108int wxPrintPreviewBase::GetMinPage() const
e81e3883 2109{ return m_minPage; }
b7cacb43 2110bool wxPrintPreviewBase::IsOk() const
e81e3883 2111{ return m_isOk; }
383f6abd 2112void wxPrintPreviewBase::SetOk(bool ok)
e81e3883 2113{ m_isOk = ok; }
f415cab9 2114
e81e3883
RR
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;
383f6abd 2142
e81e3883
RR
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
383f6abd
WS
2154int wxPrintPreview::GetCurrentPage() const
2155{
e81e3883
RR
2156 return m_pimpl->GetCurrentPage();
2157}
2158
383f6abd
WS
2159void wxPrintPreview::SetPrintout(wxPrintout *printout)
2160{
e81e3883
RR
2161 m_pimpl->SetPrintout( printout );
2162}
2163
383f6abd
WS
2164wxPrintout *wxPrintPreview::GetPrintout() const
2165{
e81e3883
RR
2166 return m_pimpl->GetPrintout();
2167}
2168
383f6abd
WS
2169wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
2170{
e81e3883
RR
2171 return m_pimpl->GetPrintoutForPrinting();
2172}
2173
383f6abd
WS
2174void wxPrintPreview::SetFrame(wxFrame *frame)
2175{
e81e3883
RR
2176 m_pimpl->SetFrame( frame );
2177}
2178
383f6abd
WS
2179void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
2180{
e81e3883
RR
2181 m_pimpl->SetCanvas( canvas );
2182}
2183
383f6abd 2184wxFrame *wxPrintPreview::GetFrame() const
e81e3883
RR
2185{
2186 return m_pimpl->GetFrame();
2187}
2188
383f6abd
WS
2189wxPreviewCanvas *wxPrintPreview::GetCanvas() const
2190{
e81e3883
RR
2191 return m_pimpl->GetCanvas();
2192}
2193
2194bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
2195{
2196 return m_pimpl->PaintPage( canvas, dc );
2197}
2198
b88bf073
VS
2199bool wxPrintPreview::UpdatePageRendering()
2200{
2201 return m_pimpl->UpdatePageRendering();
2202}
2203
e81e3883
RR
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
d8766675
JS
2224int wxPrintPreview::GetZoom() const
2225{
2226 return m_pimpl->GetZoom();
2227}
2228
e81e3883
RR
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
b7cacb43 2244bool wxPrintPreview::IsOk() const
e81e3883 2245{
a1b806b9 2246 return m_pimpl->IsOk();
e81e3883
RR
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
d427503c 2264#endif // wxUSE_PRINTING_ARCHITECTURE