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"
52 #include "wx/msw/private.h"
60 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
61 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
62 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
63 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
64 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
65 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
67 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
68 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
71 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
72 EVT_PAINT(wxPreviewCanvas::OnPaint
)
73 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
80 wxPrinterBase::wxPrinterBase(wxPrintDialogData
*data
)
82 m_currentPrintout
= (wxPrintout
*) NULL
;
83 sm_abortWindow
= (wxWindow
*) NULL
;
86 m_printDialogData
= (*data
);
87 sm_lastError
= wxPRINTER_NO_ERROR
;
90 wxWindow
*wxPrinterBase::sm_abortWindow
= (wxWindow
*) NULL
;
91 bool wxPrinterBase::sm_abortIt
= FALSE
;
92 wxPrinterError
wxPrinterBase::sm_lastError
= wxPRINTER_NO_ERROR
;
94 wxPrinterBase::~wxPrinterBase()
98 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
100 wxPrinterBase::sm_abortIt
= TRUE
;
101 wxPrinterBase::sm_abortWindow
->Show(FALSE
);
102 wxPrinterBase::sm_abortWindow
->Close(TRUE
);
103 wxPrinterBase::sm_abortWindow
= (wxWindow
*) NULL
;
106 wxWindow
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
* printout
)
108 wxPrintAbortDialog
*dialog
= new wxPrintAbortDialog(parent
, _("Printing ") , wxDefaultPosition
, wxDefaultSize
, wxDEFAULT_DIALOG_STYLE
);
110 wxBoxSizer
*button_sizer
= new wxBoxSizer( wxVERTICAL
);
111 button_sizer
->Add( new wxStaticText(dialog
, -1, _("Please wait while printing\n") + printout
->GetTitle() ), 0, wxALL
, 10 );
112 button_sizer
->Add( new wxButton( dialog
, wxID_CANCEL
, wxT("Cancel") ), 0, wxALL
| wxALIGN_CENTER
, 10 );
114 dialog
->SetAutoLayout( TRUE
);
115 dialog
->SetSizer( button_sizer
);
117 button_sizer
->Fit(dialog
);
118 button_sizer
->SetSizeHints (dialog
) ;
123 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), const wxString
& message
)
125 wxMessageBox(message
, _("Printing Error"), wxOK
, parent
);
132 wxPrintout::wxPrintout(const wxString
& title
)
134 m_printoutTitle
= title
;
135 m_printoutDC
= (wxDC
*) NULL
;
138 m_pageWidthPixels
= 0;
139 m_pageHeightPixels
= 0;
147 wxPrintout::~wxPrintout()
151 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
153 return GetDC()->StartDoc(_("Printing ") + m_printoutTitle
);
156 void wxPrintout::OnEndDocument()
161 void wxPrintout::OnBeginPrinting()
165 void wxPrintout::OnEndPrinting()
169 bool wxPrintout::HasPage(int page
)
174 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
186 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
187 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
188 wxScrolledWindow(parent
, -1, pos
, size
, style
, name
)
190 m_printPreview
= preview
;
191 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
193 SetScrollbars(15, 18, 100, 100);
196 wxPreviewCanvas::~wxPreviewCanvas()
200 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
207 if (!GetUpdateRegion().IsEmpty())
208 dc.SetClippingRegion( GetUpdateRegion() );
214 m_printPreview
->PaintPage(this, dc
);
218 // Responds to colour changes, and passes event on to children.
219 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
221 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
224 // Propagate the event to the non-top-level children
225 wxWindow::OnSysColourChanged(event
);
229 * Preview control bar
232 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
233 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnWindowClose
)
234 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrint
)
235 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPreviousButton
)
236 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNextButton
)
237 EVT_CHAR(wxPreviewControlBar::OnChar
)
238 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoom
)
239 EVT_PAINT(wxPreviewControlBar::OnPaint
)
242 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
243 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
244 long style
, const wxString
& name
):
245 wxPanel(parent
, -1, pos
, size
, style
, name
)
247 m_printPreview
= preview
;
248 m_closeButton
= (wxButton
*) NULL
;
249 m_nextPageButton
= (wxButton
*) NULL
;
250 m_previousPageButton
= (wxButton
*) NULL
;
251 m_printButton
= (wxButton
*) NULL
;
252 m_zoomControl
= (wxChoice
*) NULL
;
253 m_buttonFlags
= buttons
;
256 wxPreviewControlBar::~wxPreviewControlBar()
260 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
266 dc
.SetPen(*wxBLACK_PEN
);
267 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
268 dc
.DrawLine( 0, h
-1, w
, h
-1 );
271 void wxPreviewControlBar::OnWindowClose(wxCommandEvent
& WXUNUSED(event
))
273 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
277 void wxPreviewControlBar::OnPrint(wxCommandEvent
& WXUNUSED(event
))
279 wxPrintPreviewBase
*preview
= GetPrintPreview();
280 preview
->Print(TRUE
);
283 void wxPreviewControlBar::OnChar(wxKeyEvent
&event
)
285 switch(event
.KeyCode())
296 void wxPreviewControlBar::OnNext(void)
298 wxPrintPreviewBase
*preview
= GetPrintPreview();
301 int currentPage
= preview
->GetCurrentPage();
302 if ((preview
->GetMaxPage() > 0) &&
303 (currentPage
< preview
->GetMaxPage()) &&
304 preview
->GetPrintout()->HasPage(currentPage
+ 1))
306 preview
->SetCurrentPage(currentPage
+ 1);
311 void wxPreviewControlBar::OnPrevious(void)
313 wxPrintPreviewBase
*preview
= GetPrintPreview();
316 int currentPage
= preview
->GetCurrentPage();
317 if ((preview
->GetMinPage() > 0) &&
318 (currentPage
> preview
->GetMinPage()) &&
319 preview
->GetPrintout()->HasPage(currentPage
- 1))
321 preview
->SetCurrentPage(currentPage
- 1);
326 void wxPreviewControlBar::OnZoom(wxCommandEvent
& WXUNUSED(event
))
328 int zoom
= GetZoomControl();
329 if (GetPrintPreview())
330 GetPrintPreview()->SetZoom(zoom
);
333 void wxPreviewControlBar::CreateButtons()
335 SetSize(0, 0, 400, 40);
344 wxFont buttonFont(fontSize, wxSWISS, wxNORMAL, wxBOLD);
348 int buttonWidth
= 65;
350 int buttonHeight
= -1;
352 int buttonHeight
= 24;
364 m_closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, _("Close"),
365 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
367 x
+= gap
+ buttonWidth
;
369 if (m_buttonFlags
& wxPREVIEW_PRINT
)
371 m_printButton
= new wxButton(this, wxID_PREVIEW_PRINT
, _("Print..."), wxPoint(x
, y
),
372 wxSize(buttonWidth
, buttonHeight
));
373 x
+= gap
+ buttonWidth
;
376 if (m_buttonFlags
& wxPREVIEW_PREVIOUS
)
378 m_previousPageButton
= new wxButton(this, wxID_PREVIEW_PREVIOUS
, wxT("<<"), wxPoint(x
, y
),
379 wxSize(buttonWidth
, buttonHeight
));
380 x
+= gap
+ buttonWidth
;
383 if (m_buttonFlags
& wxPREVIEW_NEXT
)
385 m_nextPageButton
= new wxButton(this, wxID_PREVIEW_NEXT
, wxT(">>"),
386 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
387 x
+= gap
+ buttonWidth
;
390 if (m_buttonFlags
& wxPREVIEW_ZOOM
)
392 static const char *choices
[] =
394 "10%", "15%", "20%", "25%", "30%", "35%", "40%", "45%", "50%", "55%",
395 "60%", "65%", "70%", "75%", "80%", "85%", "90%", "95%", "100%", "110%",
396 "120%", "150%", "200%"
399 int n
= WXSIZEOF(choices
);
401 wxString
* strings
= new wxString
[n
];
403 for (i
= 0; i
< n
; i
++ )
404 strings
[i
] = choices
[i
];
406 m_zoomControl
= new wxChoice(this, wxID_PREVIEW_ZOOM
,
414 SetZoomControl(m_printPreview
->GetZoom());
417 // m_closeButton->SetDefault();
420 void wxPreviewControlBar::SetZoomControl(int zoom
)
423 sprintf(buf
, "%d%%", zoom
);
424 // Someone is calling methods that do no exist in wxChoice!! So I'll just comment out for VA for now
426 m_zoomControl
->SetStringSelection(buf
);
429 int wxPreviewControlBar::GetZoomControl()
432 if (m_zoomControl
&& (m_zoomControl
->GetStringSelection() != wxT("")))
434 wxStrcpy(buf
, m_zoomControl
->GetStringSelection());
435 buf
[wxStrlen(buf
) - 1] = 0;
436 return (int)wxAtoi(buf
);
446 BEGIN_EVENT_TABLE(wxPreviewFrame
, wxFrame
)
447 EVT_CLOSE(wxPreviewFrame::OnCloseWindow
)
450 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxFrame
*parent
, const wxString
& title
,
451 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
452 wxFrame(parent
, -1, title
, pos
, size
, style
, name
)
454 m_printPreview
= preview
;
456 m_previewCanvas
= NULL
;
459 wxPreviewFrame::~wxPreviewFrame()
463 void wxPreviewFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
467 // Need to delete the printout and the print preview
468 wxPrintout
*printout
= m_printPreview
->GetPrintout();
472 m_printPreview
->SetPrintout(NULL
);
473 m_printPreview
->SetCanvas(NULL
);
474 m_printPreview
->SetFrame(NULL
);
476 delete m_printPreview
;
481 void wxPreviewFrame::Initialize()
488 m_printPreview
->SetCanvas(m_previewCanvas
);
489 m_printPreview
->SetFrame(this);
491 // Set layout constraints here
493 // Control bar constraints
494 wxLayoutConstraints
*c1
= new wxLayoutConstraints
;
496 // m_controlBar->GetSize(&w, &h);
498 #if (defined(__WXMSW__) || defined(__WXGTK__))
504 c1
->left
.SameAs (this, wxLeft
);
505 c1
->top
.SameAs (this, wxTop
);
506 c1
->right
.SameAs (this, wxRight
);
507 c1
->height
.Absolute (h
);
509 m_controlBar
->SetConstraints(c1
);
511 // Canvas constraints
512 wxLayoutConstraints
*c2
= new wxLayoutConstraints
;
514 c2
->left
.SameAs (this, wxLeft
);
515 c2
->top
.Below (m_controlBar
);
516 c2
->right
.SameAs (this, wxRight
);
517 c2
->bottom
.SameAs (this, wxBottom
);
519 m_previewCanvas
->SetConstraints(c2
);
528 void wxPreviewFrame::CreateCanvas()
530 m_previewCanvas
= new wxPreviewCanvas(m_printPreview
, this);
533 void wxPreviewFrame::CreateControlBar()
535 long buttons
= wxPREVIEW_DEFAULT
;
536 if (m_printPreview
->GetPrintoutForPrinting())
537 buttons
|= wxPREVIEW_PRINT
;
539 m_controlBar
= new wxPreviewControlBar(m_printPreview
, buttons
, this, wxPoint(0, 0), wxSize(400, 40));
540 m_controlBar
->CreateButtons();
547 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
548 wxPrintout
*printoutForPrinting
,
552 m_printDialogData
= (*data
);
554 Init(printout
, printoutForPrinting
);
557 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
,
558 wxPrintout
*printoutForPrinting
,
559 wxPrintDialogData
*data
)
562 m_printDialogData
= (*data
);
564 Init(printout
, printoutForPrinting
);
567 void wxPrintPreviewBase::Init(wxPrintout
*printout
,
568 wxPrintout
*printoutForPrinting
)
571 m_previewPrintout
= printout
;
572 if (m_previewPrintout
)
573 m_previewPrintout
->SetIsPreview(TRUE
);
575 m_printPrintout
= printoutForPrinting
;
577 m_previewCanvas
= NULL
;
578 m_previewFrame
= NULL
;
579 m_previewBitmap
= NULL
;
586 m_printingPrepared
= FALSE
;
588 // Too soon! Moved to RenderPage.
589 // printout->OnPreparePrinting();
591 // Get some parameters from the printout, if defined
593 printout
->GetPageInfo(&m_minPage
, &m_maxPage
, &selFrom
, &selTo
);
596 wxPrintPreviewBase::~wxPrintPreviewBase()
598 if (m_previewPrintout
)
599 delete m_previewPrintout
;
601 delete m_previewBitmap
;
603 delete m_printPrintout
;
606 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
608 if (m_currentPage
== pageNum
)
611 m_currentPage
= pageNum
;
614 delete m_previewBitmap
;
615 m_previewBitmap
= NULL
;
620 if (!RenderPage(pageNum
))
622 m_previewCanvas
->Refresh();
627 bool wxPrintPreviewBase::PaintPage(wxWindow
*canvas
, wxDC
& dc
)
629 DrawBlankPage(canvas
, dc
);
631 if (!m_previewBitmap
)
632 if (!RenderPage(m_currentPage
))
635 if (!m_previewBitmap
)
641 int canvasWidth
, canvasHeight
;
642 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
644 double zoomScale
= ((float)m_currentZoom
/(float)100);
645 double actualWidth
= (zoomScale
*m_pageWidth
*m_previewScale
);
646 // float actualHeight = (float)(zoomScale*m_pageHeight*m_previewScale);
648 int x
= (int) ((canvasWidth
- actualWidth
)/2.0);
649 if (x
< m_leftMargin
)
654 temp_dc
.SelectObject(*m_previewBitmap
);
656 dc
.Blit(x
, y
, m_previewBitmap
->GetWidth(), m_previewBitmap
->GetHeight(), &temp_dc
, 0, 0);
658 temp_dc
.SelectObject(wxNullBitmap
);
663 bool wxPrintPreviewBase::RenderPage(int pageNum
)
667 int canvasWidth
, canvasHeight
;
669 if (!m_previewCanvas
)
671 wxFAIL_MSG(_T("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
675 m_previewCanvas
->GetSize(&canvasWidth
, &canvasHeight
);
677 double zoomScale
= (m_currentZoom
/100.0);
678 int actualWidth
= (int)(zoomScale
*m_pageWidth
*m_previewScale
);
679 int actualHeight
= (int)(zoomScale
*m_pageHeight
*m_previewScale
);
681 int x
= (int)((canvasWidth
- actualWidth
)/2.0);
682 if (x
< m_leftMargin
)
684 // int y = m_topMargin;
687 if (!m_previewBitmap
)
689 m_previewBitmap
= new wxBitmap((int)actualWidth
, (int)actualHeight
);
690 if (!m_previewBitmap
|| !m_previewBitmap
->Ok())
692 if (m_previewBitmap
) {
693 delete m_previewBitmap
;
694 m_previewBitmap
= NULL
;
696 wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK
);
702 memoryDC
.SelectObject(*m_previewBitmap
);
706 m_previewPrintout
->SetDC(&memoryDC
);
707 m_previewPrintout
->SetPageSizePixels(m_pageWidth
, m_pageHeight
);
709 // Need to delay OnPreparePrinting until here, so we have enough information.
710 if (!m_printingPrepared
)
712 m_previewPrintout
->OnPreparePrinting();
713 m_printingPrepared
= TRUE
;
716 m_previewPrintout
->OnBeginPrinting();
718 if (!m_previewPrintout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
720 wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK
);
722 memoryDC
.SelectObject(wxNullBitmap
);
724 delete m_previewBitmap
;
725 m_previewBitmap
= NULL
;
729 m_previewPrintout
->OnPrintPage(pageNum
);
730 m_previewPrintout
->OnEndDocument();
731 m_previewPrintout
->OnEndPrinting();
733 m_previewPrintout
->SetDC(NULL
);
735 memoryDC
.SelectObject(wxNullBitmap
);
739 wxSprintf(buf
, _("Page %d of %d"), pageNum
, m_maxPage
);
741 wxSprintf(buf
, _("Page %d"), pageNum
);
744 m_previewFrame
->SetStatusText(buf
);
750 bool wxPrintPreviewBase::DrawBlankPage(wxWindow
*canvas
, wxDC
& dc
)
752 int canvasWidth
, canvasHeight
;
753 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
755 float zoomScale
= (float)((float)m_currentZoom
/(float)100);
756 float actualWidth
= zoomScale
*m_pageWidth
*m_previewScale
;
757 float actualHeight
= zoomScale
*m_pageHeight
*m_previewScale
;
759 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
760 if (x
< m_leftMargin
)
761 x
= (float)m_leftMargin
;
762 float y
= (float)m_topMargin
;
764 // Draw shadow, allowing for 1-pixel border AROUND the actual page
765 int shadowOffset
= 4;
766 dc
.SetPen(*wxBLACK_PEN
);
767 dc
.SetBrush(*wxBLACK_BRUSH
);
769 dc.DrawRectangle((int)(x-1 + shadowOffset), (int)(y-1 + shadowOffset), (int)(actualWidth+2), (int)(actualHeight+2));
771 dc
.DrawRectangle((int)(x
+ shadowOffset
), (int)(y
+ actualHeight
+1), (int)(actualWidth
), shadowOffset
);
772 dc
.DrawRectangle((int)(x
+ actualWidth
), (int)(y
+ shadowOffset
), shadowOffset
, (int)(actualHeight
));
774 // Draw blank page allowing for 1-pixel border AROUND the actual page
775 dc
.SetPen(*wxBLACK_PEN
);
776 dc
.SetBrush(*wxWHITE_BRUSH
);
779 wxRegion update_region = canvas->GetUpdateRegion();
780 wxRect r = update_region.GetBox();
782 printf( "x: %d y: %d w: %d h: %d.\n", (int)r.x, (int)r.y, (int)r.width, (int)r.height );
785 dc
.DrawRectangle((int)(x
-2), (int)(y
-1), (int)(actualWidth
+3), (int)(actualHeight
+2));
790 void wxPrintPreviewBase::SetZoom(int percent
)
792 if (m_currentZoom
== percent
)
795 m_currentZoom
= percent
;
798 delete m_previewBitmap
;
799 m_previewBitmap
= NULL
;
804 RenderPage(m_currentPage
);
805 ((wxScrolledWindow
*) m_previewCanvas
)->Scroll(0, 0);
806 m_previewCanvas
->Clear();
807 m_previewCanvas
->Refresh();
811 #endif // wxUSE_PRINTING_ARCHITECTURE