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"
26 #define __GOOD_COMPILER__
33 #include "wx/msgdlg.h"
34 #include "wx/layout.h"
35 #include "wx/choice.h"
36 #include "wx/button.h"
37 #include "wx/settings.h"
38 #include "wx/dcmemory.h"
39 #include "wx/stattext.h"
43 #include "wx/prntbase.h"
44 #include "wx/dcprint.h"
45 #include "wx/printdlg.h"
54 // Clash with Windows header files
66 #if !USE_SHARED_LIBRARY
67 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
68 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
69 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
70 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
71 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
72 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
74 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
75 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
78 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
79 EVT_PAINT(wxPreviewCanvas::OnPaint
)
80 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
88 wxPrinterBase::wxPrinterBase(wxPrintData
*data
)
90 m_currentPrintout
= (wxPrintout
*) NULL
;
91 sm_abortWindow
= (wxWindow
*) NULL
;
94 m_printData
= (*data
);
97 wxWindow
*wxPrinterBase::sm_abortWindow
= (wxWindow
*) NULL
;
98 bool wxPrinterBase::sm_abortIt
= FALSE
;
100 wxPrinterBase::~wxPrinterBase()
104 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
106 wxPrinterBase::sm_abortIt
= TRUE
;
107 wxPrinterBase::sm_abortWindow
->Show(FALSE
);
108 wxPrinterBase::sm_abortWindow
->Close(TRUE
);
109 wxPrinterBase::sm_abortWindow
= (wxWindow
*) NULL
;
112 wxWindow
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
))
114 wxPrintAbortDialog
*dialog
= new wxPrintAbortDialog(parent
, _("Printing"), wxPoint(0, 0), wxSize(400, 400), wxDEFAULT_DIALOG_STYLE
);
115 (void) new wxStaticText(dialog
, -1, _("Please wait..."), wxPoint(5, 5));
117 wxButton
*button
= new wxButton(dialog
, wxID_CANCEL
, _("Cancel"), wxPoint(5, 30));
120 button
->Centre(wxHORIZONTAL
);
126 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), char *message
)
128 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
135 wxPrintout::wxPrintout(const wxString
& title
)
137 m_printoutTitle
= title
;
138 m_printoutDC
= (wxDC
*) NULL
;
141 m_pageWidthPixels
= 0;
142 m_pageHeightPixels
= 0;
150 wxPrintout::~wxPrintout()
154 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
156 return GetDC()->StartDoc(_("Printing"));
159 void wxPrintout::OnEndDocument()
164 void wxPrintout::OnBeginPrinting()
168 void wxPrintout::OnEndPrinting()
172 bool wxPrintout::HasPage(int page
)
177 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
189 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
190 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
191 wxScrolledWindow(parent
, -1, pos
, size
, style
, name
)
193 m_printPreview
= preview
;
194 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
196 SetScrollbars(40, 40, 100, 100);
199 wxPreviewCanvas::~wxPreviewCanvas()
203 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
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::GetSystemColour(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::OnClose
)
229 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrint
)
230 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPrevious
)
231 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNext
)
232 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoom
)
233 EVT_PAINT(wxPreviewControlBar::OnPaint
)
236 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
237 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
238 long style
, const wxString
& name
):
239 wxPanel(parent
, -1, pos
, size
, style
, name
)
241 m_printPreview
= preview
;
242 m_closeButton
= (wxButton
*) NULL
;
243 m_nextPageButton
= (wxButton
*) NULL
;
244 m_previousPageButton
= (wxButton
*) NULL
;
245 m_printButton
= (wxButton
*) NULL
;
246 m_zoomControl
= (wxChoice
*) NULL
;
247 m_buttonFlags
= buttons
;
250 wxPreviewControlBar::~wxPreviewControlBar()
254 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
260 dc
.SetPen(*wxBLACK_PEN
);
261 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
262 dc
.DrawLine( 0, h
-1, w
, h
-1 );
265 void wxPreviewControlBar::OnClose(wxCommandEvent
& WXUNUSED(event
))
267 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
271 void wxPreviewControlBar::OnPrint(wxCommandEvent
& WXUNUSED(event
))
273 wxPrintPreviewBase
*preview
= GetPrintPreview();
274 preview
->Print(TRUE
);
277 void wxPreviewControlBar::OnNext(wxCommandEvent
& WXUNUSED(event
))
279 wxPrintPreviewBase
*preview
= GetPrintPreview();
282 int currentPage
= preview
->GetCurrentPage();
283 if ((preview
->GetMaxPage() > 0) &&
284 (currentPage
< preview
->GetMaxPage()) &&
285 preview
->GetPrintout()->HasPage(currentPage
+ 1))
287 preview
->SetCurrentPage(currentPage
+ 1);
292 void wxPreviewControlBar::OnPrevious(wxCommandEvent
& WXUNUSED(event
))
294 wxPrintPreviewBase
*preview
= GetPrintPreview();
297 int currentPage
= preview
->GetCurrentPage();
298 if ((preview
->GetMinPage() > 0) &&
299 (currentPage
> preview
->GetMinPage()) &&
300 preview
->GetPrintout()->HasPage(currentPage
- 1))
302 preview
->SetCurrentPage(currentPage
- 1);
307 void wxPreviewControlBar::OnZoom(wxCommandEvent
& WXUNUSED(event
))
309 int zoom
= GetZoomControl();
310 if (GetPrintPreview())
311 GetPrintPreview()->SetZoom(zoom
);
314 void wxPreviewControlBar::CreateButtons()
316 #ifdef __GOOD_COMPILER__ // Robert Roebling
318 SetSize(0, 0, 400, 40);
326 wxFont
buttonFont(fontSize
, wxSWISS
, wxNORMAL
, wxBOLD
);
329 int buttonWidth
= 65;
330 int buttonHeight
= 24;
336 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("Close"),
337 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
339 x
+= gap
+ buttonWidth
;
341 if (m_buttonFlags
& wxPREVIEW_PRINT
)
343 m_printButton
= new wxButton(this, wxID_PREVIEW_PRINT
, _("Print..."), wxPoint(x
, y
),
344 wxSize(buttonWidth
, buttonHeight
));
345 x
+= gap
+ buttonWidth
;
348 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
350 m_previousPageButton
= new wxButton(this, wxID_PREVIEW_PREVIOUS
, "<<", wxPoint(x
, y
),
351 wxSize(buttonWidth
, buttonHeight
));
352 x
+= gap
+ buttonWidth
;
355 if (m_buttonFlags
& wxPREVIEW_NEXT
)
357 m_nextPageButton
= new wxButton(this, wxID_PREVIEW_NEXT
, ">>",
358 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
359 x
+= gap
+ buttonWidth
;
362 // Can't be static because gcc bails out
363 wxString choices
[] = { "10%", "20%", "25%", "30%", "35%", "40%", "45%", "50%", "55%", "60%",
364 "65%", "70%", "75%", "80%", "85%", "90%", "95%", "100%", "110%", "120%", "150%", "200%" };
366 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
368 m_zoomControl
= new wxChoice(this, wxID_PREVIEW_ZOOM
, wxPoint(x
, y
),
369 wxSize(100, -1), n
, (wxString
*)choices
);
370 SetZoomControl(m_printPreview
->GetZoom());
373 m_closeButton
->SetDefault();
378 void wxPreviewControlBar::SetZoomControl(int zoom
)
380 #ifdef __GOOD_COMPILER__ // Robert Roebling
382 sprintf(buf
, "%d%%", zoom
);
384 m_zoomControl
->SetStringSelection(buf
);
388 int wxPreviewControlBar::GetZoomControl()
390 #ifdef __GOOD_COMPILER__ // Robert Roebling
392 if (m_zoomControl
&& m_zoomControl
->GetStringSelection())
394 strcpy(buf
, m_zoomControl
->GetStringSelection());
395 buf
[strlen(buf
) - 1] = 0;
396 return (int)atoi(buf
);
409 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxFrame
*parent
, const wxString
& title
,
410 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
411 wxFrame(parent
, -1, title
, pos
, size
, style
, name
)
413 #ifdef __GOOD_COMPILER__ // Robert Roebling
414 m_printPreview
= preview
;
416 m_previewCanvas
= NULL
;
420 wxPreviewFrame::~wxPreviewFrame()
424 bool wxPreviewFrame::OnClose()
426 #ifdef __GOOD_COMPILER__ // Robert Roebling
430 // Need to delete the printout and the print preview
431 wxPrintout
*printout
= m_printPreview
->GetPrintout();
435 m_printPreview
->SetPrintout(NULL
);
436 m_printPreview
->SetCanvas(NULL
);
437 m_printPreview
->SetFrame(NULL
);
439 delete m_printPreview
;
446 void wxPreviewFrame::Initialize()
449 #ifdef __GOOD_COMPILER__ // Robert Roebling
456 m_printPreview
->SetCanvas(m_previewCanvas
);
457 m_printPreview
->SetFrame(this);
459 // Set layout constraints here
461 // Control bar constraints
462 wxLayoutConstraints
*c1
= new wxLayoutConstraints
;
464 // m_controlBar->GetSize(&w, &h);
472 c1
->left
.SameAs (this, wxLeft
);
473 c1
->top
.SameAs (this, wxTop
);
474 c1
->right
.SameAs (this, wxRight
);
475 c1
->height
.Absolute (h
);
477 m_controlBar
->SetConstraints(c1
);
479 // Canvas constraints
480 wxLayoutConstraints
*c2
= new wxLayoutConstraints
;
482 c2
->left
.SameAs (this, wxLeft
);
483 c2
->top
.Below (m_controlBar
);
484 c2
->right
.SameAs (this, wxRight
);
485 c2
->bottom
.SameAs (this, wxBottom
);
487 m_previewCanvas
->SetConstraints(c2
);
498 void wxPreviewFrame::CreateCanvas()
500 #ifdef __GOOD_COMPILER__ // Robert Roebling
502 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
507 void wxPreviewFrame::CreateControlBar()
509 #ifdef __GOOD_COMPILER__ // Robert Roebling
511 long buttons
= wxPREVIEW_DEFAULT
;
512 if (m_printPreview
->GetPrintoutForPrinting())
513 buttons
|= wxPREVIEW_PRINT
;
515 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this, wxPoint(0, 0), wxSize(400, 40));
516 m_controlBar
->CreateButtons();
524 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
, wxPrintout
*printoutForPrinting
, wxPrintData
*data
)
527 #ifdef __GOOD_COMPILER__ // Robert Roebling
530 m_previewPrintout
= printout
;
531 if (m_previewPrintout
)
532 m_previewPrintout
->SetIsPreview(TRUE
);
534 m_printPrintout
= printoutForPrinting
;
536 m_printData
= (*data
);
538 m_previewCanvas
= NULL
;
539 m_previewFrame
= NULL
;
540 m_previewBitmap
= NULL
;
548 printout
->OnPreparePrinting();
550 // Get some parameters from the printout, if defined
552 printout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
557 wxPrintPreviewBase::~wxPrintPreviewBase()
559 #ifdef __GOOD_COMPILER__ // Robert Roebling
561 if (m_previewPrintout
)
562 delete m_previewPrintout
;
564 delete m_previewBitmap
;
566 delete m_printPrintout
;
571 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
573 #ifdef __GOOD_COMPILER__ // Robert Roebling
574 if (m_currentPage
== pageNum
)
577 m_currentPage
= pageNum
;
580 delete m_previewBitmap
;
581 m_previewBitmap
= NULL
;
587 m_previewCanvas
->Refresh();
594 bool wxPrintPreviewBase::PaintPage(wxWindow
*canvas
, wxDC
& dc
)
597 #ifdef __GOOD_COMPILER__ // Robert Roebling
599 DrawBlankPage(canvas
, dc
);
601 if (!m_previewBitmap
)
602 RenderPage(m_currentPage
);
604 if (!m_previewBitmap
)
610 int canvasWidth
, canvasHeight
;
611 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
613 double zoomScale
= ((float)m_currentZoom
/(float)100);
614 double actualWidth
= (zoomScale
*m_pageWidth
*m_previewScale
);
615 // float actualHeight = (float)(zoomScale*m_pageHeight*m_previewScale);
617 int x
= (int) ((canvasWidth
- actualWidth
)/2.0);
618 if (x
< m_leftMargin
)
623 temp_dc
.SelectObject(*m_previewBitmap
);
625 dc
.Blit(x
, y
, m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
627 temp_dc
.SelectObject(wxNullBitmap
);
634 bool wxPrintPreviewBase::RenderPage(int pageNum
)
636 int canvasWidth
, canvasHeight
;
638 #ifdef __GOOD_COMPILER__ // Robert Roebling
640 if (!m_previewCanvas
)
642 wxMessageBox(_("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"),
643 _("Print Preview Failure"), wxOK
);
646 m_previewCanvas
->GetSize(&canvasWidth
, &canvasHeight
);
648 double zoomScale
= (m_currentZoom
/100.0);
649 int actualWidth
= (int)(zoomScale
*m_pageWidth
*m_previewScale
);
650 int actualHeight
= (int)(zoomScale
*m_pageHeight
*m_previewScale
);
652 int x
= (int)((canvasWidth
- actualWidth
)/2.0);
653 if (x
< m_leftMargin
)
655 // int y = m_topMargin;
658 if (!m_previewBitmap
)
660 m_previewBitmap
= new wxBitmap((int)actualWidth
, (int)actualHeight
);
661 if (!m_previewBitmap
|| !m_previewBitmap
->Ok())
664 delete m_previewBitmap
;
665 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
671 memoryDC
.SelectObject(*m_previewBitmap
);
675 m_previewPrintout
->SetDC(&memoryDC
);
676 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
678 m_previewPrintout
->OnBeginPrinting();
681 if (!m_previewPrintout
->OnBeginDocument(m_printData
.GetFromPage(), m_printData
.GetToPage()))
683 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
685 memoryDC
.SelectObject(wxNullBitmap
);
687 delete m_previewBitmap
;
691 m_previewPrintout
->OnPrintPage(pageNum
);
692 m_previewPrintout
->OnEndDocument();
693 m_previewPrintout
->OnEndPrinting();
695 m_previewPrintout
->SetDC(NULL
);
697 memoryDC
.SelectObject(wxNullBitmap
);
702 sprintf(buf
, _("Page %d of %d"), pageNum
, m_maxPage
);
704 sprintf(buf
, _("Page %d"), pageNum
);
707 m_previewFrame
->SetStatusText(buf
);
713 bool wxPrintPreviewBase::DrawBlankPage(wxWindow
*canvas
, wxDC
& dc
)
716 #ifdef __GOOD_COMPILER__ // Robert Roebling
718 int canvasWidth
, canvasHeight
;
719 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
721 float zoomScale
= (float)((float)m_currentZoom
/(float)100);
722 float actualWidth
= zoomScale
*m_pageWidth
*m_previewScale
;
723 float actualHeight
= zoomScale
*m_pageHeight
*m_previewScale
;
725 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
726 if (x
< m_leftMargin
)
727 x
= (float)m_leftMargin
;
728 float y
= (float)m_topMargin
;
730 // Draw shadow, allowing for 1-pixel border AROUND the actual page
731 int shadowOffset
= 4;
732 dc
.SetPen(*wxBLACK_PEN
);
733 dc
.SetBrush(*wxBLACK_BRUSH
);
734 dc
.DrawRectangle((int)(x
-1 + shadowOffset
), (int)(y
-1 + shadowOffset
), (int)(actualWidth
+2), (int)(actualHeight
+2));
736 // Draw blank page allowing for 1-pixel border AROUND the actual page
737 dc
.SetPen(*wxBLACK_PEN
);
738 dc
.SetBrush(*wxWHITE_BRUSH
);
741 dc
.DrawRectangle((int)(x
-1), (int)(y
-1), (int)(actualWidth
+2), (int)(actualHeight
+2));
748 void wxPrintPreviewBase::SetZoom(int percent
)
750 #ifdef __GOOD_COMPILER__ // Robert Roebling
751 if (m_currentZoom
== percent
)
754 m_currentZoom
= percent
;
757 delete m_previewBitmap
;
758 m_previewBitmap
= NULL
;
760 RenderPage(m_currentPage
);
764 m_previewCanvas
->Clear();
765 m_previewCanvas
->Refresh();