]> git.saurik.com Git - wxWidgets.git/blame - src/common/prntbase.cpp
remove some extraneous semicolons
[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
fc799548 324wxWindow *wxPrinterBase::CreateAbortWindow(wxWindow *parent, wxPrintout * printout)
c801d85f 325{
fc799548 326 wxPrintAbortDialog *dialog = new wxPrintAbortDialog(parent, _("Printing ") , wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE);
8826f46f 327
fc799548 328 wxBoxSizer *button_sizer = new wxBoxSizer( wxVERTICAL );
7e548f6b 329 button_sizer->Add( new wxStaticText(dialog, wxID_ANY, _("Please wait while printing\n") + printout->GetTitle() ), 0, wxALL, 10 );
fc799548 330 button_sizer->Add( new wxButton( dialog, wxID_CANCEL, wxT("Cancel") ), 0, wxALL | wxALIGN_CENTER, 10 );
8826f46f 331
7e548f6b 332 dialog->SetAutoLayout( true );
fc799548
JS
333 dialog->SetSizer( button_sizer );
334
335 button_sizer->Fit(dialog);
336 button_sizer->SetSizeHints (dialog) ;
8826f46f 337
7bcb11d3 338 return dialog;
c801d85f
KB
339}
340
161f4f73 341void wxPrinterBase::ReportError(wxWindow *parent, wxPrintout *WXUNUSED(printout), const wxString& message)
c801d85f 342{
7bcb11d3 343 wxMessageBox(message, _("Printing Error"), wxOK, parent);
c801d85f
KB
344}
345
c061373d
RR
346wxPrintDialogData& wxPrinterBase::GetPrintDialogData() const
347{
348 return (wxPrintDialogData&) m_printDialogData;
349}
350
e81e3883
RR
351//----------------------------------------------------------------------------
352// wxPrinter
353//----------------------------------------------------------------------------
354
355IMPLEMENT_CLASS(wxPrinter, wxPrinterBase)
356
357wxPrinter::wxPrinter(wxPrintDialogData *data)
358{
359 m_pimpl = wxPrintFactory::GetFactory()->CreatePrinter( data );
360}
361
362wxPrinter::~wxPrinter()
363{
364 delete m_pimpl;
365}
366
367wxWindow *wxPrinter::CreateAbortWindow(wxWindow *parent, wxPrintout *printout)
368{
369 return m_pimpl->CreateAbortWindow( parent, printout );
370}
371
372void wxPrinter::ReportError(wxWindow *parent, wxPrintout *printout, const wxString& message)
373{
374 m_pimpl->ReportError( parent, printout, message );
375}
376
377bool wxPrinter::Setup(wxWindow *parent)
378{
379 return m_pimpl->Setup( parent );
380}
381
382bool wxPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
383{
384 return m_pimpl->Print( parent, printout, prompt );
385}
386
387wxDC* wxPrinter::PrintDialog(wxWindow *parent)
388{
389 return m_pimpl->PrintDialog( parent );
390}
391
c061373d
RR
392wxPrintDialogData& wxPrinter::GetPrintDialogData() const
393{
394 return m_pimpl->GetPrintDialogData();
395}
396
397// ---------------------------------------------------------------------------
891daf8c 398// wxPrintDialogBase: the dialog for printing.
c061373d
RR
399// ---------------------------------------------------------------------------
400
891daf8c 401IMPLEMENT_ABSTRACT_CLASS(wxPrintDialogBase, wxDialog)
c061373d 402
6ce8c562 403wxPrintDialogBase::wxPrintDialogBase(wxWindow *parent,
2997ca30 404 wxWindowID id,
6ce8c562
VZ
405 const wxString &title,
406 const wxPoint &pos,
407 const wxSize &size,
408 long style)
891daf8c
RR
409 : wxDialog( parent, id, title.empty() ? wxString(_("Print")) : title,
410 pos, size, style )
c061373d
RR
411{
412}
413
414// ---------------------------------------------------------------------------
891daf8c 415// wxPrintDialog: the dialog for printing
c061373d
RR
416// ---------------------------------------------------------------------------
417
418IMPLEMENT_CLASS(wxPrintDialog, wxObject)
419
420wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintDialogData* data)
421{
422 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
423}
424
425wxPrintDialog::wxPrintDialog(wxWindow *parent, wxPrintData* data)
426{
427 m_pimpl = wxPrintFactory::GetFactory()->CreatePrintDialog( parent, data );
428}
429
430wxPrintDialog::~wxPrintDialog()
431{
432 delete m_pimpl;
433}
434
435int wxPrintDialog::ShowModal()
436{
437 return m_pimpl->ShowModal();
438}
439
440wxPrintDialogData& wxPrintDialog::GetPrintDialogData()
441{
442 return m_pimpl->GetPrintDialogData();
443}
444
445wxPrintData& wxPrintDialog::GetPrintData()
446{
447 return m_pimpl->GetPrintData();
448}
891daf8c 449
c061373d
RR
450wxDC *wxPrintDialog::GetPrintDC()
451{
452 return m_pimpl->GetPrintDC();
453}
454
891daf8c
RR
455// ---------------------------------------------------------------------------
456// wxPageSetupDialogBase: the page setup dialog
457// ---------------------------------------------------------------------------
458
459IMPLEMENT_ABSTRACT_CLASS(wxPageSetupDialogBase, wxDialog)
460
461wxPageSetupDialogBase::wxPageSetupDialogBase(wxWindow *parent,
2997ca30 462 wxWindowID id,
891daf8c
RR
463 const wxString &title,
464 const wxPoint &pos,
465 const wxSize &size,
466 long style)
467 : wxDialog( parent, id, title.empty() ? wxString(_("Page setup")) : title,
468 pos, size, style )
469{
470}
471
472// ---------------------------------------------------------------------------
473// wxPageSetupDialog: the page setup dialog
474// ---------------------------------------------------------------------------
475
476IMPLEMENT_CLASS(wxPageSetupDialog, wxObject)
477
478wxPageSetupDialog::wxPageSetupDialog(wxWindow *parent, wxPageSetupDialogData *data )
479{
480 m_pimpl = wxPrintFactory::GetFactory()->CreatePageSetupDialog( parent, data );
481}
482
483wxPageSetupDialog::~wxPageSetupDialog()
484{
485 delete m_pimpl;
486}
487
488int wxPageSetupDialog::ShowModal()
489{
490 return m_pimpl->ShowModal();
491}
492
493wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupDialogData()
494{
495 return m_pimpl->GetPageSetupDialogData();
496}
497
498// old name
499wxPageSetupDialogData& wxPageSetupDialog::GetPageSetupData()
500{
501 return m_pimpl->GetPageSetupDialogData();
502}
503
e81e3883
RR
504//----------------------------------------------------------------------------
505// wxPrintAbortDialog
506//----------------------------------------------------------------------------
507
508BEGIN_EVENT_TABLE(wxPrintAbortDialog, wxDialog)
509 EVT_BUTTON(wxID_CANCEL, wxPrintAbortDialog::OnCancel)
510END_EVENT_TABLE()
511
512void wxPrintAbortDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
513{
514 wxPrinterBase::sm_abortIt = true;
515 wxPrinterBase::sm_abortWindow->Show(false);
516 wxPrinterBase::sm_abortWindow->Close(true);
861eef72 517 wxPrinterBase::sm_abortWindow->Destroy();
d3b9f782 518 wxPrinterBase::sm_abortWindow = NULL;
e81e3883
RR
519}
520
521//----------------------------------------------------------------------------
522// wxPrintout
523//----------------------------------------------------------------------------
524
525IMPLEMENT_ABSTRACT_CLASS(wxPrintout, wxObject)
7bcb11d3 526
34da0970 527wxPrintout::wxPrintout(const wxString& title)
c801d85f 528{
7bcb11d3 529 m_printoutTitle = title ;
d3b9f782 530 m_printoutDC = NULL;
7bcb11d3
JS
531 m_pageWidthMM = 0;
532 m_pageHeightMM = 0;
533 m_pageWidthPixels = 0;
534 m_pageHeightPixels = 0;
535 m_PPIScreenX = 0;
536 m_PPIScreenY = 0;
537 m_PPIPrinterX = 0;
538 m_PPIPrinterY = 0;
1bd122dd 539 m_preview = NULL;
c801d85f
KB
540}
541
34da0970 542wxPrintout::~wxPrintout()
c801d85f 543{
c801d85f
KB
544}
545
546bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage), int WXUNUSED(endPage))
547{
fc799548 548 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle);
c801d85f
KB
549}
550
34da0970 551void wxPrintout::OnEndDocument()
c801d85f 552{
7bcb11d3 553 GetDC()->EndDoc();
c801d85f
KB
554}
555
34da0970 556void wxPrintout::OnBeginPrinting()
c801d85f
KB
557{
558}
559
34da0970 560void wxPrintout::OnEndPrinting()
c801d85f
KB
561{
562}
563
564bool wxPrintout::HasPage(int page)
565{
7bcb11d3 566 return (page == 1);
c801d85f
KB
567}
568
569void wxPrintout::GetPageInfo(int *minPage, int *maxPage, int *fromPage, int *toPage)
570{
7bcb11d3
JS
571 *minPage = 1;
572 *maxPage = 32000;
573 *fromPage = 1;
574 *toPage = 1;
c801d85f
KB
575}
576
f415cab9
JS
577void wxPrintout::FitThisSizeToPaper(const wxSize& imageSize)
578{
579 // Set the DC scale and origin so that the given image size fits within the
580 // entire page and the origin is at the top left corner of the page. Note
581 // that with most printers, portions of the page will be non-printable. Use
582 // this if you're managing your own page margins.
583 if (!m_printoutDC) return;
584 wxRect paperRect = GetPaperRectPixels();
585 wxCoord pw, ph;
586 GetPageSizePixels(&pw, &ph);
587 wxCoord w, h;
588 m_printoutDC->GetSize(&w, &h);
589 float scaleX = ((float(paperRect.width) * w) / (float(pw) * imageSize.x));
590 float scaleY = ((float(paperRect.height) * h) / (float(ph) * imageSize.y));
591 float actualScale = wxMin(scaleX, scaleY);
03647350 592 m_printoutDC->SetUserScale(actualScale, actualScale);
f415cab9
JS
593 m_printoutDC->SetDeviceOrigin(0, 0);
594 wxRect logicalPaperRect = GetLogicalPaperRect();
595 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
596}
597
598void wxPrintout::FitThisSizeToPage(const wxSize& imageSize)
599{
600 // Set the DC scale and origin so that the given image size fits within the
601 // printable area of the page and the origin is at the top left corner of
602 // the printable area.
603 if (!m_printoutDC) return;
604 int w, h;
605 m_printoutDC->GetSize(&w, &h);
606 float scaleX = float(w) / imageSize.x;
607 float scaleY = float(h) / imageSize.y;
608 float actualScale = wxMin(scaleX, scaleY);
03647350 609 m_printoutDC->SetUserScale(actualScale, actualScale);
f415cab9
JS
610 m_printoutDC->SetDeviceOrigin(0, 0);
611}
612
613void wxPrintout::FitThisSizeToPageMargins(const wxSize& imageSize, const wxPageSetupDialogData& pageSetupData)
614{
615 // Set the DC scale and origin so that the given image size fits within the
616 // page margins defined in the given wxPageSetupDialogData object and the
617 // origin is at the top left corner of the page margins.
618 if (!m_printoutDC) return;
619 wxRect paperRect = GetPaperRectPixels();
620 wxCoord pw, ph;
621 GetPageSizePixels(&pw, &ph);
622 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
623 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
624 wxCoord mw, mh;
625 GetPageSizeMM(&mw, &mh);
626 float mmToDeviceX = float(pw) / mw;
627 float mmToDeviceY = float(ph) / mh;
5a70d3f5
VZ
628 wxRect pageMarginsRect(paperRect.x + wxRound(mmToDeviceX * topLeft.x),
629 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
630 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
631 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
f415cab9
JS
632 wxCoord w, h;
633 m_printoutDC->GetSize(&w, &h);
634 float scaleX = (float(pageMarginsRect.width) * w) / (float(pw) * imageSize.x);
635 float scaleY = (float(pageMarginsRect.height) * h) / (float(ph) * imageSize.y);
636 float actualScale = wxMin(scaleX, scaleY);
03647350 637 m_printoutDC->SetUserScale(actualScale, actualScale);
f415cab9
JS
638 m_printoutDC->SetDeviceOrigin(0, 0);
639 wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
640 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
641}
642
643void wxPrintout::MapScreenSizeToPaper()
644{
645 // Set the DC scale so that an image on the screen is the same size on the
646 // paper and the origin is at the top left of the paper. Note that with most
647 // printers, portions of the page will be cut off. Use this if you're
648 // managing your own page margins.
649 if (!m_printoutDC) return;
650 MapScreenSizeToPage();
651 wxRect logicalPaperRect = GetLogicalPaperRect();
652 SetLogicalOrigin(logicalPaperRect.x, logicalPaperRect.y);
653}
654
655void wxPrintout::MapScreenSizeToPage()
656{
657 // Set the DC scale and origin so that an image on the screen is the same
658 // size on the paper and the origin is at the top left of the printable area.
659 if (!m_printoutDC) return;
03647350
VZ
660 int ppiScreenX, ppiScreenY;
661 GetPPIScreen(&ppiScreenX, &ppiScreenY);
662 int ppiPrinterX, ppiPrinterY;
663 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
664 int w, h;
665 m_printoutDC->GetSize(&w, &h);
666 int pageSizePixelsX, pageSizePixelsY;
667 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
668 float userScaleX = (float(ppiPrinterX) * w) / (float(ppiScreenX) * pageSizePixelsX);
669 float userScaleY = (float(ppiPrinterY) * h) / (float(ppiScreenY) * pageSizePixelsY);
f415cab9
JS
670 m_printoutDC->SetUserScale(userScaleX, userScaleY);
671 m_printoutDC->SetDeviceOrigin(0, 0);
672}
673
674void wxPrintout::MapScreenSizeToPageMargins(const wxPageSetupDialogData& pageSetupData)
675{
676 // Set the DC scale so that an image on the screen is the same size on the
677 // paper and the origin is at the top left of the page margins defined by
678 // the given wxPageSetupDialogData object.
679 if (!m_printoutDC) return;
680 MapScreenSizeToPage();
681 wxRect logicalPageMarginsRect = GetLogicalPageMarginsRect(pageSetupData);
682 SetLogicalOrigin(logicalPageMarginsRect.x, logicalPageMarginsRect.y);
683}
684
685void wxPrintout::MapScreenSizeToDevice()
686{
687 // Set the DC scale so that a screen pixel is the same size as a device
688 // pixel and the origin is at the top left of the printable area.
689 if (!m_printoutDC) return;
03647350
VZ
690 int w, h;
691 m_printoutDC->GetSize(&w, &h);
692 int pageSizePixelsX, pageSizePixelsY;
693 GetPageSizePixels(&pageSizePixelsX, &pageSizePixelsY);
694 float userScaleX = float(w) / pageSizePixelsX;
695 float userScaleY = float(h) / pageSizePixelsY;
f415cab9
JS
696 m_printoutDC->SetUserScale(userScaleX, userScaleY);
697 m_printoutDC->SetDeviceOrigin(0, 0);
698}
699
700wxRect wxPrintout::GetLogicalPaperRect() const
701{
702 // Return the rectangle in logical units that corresponds to the paper
703 // rectangle.
704 wxRect paperRect = GetPaperRectPixels();
705 wxCoord pw, ph;
706 GetPageSizePixels(&pw, &ph);
707 wxCoord w, h;
708 m_printoutDC->GetSize(&w, &h);
709 if (w == pw && h == ph) {
710 // this DC matches the printed page, so no scaling
03647350
VZ
711 return wxRect(m_printoutDC->DeviceToLogicalX(paperRect.x),
712 m_printoutDC->DeviceToLogicalY(paperRect.y),
713 m_printoutDC->DeviceToLogicalXRel(paperRect.width),
f415cab9
JS
714 m_printoutDC->DeviceToLogicalYRel(paperRect.height));
715 }
716 // This DC doesn't match the printed page, so we have to scale.
717 float scaleX = float(w) / pw;
718 float scaleY = float(h) / ph;
03647350
VZ
719 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(paperRect.x * scaleX)),
720 m_printoutDC->DeviceToLogicalY(wxRound(paperRect.y * scaleY)),
721 m_printoutDC->DeviceToLogicalXRel(wxRound(paperRect.width * scaleX)),
5a70d3f5 722 m_printoutDC->DeviceToLogicalYRel(wxRound(paperRect.height * scaleY)));
f415cab9
JS
723}
724
725wxRect wxPrintout::GetLogicalPageRect() const
726{
727 // Return the rectangle in logical units that corresponds to the printable
728 // area.
729 int w, h;
730 m_printoutDC->GetSize(&w, &h);
03647350
VZ
731 return wxRect(m_printoutDC->DeviceToLogicalX(0),
732 m_printoutDC->DeviceToLogicalY(0),
733 m_printoutDC->DeviceToLogicalXRel(w),
f415cab9
JS
734 m_printoutDC->DeviceToLogicalYRel(h));
735}
736
737wxRect wxPrintout::GetLogicalPageMarginsRect(const wxPageSetupDialogData& pageSetupData) const
738{
739 // Return the rectangle in logical units that corresponds to the region
740 // within the page margins as specified by the given wxPageSetupDialogData
741 // object.
03647350 742
02255e07
RR
743 // We get the paper size in device units and the margins in mm,
744 // so we need to calculate the conversion with this trick
f415cab9
JS
745 wxCoord pw, ph;
746 GetPageSizePixels(&pw, &ph);
f415cab9
JS
747 wxCoord mw, mh;
748 GetPageSizeMM(&mw, &mh);
749 float mmToDeviceX = float(pw) / mw;
750 float mmToDeviceY = float(ph) / mh;
02255e07 751
03647350 752 // paper size in device units
02255e07 753 wxRect paperRect = GetPaperRectPixels();
03647350 754
02255e07
RR
755 // margins in mm
756 wxPoint topLeft = pageSetupData.GetMarginTopLeft();
757 wxPoint bottomRight = pageSetupData.GetMarginBottomRight();
03647350 758
02255e07
RR
759 // calculate margins in device units
760 wxRect pageMarginsRect(
761 paperRect.x + wxRound(mmToDeviceX * topLeft.x),
762 paperRect.y + wxRound(mmToDeviceY * topLeft.y),
763 paperRect.width - wxRound(mmToDeviceX * (topLeft.x + bottomRight.x)),
5a70d3f5 764 paperRect.height - wxRound(mmToDeviceY * (topLeft.y + bottomRight.y)));
03647350 765
f415cab9
JS
766 wxCoord w, h;
767 m_printoutDC->GetSize(&w, &h);
03647350 768 if (w == pw && h == ph)
02255e07 769 {
f415cab9 770 // this DC matches the printed page, so no scaling
02255e07 771 return wxRect(
03647350
VZ
772 m_printoutDC->DeviceToLogicalX(pageMarginsRect.x),
773 m_printoutDC->DeviceToLogicalY(pageMarginsRect.y),
774 m_printoutDC->DeviceToLogicalXRel(pageMarginsRect.width),
f415cab9
JS
775 m_printoutDC->DeviceToLogicalYRel(pageMarginsRect.height));
776 }
03647350 777
f415cab9
JS
778 // This DC doesn't match the printed page, so we have to scale.
779 float scaleX = float(w) / pw;
780 float scaleY = float(h) / ph;
03647350
VZ
781 return wxRect(m_printoutDC->DeviceToLogicalX(wxRound(pageMarginsRect.x * scaleX)),
782 m_printoutDC->DeviceToLogicalY(wxRound(pageMarginsRect.y * scaleY)),
783 m_printoutDC->DeviceToLogicalXRel(wxRound(pageMarginsRect.width * scaleX)),
5a70d3f5 784 m_printoutDC->DeviceToLogicalYRel(wxRound(pageMarginsRect.height * scaleY)));
f415cab9
JS
785}
786
787void wxPrintout::SetLogicalOrigin(wxCoord x, wxCoord y)
788{
789 // Set the device origin by specifying a point in logical coordinates.
02255e07 790 m_printoutDC->SetDeviceOrigin(
03647350 791 m_printoutDC->LogicalToDeviceX(x),
02255e07 792 m_printoutDC->LogicalToDeviceY(y) );
f415cab9 793}
03647350 794
f415cab9
JS
795void wxPrintout::OffsetLogicalOrigin(wxCoord xoff, wxCoord yoff)
796{
797 // Offset the device origin by a specified distance in device coordinates.
02255e07
RR
798 wxPoint dev_org = m_printoutDC->GetDeviceOrigin();
799 m_printoutDC->SetDeviceOrigin(
03647350 800 dev_org.x + m_printoutDC->LogicalToDeviceXRel(xoff),
02255e07 801 dev_org.y + m_printoutDC->LogicalToDeviceYRel(yoff) );
f415cab9 802}
03647350 803
f415cab9 804
e81e3883
RR
805//----------------------------------------------------------------------------
806// wxPreviewCanvas
807//----------------------------------------------------------------------------
808
809IMPLEMENT_CLASS(wxPreviewCanvas, wxWindow)
810
811BEGIN_EVENT_TABLE(wxPreviewCanvas, wxScrolledWindow)
812 EVT_PAINT(wxPreviewCanvas::OnPaint)
813 EVT_CHAR(wxPreviewCanvas::OnChar)
b88bf073 814 EVT_IDLE(wxPreviewCanvas::OnIdle)
e81e3883 815 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged)
fb6efdf2
VZ
816#if wxUSE_MOUSEWHEEL
817 EVT_MOUSEWHEEL(wxPreviewCanvas::OnMouseWheel)
818#endif
e81e3883 819END_EVENT_TABLE()
7bcb11d3 820
e9cafd42
VZ
821// VZ: the current code doesn't refresh properly without
822// wxFULL_REPAINT_ON_RESIZE, this must be fixed as otherwise we have
823// really horrible flicker when resizing the preview frame, but without
824// this style it simply doesn't work correctly at all...
c801d85f 825wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase *preview, wxWindow *parent,
7bcb11d3 826 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
7e548f6b 827wxScrolledWindow(parent, wxID_ANY, pos, size, style | wxFULL_REPAINT_ON_RESIZE, name)
c801d85f 828{
7bcb11d3 829 m_printPreview = preview;
46b24ef9
JS
830#ifdef __WXMAC__
831 // The app workspace colour is always white, but we should have
832 // a contrast with the page.
ca5020c2 833 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
92b799e0
JS
834#elif defined(__WXGTK__)
835 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
46b24ef9
JS
836#else
837 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
e71fd398 838#endif
46b24ef9 839 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
8826f46f 840
d2b354f9 841 SetScrollbars(10, 10, 100, 100);
c801d85f
KB
842}
843
34da0970 844wxPreviewCanvas::~wxPreviewCanvas()
c801d85f
KB
845{
846}
847
848void wxPreviewCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
849{
7bcb11d3
JS
850 wxPaintDC dc(this);
851 PrepareDC( dc );
8826f46f 852
a56fcaaf 853/*
809934d2
RR
854#ifdef __WXGTK__
855 if (!GetUpdateRegion().IsEmpty())
856 dc.SetClippingRegion( GetUpdateRegion() );
857#endif
a56fcaaf 858*/
809934d2 859
7bcb11d3
JS
860 if (m_printPreview)
861 {
862 m_printPreview->PaintPage(this, dc);
863 }
c801d85f
KB
864}
865
b88bf073
VS
866void wxPreviewCanvas::OnIdle(wxIdleEvent& event)
867{
88b98787
VS
868 event.Skip();
869
870 // prevent UpdatePageRendering() from being called recursively:
871 static bool s_inIdle = false;
872 if ( s_inIdle )
873 return;
874 s_inIdle = true;
875
b88bf073
VS
876 if ( m_printPreview )
877 {
878 if ( m_printPreview->UpdatePageRendering() )
879 Refresh();
880 }
88b98787
VS
881
882 s_inIdle = false;
b88bf073
VS
883}
884
c801d85f
KB
885// Responds to colour changes, and passes event on to children.
886void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent& event)
887{
46b24ef9
JS
888#ifdef __WXMAC__
889 // The app workspace colour is always white, but we should have
890 // a contrast with the page.
ca5020c2 891 wxSystemColour colourIndex = wxSYS_COLOUR_3DDKSHADOW;
92b799e0
JS
892#elif defined(__WXGTK__)
893 wxSystemColour colourIndex = wxSYS_COLOUR_BTNFACE;
46b24ef9
JS
894#else
895 wxSystemColour colourIndex = wxSYS_COLOUR_APPWORKSPACE;
e71fd398 896#endif
46b24ef9 897 SetBackgroundColour(wxSystemSettings::GetColour(colourIndex));
7bcb11d3 898 Refresh();
8826f46f 899
7bcb11d3
JS
900 // Propagate the event to the non-top-level children
901 wxWindow::OnSysColourChanged(event);
c801d85f
KB
902}
903
d2b354f9
JS
904void wxPreviewCanvas::OnChar(wxKeyEvent &event)
905{
b38b0d22 906 wxPreviewControlBar* controlBar = ((wxPreviewFrame*) GetParent())->GetControlBar();
043c6705 907 switch (event.GetKeyCode())
d2b354f9 908 {
043c6705
VZ
909 case WXK_RETURN:
910 controlBar->OnPrint();
911 return;
82579461
VZ
912 case (int)'+':
913 case WXK_NUMPAD_ADD:
914 case WXK_ADD:
915 controlBar->DoZoomIn();
916 return;
917 case (int)'-':
918 case WXK_NUMPAD_SUBTRACT:
919 case WXK_SUBTRACT:
920 controlBar->DoZoomOut();
921 return;
b38b0d22
JS
922 }
923
d2b354f9
JS
924 if (!event.ControlDown())
925 {
926 event.Skip();
927 return;
928 }
e71fd398 929
b38b0d22
JS
930 switch(event.GetKeyCode())
931 {
faa94f3e 932 case WXK_PAGEDOWN:
b38b0d22 933 controlBar->OnNext(); break;
faa94f3e 934 case WXK_PAGEUP:
b38b0d22
JS
935 controlBar->OnPrevious(); break;
936 case WXK_HOME:
937 controlBar->OnFirst(); break;
938 case WXK_END:
939 controlBar->OnLast(); break;
940 default:
941 event.Skip();
942 }
d2b354f9
JS
943}
944
fb6efdf2
VZ
945#if wxUSE_MOUSEWHEEL
946
947void wxPreviewCanvas::OnMouseWheel(wxMouseEvent& event)
948{
949 wxPreviewControlBar *
950 controlBar = wxStaticCast(GetParent(), wxPreviewFrame)->GetControlBar();
951
952 if ( controlBar )
953 {
954 if ( event.ControlDown() && event.GetWheelRotation() != 0 )
955 {
956 int currentZoom = controlBar->GetZoomControl();
957
958 int delta;
959 if ( currentZoom < 100 )
960 delta = 5;
961 else if ( currentZoom <= 120 )
962 delta = 10;
963 else
964 delta = 50;
965
966 if ( event.GetWheelRotation() > 0 )
967 delta = -delta;
968
969 int newZoom = currentZoom + delta;
970 if ( newZoom < 10 )
971 newZoom = 10;
972 if ( newZoom > 200 )
973 newZoom = 200;
974 if ( newZoom != currentZoom )
975 {
976 controlBar->SetZoomControl(newZoom);
977 m_printPreview->SetZoom(newZoom);
978 Refresh();
979 }
980 return;
981 }
982 }
983
984 event.Skip();
985}
986
987#endif // wxUSE_MOUSEWHEEL
988
82579461
VZ
989// ----------------------------------------------------------------------------
990// wxPrintPageTextCtrl
991// ----------------------------------------------------------------------------
992
993// This text control contains the page number in the interval specified during
994// its construction. Invalid pages are not accepted and the control contents is
995// validated when it loses focus. Conversely, if the user changes the page to
996// another valid one or presses Enter, OnGotoPage() method of the preview object
997// will be called.
998class wxPrintPageTextCtrl : public wxTextCtrl
999{
1000public:
1001 wxPrintPageTextCtrl(wxPreviewControlBar *preview, int minPage, int maxPage)
1002 : wxTextCtrl(preview,
1003 wxID_PREVIEW_GOTO,
1004 PageAsString(minPage),
1005 wxDefaultPosition,
1006 // We use hardcoded 99999 for the width instead of fitting
1007 // it to the values we can show because the control looks
1008 // uncomfortably narrow if the real page number is just
1009 // one or two digits.
1010 wxSize(preview->GetTextExtent("99999").x, wxDefaultCoord),
1011 wxTE_PROCESS_ENTER
1012#if wxUSE_VALIDATORS
1013 , wxTextValidator(wxFILTER_DIGITS)
1014#endif // wxUSE_VALIDATORS
1015 ),
1016 m_preview(preview),
1017 m_minPage(minPage),
1018 m_maxPage(maxPage)
1019 {
1020 m_page = minPage;
1021
1022 Connect(wxEVT_KILL_FOCUS,
1023 wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus));
1024 Connect(wxEVT_COMMAND_TEXT_ENTER,
1025 wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter));
1026 }
1027
1028 // Helpers to conveniently set or get the current page number. Return value
1029 // is 0 if the current controls contents is invalid.
1030 void SetPageNumber(int page)
1031 {
1032 wxASSERT( IsValidPage(page) );
1033
1034 SetValue(PageAsString(page));
1035 }
1036
1037 int GetPageNumber() const
1038 {
1039 long value;
1040 if ( !GetValue().ToLong(&value) || !IsValidPage(value) )
1041 return 0;
1042
1043 // Cast is safe because the value is less than (int) m_maxPage.
1044 return static_cast<int>(value);
1045 }
1046
1047private:
1048 static wxString PageAsString(int page)
1049 {
1050 return wxString::Format("%d", page);
1051 }
1052
1053 bool IsValidPage(int page) const
1054 {
1055 return page >= m_minPage && page <= m_maxPage;
1056 }
1057
1058 bool DoChangePage()
1059 {
1060 const int page = GetPageNumber();
1061
1062 if ( !page )
1063 return false;
1064
1065 if ( page != m_page )
1066 {
1067 // We have a valid page, remember it.
1068 m_page = page;
1069
1070 // And notify the owner about the change.
1071 m_preview->OnGotoPage();
1072 }
1073 //else: Nothing really changed.
1074
1075 return true;
1076 }
1077
1078 void OnKillFocus(wxFocusEvent& event)
1079 {
1080 if ( !DoChangePage() )
1081 {
1082 // The current contents is invalid so reset it back to the last
1083 // known good page index.
1084 SetPageNumber(m_page);
1085 }
1086
1087 event.Skip();
1088 }
1089
1090 void OnTextEnter(wxCommandEvent& WXUNUSED(event))
1091 {
1092 DoChangePage();
1093 }
1094
1095
1096 wxPreviewControlBar * const m_preview;
1097
1098 const int m_minPage,
1099 m_maxPage;
1100
1101 // This is the last valid page value that we had, we revert to it if an
1102 // invalid page is entered.
1103 int m_page;
1104
1105 wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl);
1106};
1107
e81e3883
RR
1108//----------------------------------------------------------------------------
1109// wxPreviewControlBar
1110//----------------------------------------------------------------------------
1111
1112IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
c801d85f
KB
1113
1114BEGIN_EVENT_TABLE(wxPreviewControlBar, wxPanel)
8826f46f 1115 EVT_BUTTON(wxID_PREVIEW_CLOSE, wxPreviewControlBar::OnWindowClose)
90b6b974 1116 EVT_BUTTON(wxID_PREVIEW_PRINT, wxPreviewControlBar::OnPrintButton)
0f90ec93
KB
1117 EVT_BUTTON(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnPreviousButton)
1118 EVT_BUTTON(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnNextButton)
bf89b538
JS
1119 EVT_BUTTON(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnFirstButton)
1120 EVT_BUTTON(wxID_PREVIEW_LAST, wxPreviewControlBar::OnLastButton)
82579461
VZ
1121 EVT_BUTTON(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnZoomInButton)
1122 EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnZoomOutButton)
1123
1124 EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnUpdatePreviousButton)
1125 EVT_UPDATE_UI(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnUpdateNextButton)
1126 EVT_UPDATE_UI(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnUpdateFirstButton)
1127 EVT_UPDATE_UI(wxID_PREVIEW_LAST, wxPreviewControlBar::OnUpdateLastButton)
1128 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnUpdateZoomInButton)
1129 EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnUpdateZoomOutButton)
1130
1131 EVT_CHOICE(wxID_PREVIEW_ZOOM, wxPreviewControlBar::OnZoomChoice)
8826f46f 1132 EVT_PAINT(wxPreviewControlBar::OnPaint)
82579461 1133
c801d85f 1134END_EVENT_TABLE()
7bcb11d3 1135
c801d85f 1136wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
7bcb11d3
JS
1137 wxWindow *parent, const wxPoint& pos, const wxSize& size,
1138 long style, const wxString& name):
7e548f6b 1139wxPanel(parent, wxID_ANY, pos, size, style, name)
c801d85f 1140{
7bcb11d3 1141 m_printPreview = preview;
d3b9f782 1142 m_closeButton = NULL;
d3b9f782 1143 m_zoomControl = NULL;
82579461 1144 m_currentPageText = NULL;
7bcb11d3 1145 m_buttonFlags = buttons;
c801d85f
KB
1146}
1147
34da0970 1148wxPreviewControlBar::~wxPreviewControlBar()
c801d85f
KB
1149{
1150}
1151
1152void wxPreviewControlBar::OnPaint(wxPaintEvent& WXUNUSED(event))
1153{
7bcb11d3 1154 wxPaintDC dc(this);
8826f46f 1155
7bcb11d3
JS
1156 int w, h;
1157 GetSize(&w, &h);
1158 dc.SetPen(*wxBLACK_PEN);
1159 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1160 dc.DrawLine( 0, h-1, w, h-1 );
c801d85f
KB
1161}
1162
c330a2cf 1163void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
c801d85f 1164{
7bcb11d3 1165 wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
7e548f6b 1166 frame->Close(true);
c801d85f
KB
1167}
1168
b38b0d22 1169void wxPreviewControlBar::OnPrint(void)
c801d85f 1170{
7bcb11d3 1171 wxPrintPreviewBase *preview = GetPrintPreview();
7e548f6b 1172 preview->Print(true);
c801d85f
KB
1173}
1174
82579461
VZ
1175void wxPreviewControlBar::OnNext()
1176{
1177 if ( IsNextEnabled() )
1178 DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
1179}
1180
1181void wxPreviewControlBar::OnPrevious()
1182{
1183 if ( IsPreviousEnabled() )
1184 DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
1185}
1186
1187void wxPreviewControlBar::OnFirst()
1188{
1189 if ( IsFirstEnabled() )
1190 DoGotoPage(GetPrintPreview()->GetMinPage());
1191}
1192
1193void wxPreviewControlBar::OnLast()
1194{
1195 if ( IsLastEnabled() )
1196 DoGotoPage(GetPrintPreview()->GetMaxPage());
1197}
1198
1199bool wxPreviewControlBar::IsNextEnabled() const
c801d85f 1200{
7bcb11d3 1201 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1202 if ( !preview )
1203 return false;
1204
1205 const int currentPage = preview->GetCurrentPage();
1206 return currentPage < preview->GetMaxPage() &&
1207 preview->GetPrintout()->HasPage(currentPage + 1);
c801d85f
KB
1208}
1209
82579461 1210bool wxPreviewControlBar::IsPreviousEnabled() const
c801d85f 1211{
7bcb11d3 1212 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1213 if ( !preview )
1214 return false;
1215
1216 const int currentPage = preview->GetCurrentPage();
1217 return currentPage > preview->GetMinPage() &&
1218 preview->GetPrintout()->HasPage(currentPage - 1);
c801d85f
KB
1219}
1220
82579461 1221bool wxPreviewControlBar::IsFirstEnabled() const
bf89b538
JS
1222{
1223 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1224 if (!preview)
1225 return false;
1226
1227 return preview->GetPrintout()->HasPage(preview->GetMinPage());
bf89b538
JS
1228}
1229
82579461 1230bool wxPreviewControlBar::IsLastEnabled() const
bf89b538
JS
1231{
1232 wxPrintPreviewBase *preview = GetPrintPreview();
82579461
VZ
1233 if (!preview)
1234 return false;
1235
1236 return preview->GetPrintout()->HasPage(preview->GetMaxPage());
bf89b538
JS
1237}
1238
82579461
VZ
1239void wxPreviewControlBar::DoGotoPage(int page)
1240{
1241 wxPrintPreviewBase *preview = GetPrintPreview();
1242 wxCHECK_RET( preview, "Shouldn't be called if there is no preview." );
1243
1244 preview->SetCurrentPage(page);
1245
1246 if ( m_currentPageText )
1247 m_currentPageText->SetPageNumber(page);
1248}
1249
1250void wxPreviewControlBar::OnGotoPage()
bf89b538
JS
1251{
1252 wxPrintPreviewBase *preview = GetPrintPreview();
1253 if (preview)
1254 {
bf89b538
JS
1255 if (preview->GetMinPage() > 0)
1256 {
82579461
VZ
1257 long currentPage = m_currentPageText->GetPageNumber();
1258 if ( currentPage )
1259 {
bf89b538
JS
1260 if (preview->GetPrintout()->HasPage(currentPage))
1261 {
1262 preview->SetCurrentPage(currentPage);
1263 }
82579461 1264 }
bf89b538
JS
1265 }
1266 }
1267}
1268
82579461 1269void wxPreviewControlBar::DoZoom()
c801d85f 1270{
7bcb11d3
JS
1271 int zoom = GetZoomControl();
1272 if (GetPrintPreview())
1273 GetPrintPreview()->SetZoom(zoom);
c801d85f
KB
1274}
1275
82579461
VZ
1276bool wxPreviewControlBar::IsZoomInEnabled() const
1277{
1278 if ( !m_zoomControl )
1279 return false;
1280
1281 const unsigned sel = m_zoomControl->GetSelection();
1282 return sel < m_zoomControl->GetCount() - 1;
1283}
1284
1285bool wxPreviewControlBar::IsZoomOutEnabled() const
1286{
1287 return m_zoomControl && m_zoomControl->GetSelection() > 0;
1288}
1289
1290void wxPreviewControlBar::DoZoomIn()
1291{
1292 if (IsZoomInEnabled())
1293 {
1294 m_zoomControl->SetSelection(m_zoomControl->GetSelection() + 1);
1295 DoZoom();
1296 }
1297}
1298
1299void wxPreviewControlBar::DoZoomOut()
1300{
1301 if (IsZoomOutEnabled())
1302 {
1303 m_zoomControl->SetSelection(m_zoomControl->GetSelection() - 1);
1304 DoZoom();
1305 }
1306}
1307
1308namespace
1309{
1310
1311// Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
1312// sequentially to it in the simplest way possible.
1313class SizerWithButtons
1314{
1315public:
1316 // Constructor creates the sizer that will hold the buttons and stores the
1317 // parent that will be used for their creation.
1318 SizerWithButtons(wxWindow *parent)
1319 : m_sizer(new wxBoxSizer(wxHORIZONTAL)),
1320 m_parent(parent)
1321 {
1322 m_hasContents =
1323 m_needsSeparator = false;
1324 }
1325
1326 // Destructor associates the sizer with the parent window.
1327 ~SizerWithButtons()
1328 {
1329 m_parent->SetSizer(m_sizer);
1330 m_sizer->Fit(m_parent);
1331 }
1332
1333
1334 // Add an arbitrary window to the sizer.
1335 void Add(wxWindow *win)
1336 {
1337 if ( m_needsSeparator )
1338 {
1339 m_needsSeparator = false;
1340
1341 m_sizer->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
1342 }
1343
1344 m_hasContents = true;
1345
1346 m_sizer->Add(win,
1347 wxSizerFlags().Border(wxLEFT | wxTOP | wxBOTTOM).Center());
1348 }
1349
1350 // Add a button with the specified id, bitmap and tooltip.
1351 void AddButton(wxWindowID btnId,
1352 const wxArtID& artId,
1353 const wxString& tooltip)
1354 {
1355 // We don't use (smaller) images inside a button with a text label but
1356 // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
1357 // wxART_BUTTON here.
1358 wxBitmap bmp = wxArtProvider::GetBitmap(artId, wxART_TOOLBAR);
1359 wxBitmapButton * const btn = new wxBitmapButton(m_parent, btnId, bmp);
1360 btn->SetToolTip(tooltip);
1361
1362 Add(btn);
1363 }
1364
1365 // Add a control at the right end of the window. This should be called last
1366 // as everything else added after it will be added on the right side too.
1367 void AddAtEnd(wxWindow *win)
1368 {
1369 m_sizer->AddStretchSpacer();
1370 m_sizer->Add(win,
1371 wxSizerFlags().Border(wxTOP | wxBOTTOM | wxRIGHT).Center());
1372 }
1373
1374 // Indicates the end of a group of buttons, a separator will be added after
1375 // it.
1376 void EndOfGroup()
1377 {
1378 if ( m_hasContents )
1379 {
1380 m_needsSeparator = true;
1381 m_hasContents = false;
1382 }
1383 }
1384
1385private:
1386 wxSizer * const m_sizer;
1387 wxWindow * const m_parent;
1388
1389 // If true, we have some controls since the last group beginning. This is
1390 // used to avoid inserting two consecutive separators if EndOfGroup() is
1391 // called twice.
1392 bool m_hasContents;
1393
1394 // If true, a separator should be inserted before adding the next button.
1395 bool m_needsSeparator;
1396
1397 wxDECLARE_NO_COPY_CLASS(SizerWithButtons);
1398};
1399
1400} // anonymous namespace
1401
34da0970 1402void wxPreviewControlBar::CreateButtons()
c801d85f 1403{
82579461 1404 SizerWithButtons sizer(this);
e71fd398 1405
82579461 1406 // Print button group (a single button).
7bcb11d3
JS
1407 if (m_buttonFlags & wxPREVIEW_PRINT)
1408 {
82579461
VZ
1409 sizer.AddButton(wxID_PREVIEW_PRINT, wxART_PRINT, _("Print"));
1410 sizer.EndOfGroup();
7bcb11d3 1411 }
e71fd398 1412
82579461 1413 // Page selection buttons group.
bf89b538
JS
1414 if (m_buttonFlags & wxPREVIEW_FIRST)
1415 {
82579461 1416 sizer.AddButton(wxID_PREVIEW_FIRST, wxART_GOTO_FIRST, _("First page"));
bf89b538 1417 }
e71fd398 1418
7bcb11d3
JS
1419 if (m_buttonFlags & wxPREVIEW_PREVIOUS)
1420 {
82579461 1421 sizer.AddButton(wxID_PREVIEW_PREVIOUS, wxART_GO_BACK, _("Previous page"));
7bcb11d3 1422 }
e71fd398 1423
82579461 1424 if (m_buttonFlags & wxPREVIEW_GOTO)
7bcb11d3 1425 {
82579461
VZ
1426 int minPage, maxPage, pageFrom, pageTo;
1427 m_printPreview->GetPrintout()->GetPageInfo(&minPage, &maxPage,
1428 &pageFrom, &pageTo);
1429
1430 m_currentPageText = new wxPrintPageTextCtrl(this, minPage, maxPage);
1431 sizer.Add(m_currentPageText);
1432
1433 wxStaticText *
1434 maxPageText = new wxStaticText(this, wxID_ANY,
1435 wxString::Format("/ %d", maxPage));
1436
1437 sizer.Add(maxPageText);
bf89b538 1438 }
e71fd398 1439
82579461 1440 if (m_buttonFlags & wxPREVIEW_NEXT)
bf89b538 1441 {
82579461 1442 sizer.AddButton(wxID_PREVIEW_NEXT, wxART_GO_FORWARD, _("Next page"));
bf89b538 1443 }
e71fd398 1444
82579461 1445 if (m_buttonFlags & wxPREVIEW_LAST)
bf89b538 1446 {
82579461 1447 sizer.AddButton(wxID_PREVIEW_LAST, wxART_GOTO_LAST, _("Last page"));
7bcb11d3 1448 }
e71fd398 1449
82579461
VZ
1450 sizer.EndOfGroup();
1451
1452 // Zoom controls group.
7bcb11d3
JS
1453 if (m_buttonFlags & wxPREVIEW_ZOOM)
1454 {
82579461
VZ
1455 sizer.AddButton(wxID_PREVIEW_ZOOM_OUT, wxART_MINUS, _("Zoom Out"));
1456
e71fd398 1457 wxString choices[] =
c25ccf85 1458 {
2b5f62a0 1459 wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
9dff8515
JS
1460 wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
1461 wxT("120%"), wxT("150%"), wxT("200%")
c25ccf85 1462 };
c25ccf85 1463 int n = WXSIZEOF(choices);
e71fd398 1464
7e548f6b 1465 m_zoomControl = new wxChoice( this, wxID_PREVIEW_ZOOM, wxDefaultPosition, wxSize(70,wxDefaultCoord), n, choices, 0 );
82579461 1466 sizer.Add(m_zoomControl);
7bcb11d3 1467 SetZoomControl(m_printPreview->GetZoom());
82579461
VZ
1468
1469 sizer.AddButton(wxID_PREVIEW_ZOOM_IN, wxART_PLUS, _("Zoom In"));
1470
1471 sizer.EndOfGroup();
7bcb11d3 1472 }
8826f46f 1473
82579461
VZ
1474 // Close button group (single button again).
1475 m_closeButton = new wxButton(this, wxID_PREVIEW_CLOSE, _("&Close"));
1476 sizer.AddAtEnd(m_closeButton);
c801d85f
KB
1477}
1478
1479void wxPreviewControlBar::SetZoomControl(int zoom)
1480{
7bcb11d3 1481 if (m_zoomControl)
963907fa
RR
1482 {
1483 int n, count = m_zoomControl->GetCount();
1484 long val;
1485 for (n=0; n<count; n++)
1486 {
1487 if (m_zoomControl->GetString(n).BeforeFirst(wxT('%')).ToLong(&val) &&
1488 (val >= long(zoom)))
1489 {
1490 m_zoomControl->SetSelection(n);
1491 return;
1492 }
1493 }
7e548f6b 1494
963907fa
RR
1495 m_zoomControl->SetSelection(count-1);
1496 }
c801d85f
KB
1497}
1498
34da0970 1499int wxPreviewControlBar::GetZoomControl()
c801d85f 1500{
963907fa 1501 if (m_zoomControl && (m_zoomControl->GetStringSelection() != wxEmptyString))
7bcb11d3 1502 {
963907fa
RR
1503 long val;
1504 if (m_zoomControl->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val))
1505 return int(val);
7bcb11d3 1506 }
7e548f6b 1507
963907fa 1508 return 0;
c801d85f
KB
1509}
1510
1511
1512/*
7bcb11d3
JS
1513* Preview frame
1514*/
c801d85f 1515
e81e3883
RR
1516IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
1517
e3065973 1518BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
043c6705 1519 EVT_CHAR_HOOK(wxPreviewFrame::OnChar)
0f90ec93 1520 EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
e3065973
JS
1521END_EVENT_TABLE()
1522
043c6705
VZ
1523void wxPreviewFrame::OnChar(wxKeyEvent &event)
1524{
1525 if ( event.GetKeyCode() == WXK_ESCAPE )
1526 {
1527 Close(true);
1528 }
1529 else
1530 {
1531 event.Skip();
1532 }
1533}
1534
a5ae8241 1535wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
7bcb11d3 1536 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
7e548f6b 1537wxFrame(parent, wxID_ANY, title, pos, size, style, name)
c801d85f 1538{
7bcb11d3
JS
1539 m_printPreview = preview;
1540 m_controlBar = NULL;
1541 m_previewCanvas = NULL;
7c995553 1542 m_windowDisabler = NULL;
46b24ef9 1543
a5ae8241 1544 // Give the application icon
46b24ef9
JS
1545#ifdef __WXMSW__
1546 wxFrame* topFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
1547 if (topFrame)
7ccf316e 1548 SetIcons(topFrame->GetIcons());
e71fd398 1549#endif
c801d85f
KB
1550}
1551
34da0970 1552wxPreviewFrame::~wxPreviewFrame()
c801d85f
KB
1553{
1554}
1555
74e3313b 1556void wxPreviewFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
c801d85f 1557{
7c995553
VZ
1558 if (m_windowDisabler)
1559 delete m_windowDisabler;
8826f46f 1560
7bcb11d3
JS
1561 // Need to delete the printout and the print preview
1562 wxPrintout *printout = m_printPreview->GetPrintout();
1563 if (printout)
1564 {
1565 delete printout;
1566 m_printPreview->SetPrintout(NULL);
1567 m_printPreview->SetCanvas(NULL);
1568 m_printPreview->SetFrame(NULL);
1569 }
b88bf073
VS
1570
1571 m_previewCanvas->SetPreview(NULL);
1572 wxDELETE(m_printPreview);
8826f46f 1573
7bcb11d3 1574 Destroy();
c801d85f
KB
1575}
1576
34da0970 1577void wxPreviewFrame::Initialize()
c801d85f 1578{
3080bf59 1579#if wxUSE_STATUSBAR
7bcb11d3 1580 CreateStatusBar();
3080bf59 1581#endif
7bcb11d3
JS
1582 CreateCanvas();
1583 CreateControlBar();
8826f46f 1584
7bcb11d3
JS
1585 m_printPreview->SetCanvas(m_previewCanvas);
1586 m_printPreview->SetFrame(this);
8826f46f 1587
9dff8515 1588 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
8826f46f 1589
9dff8515
JS
1590 item0->Add( m_controlBar, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
1591 item0->Add( m_previewCanvas, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
8826f46f 1592
7e548f6b 1593 SetAutoLayout( true );
9dff8515 1594 SetSizer( item0 );
8826f46f 1595
7c995553 1596 m_windowDisabler = new wxWindowDisabler(this);
8826f46f 1597
7bcb11d3 1598 Layout();
e71fd398 1599
d2b354f9
JS
1600 m_printPreview->AdjustScrollbars(m_previewCanvas);
1601 m_previewCanvas->SetFocus();
1602 m_controlBar->SetFocus();
c801d85f
KB
1603}
1604
34da0970 1605void wxPreviewFrame::CreateCanvas()
c801d85f 1606{
7bcb11d3 1607 m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
c801d85f
KB
1608}
1609
34da0970 1610void wxPreviewFrame::CreateControlBar()
c801d85f 1611{
7bcb11d3
JS
1612 long buttons = wxPREVIEW_DEFAULT;
1613 if (m_printPreview->GetPrintoutForPrinting())
1614 buttons |= wxPREVIEW_PRINT;
8826f46f 1615
e562dfb1 1616 m_controlBar = new wxPreviewControlBar(m_printPreview, buttons, this);
7bcb11d3 1617 m_controlBar->CreateButtons();
c801d85f 1618}
7bcb11d3 1619
c801d85f 1620/*
7bcb11d3
JS
1621* Print preview
1622*/
c801d85f 1623
891daf8c
RR
1624IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
1625
8826f46f
VZ
1626wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1627 wxPrintout *printoutForPrinting,
1628 wxPrintData *data)
1629{
1630 if (data)
1631 m_printDialogData = (*data);
1632
1633 Init(printout, printoutForPrinting);
1634}
1635
1636wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
1637 wxPrintout *printoutForPrinting,
1638 wxPrintDialogData *data)
1639{
1640 if (data)
1641 m_printDialogData = (*data);
1642
1643 Init(printout, printoutForPrinting);
1644}
1645
1646void wxPrintPreviewBase::Init(wxPrintout *printout,
1647 wxPrintout *printoutForPrinting)
c801d85f 1648{
7e548f6b 1649 m_isOk = true;
7bcb11d3
JS
1650 m_previewPrintout = printout;
1651 if (m_previewPrintout)
1bd122dd 1652 m_previewPrintout->SetPreview(static_cast<wxPrintPreview *>(this));
8826f46f 1653
7bcb11d3 1654 m_printPrintout = printoutForPrinting;
8826f46f 1655
7bcb11d3
JS
1656 m_previewCanvas = NULL;
1657 m_previewFrame = NULL;
1658 m_previewBitmap = NULL;
88b98787 1659 m_previewFailed = false;
7bcb11d3 1660 m_currentPage = 1;
c25ccf85 1661 m_currentZoom = 70;
41e1c9d8
VZ
1662 m_topMargin =
1663 m_leftMargin = 2*wxSizerFlags::GetDefaultBorder();
7bcb11d3
JS
1664 m_pageWidth = 0;
1665 m_pageHeight = 0;
7e548f6b 1666 m_printingPrepared = false;
d2b354f9
JS
1667 m_minPage = 1;
1668 m_maxPage = 1;
c801d85f
KB
1669}
1670
34da0970 1671wxPrintPreviewBase::~wxPrintPreviewBase()
c801d85f 1672{
7bcb11d3
JS
1673 if (m_previewPrintout)
1674 delete m_previewPrintout;
1675 if (m_previewBitmap)
1676 delete m_previewBitmap;
1677 if (m_printPrintout)
1678 delete m_printPrintout;
c801d85f
KB
1679}
1680
1681bool wxPrintPreviewBase::SetCurrentPage(int pageNum)
1682{
7bcb11d3 1683 if (m_currentPage == pageNum)
7e548f6b 1684 return true;
8826f46f 1685
7bcb11d3 1686 m_currentPage = pageNum;
88b98787
VS
1687
1688 InvalidatePreviewBitmap();
e71fd398 1689
7bcb11d3
JS
1690 if (m_previewCanvas)
1691 {
d2b354f9 1692 AdjustScrollbars(m_previewCanvas);
e71fd398 1693
7bcb11d3 1694 m_previewCanvas->Refresh();
d2b354f9 1695 m_previewCanvas->SetFocus();
7bcb11d3 1696 }
7e548f6b 1697 return true;
c801d85f
KB
1698}
1699
383f6abd 1700int wxPrintPreviewBase::GetCurrentPage() const
259c43f6 1701 { return m_currentPage; }
383f6abd 1702void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
259c43f6 1703 { m_previewPrintout = printout; }
383f6abd 1704wxPrintout *wxPrintPreviewBase::GetPrintout() const
259c43f6 1705 { return m_previewPrintout; }
383f6abd 1706wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
259c43f6 1707 { return m_printPrintout; }
383f6abd 1708void wxPrintPreviewBase::SetFrame(wxFrame *frame)
259c43f6 1709 { m_previewFrame = frame; }
383f6abd 1710void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
259c43f6 1711 { m_previewCanvas = canvas; }
383f6abd 1712wxFrame *wxPrintPreviewBase::GetFrame() const
e81e3883 1713 { return m_previewFrame; }
383f6abd 1714wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
e81e3883
RR
1715 { return m_previewCanvas; }
1716
f415cab9
JS
1717void wxPrintPreviewBase::CalcRects(wxPreviewCanvas *canvas, wxRect& pageRect, wxRect& paperRect)
1718{
1719 // Calculate the rectangles for the printable area of the page and the
1720 // entire paper as they appear on the canvas on-screen.
1721 int canvasWidth, canvasHeight;
1722 canvas->GetSize(&canvasWidth, &canvasHeight);
1723
1724 float zoomScale = float(m_currentZoom) / 100;
1725 float screenPrintableWidth = zoomScale * m_pageWidth * m_previewScaleX;
1726 float screenPrintableHeight = zoomScale * m_pageHeight * m_previewScaleY;
1727
1728 wxRect devicePaperRect = m_previewPrintout->GetPaperRectPixels();
1729 wxCoord devicePrintableWidth, devicePrintableHeight;
1730 m_previewPrintout->GetPageSizePixels(&devicePrintableWidth, &devicePrintableHeight);
1731 float scaleX = screenPrintableWidth / devicePrintableWidth;
1732 float scaleY = screenPrintableHeight / devicePrintableHeight;
1733 paperRect.width = wxCoord(scaleX * devicePaperRect.width);
1734 paperRect.height = wxCoord(scaleY * devicePaperRect.height);
1735
1736 paperRect.x = wxCoord((canvasWidth - paperRect.width)/ 2.0);
1737 if (paperRect.x < m_leftMargin)
1738 paperRect.x = m_leftMargin;
1739 paperRect.y = wxCoord((canvasHeight - paperRect.height)/ 2.0);
1740 if (paperRect.y < m_topMargin)
1741 paperRect.y = m_topMargin;
1742
1743 pageRect.x = paperRect.x - wxCoord(scaleX * devicePaperRect.x);
1744 pageRect.y = paperRect.y - wxCoord(scaleY * devicePaperRect.y);
1745 pageRect.width = wxCoord(screenPrintableWidth);
1746 pageRect.height = wxCoord(screenPrintableHeight);
1747}
1748
1749
88b98787
VS
1750void wxPrintPreviewBase::InvalidatePreviewBitmap()
1751{
1752 wxDELETE(m_previewBitmap);
1753 // if there was a problem with rendering the preview, try again now
1754 // that it changed in some way (less memory may be needed, for example):
1755 m_previewFailed = false;
1756}
1757
b88bf073
VS
1758bool wxPrintPreviewBase::UpdatePageRendering()
1759{
1760 if ( m_previewBitmap )
1761 return false;
1762
88b98787
VS
1763 if ( m_previewFailed )
1764 return false;
1765
b88bf073 1766 if ( !RenderPage(m_currentPage) )
88b98787
VS
1767 {
1768 m_previewFailed = true; // don't waste time failing again
b88bf073 1769 return false;
88b98787 1770 }
b88bf073
VS
1771
1772 return true;
1773}
1774
d2b354f9 1775bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
c801d85f 1776{
7bcb11d3 1777 DrawBlankPage(canvas, dc);
8826f46f 1778
7bcb11d3 1779 if (!m_previewBitmap)
7e548f6b 1780 return false;
7bcb11d3 1781 if (!canvas)
7e548f6b 1782 return false;
8826f46f 1783
f415cab9
JS
1784 wxRect pageRect, paperRect;
1785 CalcRects(canvas, pageRect, paperRect);
7bcb11d3
JS
1786 wxMemoryDC temp_dc;
1787 temp_dc.SelectObject(*m_previewBitmap);
8826f46f 1788
03647350 1789 dc.Blit(pageRect.x, pageRect.y,
f415cab9 1790 m_previewBitmap->GetWidth(), m_previewBitmap->GetHeight(), &temp_dc, 0, 0);
8826f46f 1791
7bcb11d3 1792 temp_dc.SelectObject(wxNullBitmap);
7e548f6b 1793 return true;
c801d85f
KB
1794}
1795
d2b354f9
JS
1796// Adjusts the scrollbars for the current scale
1797void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas *canvas)
1798{
1799 if (!canvas)
1800 return ;
1801
f415cab9
JS
1802 wxRect pageRect, paperRect;
1803 CalcRects(canvas, pageRect, paperRect);
1804 int totalWidth = paperRect.width + 2 * m_leftMargin;
1805 int totalHeight = paperRect.height + 2 * m_topMargin;
1806 int scrollUnitsX = totalWidth / 10;
1807 int scrollUnitsY = totalHeight / 10;
d2b354f9
JS
1808 wxSize virtualSize = canvas->GetVirtualSize();
1809 if (virtualSize.GetWidth() != totalWidth || virtualSize.GetHeight() != totalHeight)
7e548f6b 1810 canvas->SetScrollbars(10, 10, scrollUnitsX, scrollUnitsY, 0, 0, true);
d2b354f9
JS
1811}
1812
25a3fca2
VS
1813bool wxPrintPreviewBase::RenderPageIntoDC(wxDC& dc, int pageNum)
1814{
1815 m_previewPrintout->SetDC(&dc);
1816 m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
1817
1818 // Need to delay OnPreparePrinting() until here, so we have enough
1819 // information.
1820 if (!m_printingPrepared)
1821 {
1822 m_previewPrintout->OnPreparePrinting();
1823 int selFrom, selTo;
1824 m_previewPrintout->GetPageInfo(&m_minPage, &m_maxPage, &selFrom, &selTo);
1825 m_printingPrepared = true;
1826 }
1827
1828 m_previewPrintout->OnBeginPrinting();
1829
1830 if (!m_previewPrintout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
1831 {
1832 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK);
1833 return false;
1834 }
1835
1836 m_previewPrintout->OnPrintPage(pageNum);
1837 m_previewPrintout->OnEndDocument();
1838 m_previewPrintout->OnEndPrinting();
1839
1840 m_previewPrintout->SetDC(NULL);
1841
1842 return true;
1843}
1844
1845bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap& bmp, int pageNum)
1846{
1847 wxMemoryDC memoryDC;
1848 memoryDC.SelectObject(bmp);
1849 memoryDC.Clear();
1850
1851 return RenderPageIntoDC(memoryDC, pageNum);
1852}
1853
c801d85f
KB
1854bool wxPrintPreviewBase::RenderPage(int pageNum)
1855{
f6bcfd97
BP
1856 wxBusyCursor busy;
1857
7bcb11d3 1858 if (!m_previewCanvas)
c801d85f 1859 {
9a83f860 1860 wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
7e548f6b 1861 return false;
c801d85f 1862 }
8826f46f 1863
f415cab9
JS
1864 wxRect pageRect, paperRect;
1865 CalcRects(m_previewCanvas, pageRect, paperRect);
8826f46f 1866
7bcb11d3
JS
1867 if (!m_previewBitmap)
1868 {
f415cab9
JS
1869 m_previewBitmap = new wxBitmap(pageRect.width, pageRect.height);
1870
7bcb11d3
JS
1871 if (!m_previewBitmap || !m_previewBitmap->Ok())
1872 {
88b98787 1873 InvalidatePreviewBitmap();
7bcb11d3 1874 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
7e548f6b 1875 return false;
7bcb11d3
JS
1876 }
1877 }
8826f46f 1878
25a3fca2 1879 if ( !RenderPageIntoBitmap(*m_previewBitmap, pageNum) )
7bcb11d3 1880 {
88b98787 1881 InvalidatePreviewBitmap();
25a3fca2 1882 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
7e548f6b 1883 return false;
7bcb11d3 1884 }
8826f46f 1885
3080bf59
VZ
1886#if wxUSE_STATUSBAR
1887 wxString status;
7bcb11d3 1888 if (m_maxPage != 0)
7e548f6b 1889 status = wxString::Format(_("Page %d of %d"), pageNum, m_maxPage);
7bcb11d3 1890 else
7e548f6b 1891 status = wxString::Format(_("Page %d"), pageNum);
8826f46f 1892
7bcb11d3 1893 if (m_previewFrame)
3080bf59
VZ
1894 m_previewFrame->SetStatusText(status);
1895#endif
8826f46f 1896
7e548f6b 1897 return true;
c801d85f
KB
1898}
1899
d2b354f9 1900bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
c801d85f 1901{
f415cab9 1902 wxRect pageRect, paperRect;
8826f46f 1903
f415cab9 1904 CalcRects(canvas, pageRect, paperRect);
8826f46f 1905
f415cab9
JS
1906 // Draw shadow, allowing for 1-pixel border AROUND the actual paper
1907 wxCoord shadowOffset = 4;
8826f46f 1908
7bcb11d3
JS
1909 dc.SetPen(*wxBLACK_PEN);
1910 dc.SetBrush(*wxBLACK_BRUSH);
f415cab9
JS
1911 dc.DrawRectangle(paperRect.x + shadowOffset, paperRect.y + paperRect.height + 1,
1912 paperRect.width, shadowOffset);
1913
1914 dc.DrawRectangle(paperRect.x + paperRect.width, paperRect.y + shadowOffset,
1915 shadowOffset, paperRect.height);
8826f46f 1916
f415cab9 1917 // Draw blank page allowing for 1-pixel border AROUND the actual paper
7bcb11d3
JS
1918 dc.SetPen(*wxBLACK_PEN);
1919 dc.SetBrush(*wxWHITE_BRUSH);
03647350 1920 dc.DrawRectangle(paperRect.x - 2, paperRect.y - 1,
f415cab9 1921 paperRect.width + 3, paperRect.height + 2);
8826f46f 1922
7e548f6b 1923 return true;
2a47d3c1
JS
1924}
1925
7bcb11d3 1926void wxPrintPreviewBase::SetZoom(int percent)
2a47d3c1 1927{
7bcb11d3
JS
1928 if (m_currentZoom == percent)
1929 return;
8826f46f 1930
7bcb11d3 1931 m_currentZoom = percent;
88b98787
VS
1932
1933 InvalidatePreviewBitmap();
aff37a19 1934
7bcb11d3
JS
1935 if (m_previewCanvas)
1936 {
d2b354f9 1937 AdjustScrollbars(m_previewCanvas);
95724b1a 1938 ((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
e71fd398 1939 m_previewCanvas->ClearBackground();
7bcb11d3 1940 m_previewCanvas->Refresh();
d2b354f9 1941 m_previewCanvas->SetFocus();
7bcb11d3 1942 }
2a47d3c1
JS
1943}
1944
383f6abd
WS
1945wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
1946{
e81e3883
RR
1947 return m_printDialogData;
1948}
1949
383f6abd 1950int wxPrintPreviewBase::GetZoom() const
e81e3883 1951{ return m_currentZoom; }
383f6abd 1952int wxPrintPreviewBase::GetMaxPage() const
e81e3883 1953{ return m_maxPage; }
383f6abd 1954int wxPrintPreviewBase::GetMinPage() const
e81e3883 1955{ return m_minPage; }
b7cacb43 1956bool wxPrintPreviewBase::IsOk() const
e81e3883 1957{ return m_isOk; }
383f6abd 1958void wxPrintPreviewBase::SetOk(bool ok)
e81e3883 1959{ m_isOk = ok; }
f415cab9 1960
e81e3883
RR
1961//----------------------------------------------------------------------------
1962// wxPrintPreview
1963//----------------------------------------------------------------------------
1964
1965IMPLEMENT_CLASS(wxPrintPreview, wxPrintPreviewBase)
1966
1967wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1968 wxPrintout *printoutForPrinting,
1969 wxPrintDialogData *data) :
1970 wxPrintPreviewBase( printout, printoutForPrinting, data )
1971{
1972 m_pimpl = wxPrintFactory::GetFactory()->
1973 CreatePrintPreview( printout, printoutForPrinting, data );
1974}
1975
1976wxPrintPreview::wxPrintPreview(wxPrintout *printout,
1977 wxPrintout *printoutForPrinting,
1978 wxPrintData *data ) :
1979 wxPrintPreviewBase( printout, printoutForPrinting, data )
1980{
1981 m_pimpl = wxPrintFactory::GetFactory()->
1982 CreatePrintPreview( printout, printoutForPrinting, data );
1983}
1984
1985wxPrintPreview::~wxPrintPreview()
1986{
1987 delete m_pimpl;
383f6abd 1988
e81e3883
RR
1989 // don't delete twice
1990 m_printPrintout = NULL;
1991 m_previewPrintout = NULL;
1992 m_previewBitmap = NULL;
1993}
1994
1995bool wxPrintPreview::SetCurrentPage(int pageNum)
1996{
1997 return m_pimpl->SetCurrentPage( pageNum );
1998}
1999
383f6abd
WS
2000int wxPrintPreview::GetCurrentPage() const
2001{
e81e3883
RR
2002 return m_pimpl->GetCurrentPage();
2003}
2004
383f6abd
WS
2005void wxPrintPreview::SetPrintout(wxPrintout *printout)
2006{
e81e3883
RR
2007 m_pimpl->SetPrintout( printout );
2008}
2009
383f6abd
WS
2010wxPrintout *wxPrintPreview::GetPrintout() const
2011{
e81e3883
RR
2012 return m_pimpl->GetPrintout();
2013}
2014
383f6abd
WS
2015wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
2016{
e81e3883
RR
2017 return m_pimpl->GetPrintoutForPrinting();
2018}
2019
383f6abd
WS
2020void wxPrintPreview::SetFrame(wxFrame *frame)
2021{
e81e3883
RR
2022 m_pimpl->SetFrame( frame );
2023}
2024
383f6abd
WS
2025void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
2026{
e81e3883
RR
2027 m_pimpl->SetCanvas( canvas );
2028}
2029
383f6abd 2030wxFrame *wxPrintPreview::GetFrame() const
e81e3883
RR
2031{
2032 return m_pimpl->GetFrame();
2033}
2034
383f6abd
WS
2035wxPreviewCanvas *wxPrintPreview::GetCanvas() const
2036{
e81e3883
RR
2037 return m_pimpl->GetCanvas();
2038}
2039
2040bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
2041{
2042 return m_pimpl->PaintPage( canvas, dc );
2043}
2044
b88bf073
VS
2045bool wxPrintPreview::UpdatePageRendering()
2046{
2047 return m_pimpl->UpdatePageRendering();
2048}
2049
e81e3883
RR
2050bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
2051{
2052 return m_pimpl->DrawBlankPage( canvas, dc );
2053}
2054
2055void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas *canvas)
2056{
2057 m_pimpl->AdjustScrollbars( canvas );
2058}
2059
2060bool wxPrintPreview::RenderPage(int pageNum)
2061{
2062 return m_pimpl->RenderPage( pageNum );
2063}
2064
2065void wxPrintPreview::SetZoom(int percent)
2066{
2067 m_pimpl->SetZoom( percent );
2068}
2069
d8766675
JS
2070int wxPrintPreview::GetZoom() const
2071{
2072 return m_pimpl->GetZoom();
2073}
2074
e81e3883
RR
2075wxPrintDialogData& wxPrintPreview::GetPrintDialogData()
2076{
2077 return m_pimpl->GetPrintDialogData();
2078}
2079
2080int wxPrintPreview::GetMaxPage() const
2081{
2082 return m_pimpl->GetMaxPage();
2083}
2084
2085int wxPrintPreview::GetMinPage() const
2086{
2087 return m_pimpl->GetMinPage();
2088}
2089
b7cacb43 2090bool wxPrintPreview::IsOk() const
e81e3883
RR
2091{
2092 return m_pimpl->Ok();
2093}
2094
2095void wxPrintPreview::SetOk(bool ok)
2096{
2097 m_pimpl->SetOk( ok );
2098}
2099
2100bool wxPrintPreview::Print(bool interactive)
2101{
2102 return m_pimpl->Print( interactive );
2103}
2104
2105void wxPrintPreview::DetermineScaling()
2106{
2107 m_pimpl->DetermineScaling();
2108}
2109
d427503c 2110#endif // wxUSE_PRINTING_ARCHITECTURE