1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Printing framework base class implementation
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "prntbase.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #if wxUSE_PRINTING_ARCHITECTURE
31 #include "wx/msgdlg.h"
32 #include "wx/layout.h"
33 #include "wx/choice.h"
34 #include "wx/button.h"
35 #include "wx/settings.h"
36 #include "wx/dcmemory.h"
37 #include "wx/stattext.h"
41 #include "wx/prntbase.h"
42 #include "wx/dcprint.h"
43 #include "wx/printdlg.h"
44 #include "wx/module.h"
50 #include "wx/msw/private.h"
58 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
59 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
60 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
61 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
62 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
63 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
65 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
66 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
69 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
70 EVT_PAINT(wxPreviewCanvas::OnPaint
)
71 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
78 wxPrinterBase::wxPrinterBase(wxPrintDialogData
*data
)
80 m_currentPrintout
= (wxPrintout
*) NULL
;
81 sm_abortWindow
= (wxWindow
*) NULL
;
84 m_printDialogData
= (*data
);
85 sm_lastError
= wxPRINTER_NO_ERROR
;
88 wxWindow
*wxPrinterBase::sm_abortWindow
= (wxWindow
*) NULL
;
89 bool wxPrinterBase::sm_abortIt
= FALSE
;
90 wxPrinterError
wxPrinterBase::sm_lastError
= wxPRINTER_NO_ERROR
;
92 wxPrinterBase::~wxPrinterBase()
96 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
98 wxPrinterBase::sm_abortIt
= TRUE
;
99 wxPrinterBase::sm_abortWindow
->Show(FALSE
);
100 wxPrinterBase::sm_abortWindow
->Close(TRUE
);
101 wxPrinterBase::sm_abortWindow
= (wxWindow
*) NULL
;
104 wxWindow
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
))
106 wxPrintAbortDialog
*dialog
= new wxPrintAbortDialog(parent
, _("Printing"), wxPoint(0, 0), wxSize(400, 400), wxDEFAULT_DIALOG_STYLE
);
107 (void) new wxStaticText(dialog
, -1, _("Please wait..."), wxPoint(5, 5));
109 wxButton
*button
= new wxButton(dialog
, wxID_CANCEL
, _("Cancel"), wxPoint(5, 30));
112 button
->Centre(wxHORIZONTAL
);
118 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), const wxString
& message
)
120 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
127 wxPrintout::wxPrintout(const wxString
& title
)
129 m_printoutTitle
= title
;
130 m_printoutDC
= (wxDC
*) NULL
;
133 m_pageWidthPixels
= 0;
134 m_pageHeightPixels
= 0;
142 wxPrintout::~wxPrintout()
146 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
148 return GetDC()->StartDoc(_("Printing"));
151 void wxPrintout::OnEndDocument()
156 void wxPrintout::OnBeginPrinting()
160 void wxPrintout::OnEndPrinting()
164 bool wxPrintout::HasPage(int page
)
169 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
181 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
182 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
183 wxScrolledWindow(parent
, -1, pos
, size
, style
, name
)
185 m_printPreview
= preview
;
186 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
188 SetScrollbars(15, 18, 100, 100);
191 wxPreviewCanvas::~wxPreviewCanvas()
195 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
202 if (!GetUpdateRegion().IsEmpty())
203 dc.SetClippingRegion( GetUpdateRegion() );
209 m_printPreview
->PaintPage(this, dc
);
213 // Responds to colour changes, and passes event on to children.
214 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
216 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
219 // Propagate the event to the non-top-level children
220 wxWindow::OnSysColourChanged(event
);
224 * Preview control bar
227 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
228 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
229 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrint
)
230 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
231 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
232 EVT_CHAR(wxPreviewControlBar::OnChar
)
233 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoom
)
234 EVT_PAINT(wxPreviewControlBar::OnPaint
)
237 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
238 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
239 long style
, const wxString
& name
):
240 wxPanel(parent
, -1, pos
, size
, style
, name
)
242 m_printPreview
= preview
;
243 m_closeButton
= (wxButton
*) NULL
;
244 m_nextPageButton
= (wxButton
*) NULL
;
245 m_previousPageButton
= (wxButton
*) NULL
;
246 m_printButton
= (wxButton
*) NULL
;
247 m_zoomControl
= (wxChoice
*) NULL
;
248 m_buttonFlags
= buttons
;
251 wxPreviewControlBar::~wxPreviewControlBar()
255 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
261 dc
.SetPen(*wxBLACK_PEN
);
262 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
263 dc
.DrawLine( 0, h
-1, w
, h
-1 );
266 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
268 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
272 void wxPreviewControlBar::OnPrint(wxCommandEvent
& WXUNUSED(event
))
274 wxPrintPreviewBase
*preview
= GetPrintPreview();
275 preview
->Print(TRUE
);
278 void wxPreviewControlBar::OnChar(wxKeyEvent
&event
)
280 switch(event
.KeyCode())
291 void wxPreviewControlBar::OnNext(void)
293 wxPrintPreviewBase
*preview
= GetPrintPreview();
296 int currentPage
= preview
->GetCurrentPage();
297 if ((preview
->GetMaxPage() > 0) &&
298 (currentPage
< preview
->GetMaxPage()) &&
299 preview
->GetPrintout()->HasPage(currentPage
+ 1))
301 preview
->SetCurrentPage(currentPage
+ 1);
306 void wxPreviewControlBar::OnPrevious(void)
308 wxPrintPreviewBase
*preview
= GetPrintPreview();
311 int currentPage
= preview
->GetCurrentPage();
312 if ((preview
->GetMinPage() > 0) &&
313 (currentPage
> preview
->GetMinPage()) &&
314 preview
->GetPrintout()->HasPage(currentPage
- 1))
316 preview
->SetCurrentPage(currentPage
- 1);
321 void wxPreviewControlBar::OnZoom(wxCommandEvent
& WXUNUSED(event
))
323 int zoom
= GetZoomControl();
324 if (GetPrintPreview())
325 GetPrintPreview()->SetZoom(zoom
);
328 void wxPreviewControlBar::CreateButtons()
330 SetSize(0, 0, 400, 40);
339 wxFont buttonFont(fontSize, wxSWISS, wxNORMAL, wxBOLD);
343 int buttonWidth
= 65;
345 int buttonHeight
= -1;
347 int buttonHeight
= 24;
359 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("Close"),
360 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
362 x
+= gap
+ buttonWidth
;
364 if (m_buttonFlags
& wxPREVIEW_PRINT
)
366 m_printButton
= new wxButton(this, wxID_PREVIEW_PRINT
, _("Print..."), wxPoint(x
, y
),
367 wxSize(buttonWidth
, buttonHeight
));
368 x
+= gap
+ buttonWidth
;
371 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
373 m_previousPageButton
= new wxButton(this, wxID_PREVIEW_PREVIOUS
, wxT("<<"), wxPoint(x
, y
),
374 wxSize(buttonWidth
, buttonHeight
));
375 x
+= gap
+ buttonWidth
;
378 if (m_buttonFlags
& wxPREVIEW_NEXT
)
380 m_nextPageButton
= new wxButton(this, wxID_PREVIEW_NEXT
, wxT(">>"),
381 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
382 x
+= gap
+ buttonWidth
;
385 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
387 static const char *choices
[] =
389 "10%", "15%", "20%", "25%", "30%", "35%", "40%", "45%", "50%", "55%",
390 "60%", "65%", "70%", "75%", "80%", "85%", "90%", "95%", "100%", "110%",
391 "120%", "150%", "200%"
394 int n
= WXSIZEOF(choices
);
396 wxString
* strings
= new wxString
[n
];
398 for (i
= 0; i
< n
; i
++ )
399 strings
[i
] = choices
[i
];
401 m_zoomControl
= new wxChoice(this, wxID_PREVIEW_ZOOM
,
409 SetZoomControl(m_printPreview
->GetZoom());
412 // m_closeButton->SetDefault();
415 void wxPreviewControlBar::SetZoomControl(int zoom
)
418 sprintf(buf
, "%d%%", zoom
);
419 // Someone is calling methods that do no exist in wxChoice!! So I'll just comment out for VA for now
421 m_zoomControl
->SetStringSelection(buf
);
424 int wxPreviewControlBar::GetZoomControl()
427 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxT("")))
429 wxStrcpy(buf
, m_zoomControl
->GetStringSelection());
430 buf
[wxStrlen(buf
) - 1] = 0;
431 return (int)wxAtoi(buf
);
441 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
442 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
445 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxFrame
*parent
, const wxString
& title
,
446 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
447 wxFrame(parent
, -1, title
, pos
, size
, style
, name
)
449 m_printPreview
= preview
;
451 m_previewCanvas
= NULL
;
454 wxPreviewFrame::~wxPreviewFrame()
458 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
462 // Need to delete the printout and the print preview
463 wxPrintout
*printout
= m_printPreview
->GetPrintout();
467 m_printPreview
->SetPrintout(NULL
);
468 m_printPreview
->SetCanvas(NULL
);
469 m_printPreview
->SetFrame(NULL
);
471 delete m_printPreview
;
476 void wxPreviewFrame::Initialize()
483 m_printPreview
->SetCanvas(m_previewCanvas
);
484 m_printPreview
->SetFrame(this);
486 // Set layout constraints here
488 // Control bar constraints
489 wxLayoutConstraints
*c1
= new wxLayoutConstraints
;
491 // m_controlBar->GetSize(&w, &h);
493 #if (defined(__WXMSW__) || defined(__WXGTK__))
499 c1
->left
.SameAs (this, wxLeft
);
500 c1
->top
.SameAs (this, wxTop
);
501 c1
->right
.SameAs (this, wxRight
);
502 c1
->height
.Absolute (h
);
504 m_controlBar
->SetConstraints(c1
);
506 // Canvas constraints
507 wxLayoutConstraints
*c2
= new wxLayoutConstraints
;
509 c2
->left
.SameAs (this, wxLeft
);
510 c2
->top
.Below (m_controlBar
);
511 c2
->right
.SameAs (this, wxRight
);
512 c2
->bottom
.SameAs (this, wxBottom
);
514 m_previewCanvas
->SetConstraints(c2
);
523 void wxPreviewFrame::CreateCanvas()
525 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
528 void wxPreviewFrame::CreateControlBar()
530 long buttons
= wxPREVIEW_DEFAULT
;
531 if (m_printPreview
->GetPrintoutForPrinting())
532 buttons
|= wxPREVIEW_PRINT
;
534 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this, wxPoint(0, 0), wxSize(400, 40));
535 m_controlBar
->CreateButtons();
542 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
543 wxPrintout
*printoutForPrinting
,
547 m_printDialogData
= (*data
);
549 Init(printout
, printoutForPrinting
);
552 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
553 wxPrintout
*printoutForPrinting
,
554 wxPrintDialogData
*data
)
557 m_printDialogData
= (*data
);
559 Init(printout
, printoutForPrinting
);
562 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
563 wxPrintout
*printoutForPrinting
)
566 m_previewPrintout
= printout
;
567 if (m_previewPrintout
)
568 m_previewPrintout
->SetIsPreview(TRUE
);
570 m_printPrintout
= printoutForPrinting
;
572 m_previewCanvas
= NULL
;
573 m_previewFrame
= NULL
;
574 m_previewBitmap
= NULL
;
581 m_printingPrepared
= FALSE
;
583 // Too soon! Moved to RenderPage.
584 // printout->OnPreparePrinting();
586 // Get some parameters from the printout, if defined
588 printout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
591 wxPrintPreviewBase::~wxPrintPreviewBase()
593 if (m_previewPrintout
)
594 delete m_previewPrintout
;
596 delete m_previewBitmap
;
598 delete m_printPrintout
;
601 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
603 if (m_currentPage
== pageNum
)
606 m_currentPage
= pageNum
;
609 delete m_previewBitmap
;
610 m_previewBitmap
= NULL
;
615 if (!RenderPage(pageNum
))
617 m_previewCanvas
->Refresh();
622 bool wxPrintPreviewBase::PaintPage(wxWindow
*canvas
, wxDC
& dc
)
624 DrawBlankPage(canvas
, dc
);
626 if (!m_previewBitmap
)
627 if (!RenderPage(m_currentPage
))
630 if (!m_previewBitmap
)
636 int canvasWidth
, canvasHeight
;
637 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
639 double zoomScale
= ((float)m_currentZoom
/(float)100);
640 double actualWidth
= (zoomScale
*m_pageWidth
*m_previewScale
);
641 // float actualHeight = (float)(zoomScale*m_pageHeight*m_previewScale);
643 int x
= (int) ((canvasWidth
- actualWidth
)/2.0);
644 if (x
< m_leftMargin
)
649 temp_dc
.SelectObject(*m_previewBitmap
);
651 dc
.Blit(x
, y
, m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
653 temp_dc
.SelectObject(wxNullBitmap
);
658 bool wxPrintPreviewBase::RenderPage(int pageNum
)
662 int canvasWidth
, canvasHeight
;
664 if (!m_previewCanvas
)
666 wxFAIL_MSG(_T("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
670 m_previewCanvas
->GetSize(&canvasWidth
, &canvasHeight
);
672 double zoomScale
= (m_currentZoom
/100.0);
673 int actualWidth
= (int)(zoomScale
*m_pageWidth
*m_previewScale
);
674 int actualHeight
= (int)(zoomScale
*m_pageHeight
*m_previewScale
);
676 int x
= (int)((canvasWidth
- actualWidth
)/2.0);
677 if (x
< m_leftMargin
)
679 // int y = m_topMargin;
682 if (!m_previewBitmap
)
684 m_previewBitmap
= new wxBitmap((int)actualWidth
, (int)actualHeight
);
685 if (!m_previewBitmap
|| !m_previewBitmap
->Ok())
687 if (m_previewBitmap
) {
688 delete m_previewBitmap
;
689 m_previewBitmap
= NULL
;
691 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
697 memoryDC
.SelectObject(*m_previewBitmap
);
701 m_previewPrintout
->SetDC(&memoryDC
);
702 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
704 // Need to delay OnPreparePrinting until here, so we have enough information.
705 if (!m_printingPrepared
)
707 m_previewPrintout
->OnPreparePrinting();
708 m_printingPrepared
= TRUE
;
711 m_previewPrintout
->OnBeginPrinting();
713 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
715 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
717 memoryDC
.SelectObject(wxNullBitmap
);
719 delete m_previewBitmap
;
720 m_previewBitmap
= NULL
;
724 m_previewPrintout
->OnPrintPage(pageNum
);
725 m_previewPrintout
->OnEndDocument();
726 m_previewPrintout
->OnEndPrinting();
728 m_previewPrintout
->SetDC(NULL
);
730 memoryDC
.SelectObject(wxNullBitmap
);
734 wxSprintf(buf
, _("Page %d of %d"), pageNum
, m_maxPage
);
736 wxSprintf(buf
, _("Page %d"), pageNum
);
739 m_previewFrame
->SetStatusText(buf
);
745 bool wxPrintPreviewBase::DrawBlankPage(wxWindow
*canvas
, wxDC
& dc
)
747 int canvasWidth
, canvasHeight
;
748 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
750 float zoomScale
= (float)((float)m_currentZoom
/(float)100);
751 float actualWidth
= zoomScale
*m_pageWidth
*m_previewScale
;
752 float actualHeight
= zoomScale
*m_pageHeight
*m_previewScale
;
754 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
755 if (x
< m_leftMargin
)
756 x
= (float)m_leftMargin
;
757 float y
= (float)m_topMargin
;
759 // Draw shadow, allowing for 1-pixel border AROUND the actual page
760 int shadowOffset
= 4;
761 dc
.SetPen(*wxBLACK_PEN
);
762 dc
.SetBrush(*wxBLACK_BRUSH
);
764 dc.DrawRectangle((int)(x-1 + shadowOffset), (int)(y-1 + shadowOffset), (int)(actualWidth+2), (int)(actualHeight+2));
766 dc
.DrawRectangle((int)(x
+ shadowOffset
), (int)(y
+ actualHeight
+1), (int)(actualWidth
), shadowOffset
);
767 dc
.DrawRectangle((int)(x
+ actualWidth
), (int)(y
+ shadowOffset
), shadowOffset
, (int)(actualHeight
));
769 // Draw blank page allowing for 1-pixel border AROUND the actual page
770 dc
.SetPen(*wxBLACK_PEN
);
771 dc
.SetBrush(*wxWHITE_BRUSH
);
774 wxRegion update_region = canvas->GetUpdateRegion();
775 wxRect r = update_region.GetBox();
777 printf( "x: %d y: %d w: %d h: %d.\n", (int)r.x, (int)r.y, (int)r.width, (int)r.height );
780 dc
.DrawRectangle((int)(x
-2), (int)(y
-1), (int)(actualWidth
+3), (int)(actualHeight
+2));
785 void wxPrintPreviewBase::SetZoom(int percent
)
787 if (m_currentZoom
== percent
)
790 m_currentZoom
= percent
;
793 delete m_previewBitmap
;
794 m_previewBitmap
= NULL
;
799 RenderPage(m_currentPage
);
800 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
801 m_previewCanvas
->Clear();
802 m_previewCanvas
->Refresh();
806 #endif // wxUSE_PRINTING_ARCHITECTURE