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"
23 // #define __GOOD_COMPILER__
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"
52 // Clash with Windows header files
61 #if !defined(APIENTRY) // NT defines APIENTRY, 3.x not
62 #define APIENTRY FAR PASCAL
68 #define _EXPORT _export
69 typedef signed short int SHORT
;
72 #if !defined(__WIN32__) // 3.x uses FARPROC for dialogs
73 #define DLGPROC FARPROC
76 LONG APIENTRY _EXPORT
wxAbortProc(HDC hPr
, int Code
);
80 #if !USE_SHARED_LIBRARY
81 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
82 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
83 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
84 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
85 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
86 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
88 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
89 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
92 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
93 EVT_PAINT(wxPreviewCanvas::OnPaint
)
94 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
102 wxPrinterBase::wxPrinterBase(wxPrintData
*data
)
104 currentPrintout
= NULL
;
111 wxWindow
*wxPrinterBase::abortWindow
= NULL
;
112 bool wxPrinterBase::abortIt
= FALSE
;
114 wxPrinterBase::~wxPrinterBase(void)
118 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
120 wxPrinterBase::abortIt
= TRUE
;
121 wxPrinterBase::abortWindow
->Show(FALSE
);
122 wxPrinterBase::abortWindow
->Close(TRUE
);
123 wxPrinterBase::abortWindow
= NULL
;
126 wxWindow
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
))
128 wxPrintAbortDialog
*dialog
= new wxPrintAbortDialog(parent
, _("Printing"), wxPoint(0, 0), wxSize(400, 400));
129 (void) new wxStaticText(dialog
, -1, _("Please wait..."), wxPoint(5, 5));
131 wxButton
*button
= new wxButton(dialog
, wxID_CANCEL
, _("Cancel"), wxPoint(5, 30));
134 button
->Centre(wxHORIZONTAL
);
140 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), char *message
)
142 wxMessageBox(message
, "Printing Error", wxOK
, parent
);
149 wxPrintout::wxPrintout(char *title
)
151 printoutTitle
= title
? copystring(title
) : (char*)NULL
;
156 pageHeightPixels
= 0;
164 wxPrintout::~wxPrintout(void)
167 delete[] printoutTitle
;
170 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
172 return GetDC()->StartDoc("Printing");
175 void wxPrintout::OnEndDocument(void)
180 void wxPrintout::OnBeginPrinting(void)
184 void wxPrintout::OnEndPrinting(void)
188 bool wxPrintout::HasPage(int page
)
193 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
205 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
206 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
207 wxScrolledWindow(parent
, -1, pos
, size
, style
, name
)
209 printPreview
= preview
;
210 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
212 SetScrollbars(40, 40, 100, 100);
215 wxPreviewCanvas::~wxPreviewCanvas(void)
219 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
225 printPreview
->PaintPage(this, dc
);
229 // Responds to colour changes, and passes event on to children.
230 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
232 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
235 // Propagate the event to the non-top-level children
236 wxWindow::OnSysColourChanged(event
);
240 * Preview control bar
243 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
244 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnClose
)
245 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrint
)
246 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPrevious
)
247 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNext
)
248 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoom
)
249 EVT_PAINT(wxPreviewControlBar::OnPaint
)
252 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
253 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
254 long style
, const wxString
& name
):
255 wxPanel(parent
, -1, pos
, size
, style
, name
)
257 printPreview
= preview
;
259 nextPageButton
= NULL
;
260 previousPageButton
= NULL
;
263 buttonFlags
= buttons
;
266 wxFont
*wxPreviewControlBar::buttonFont
= NULL
;
268 wxPreviewControlBar::~wxPreviewControlBar(void)
272 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
278 dc
.SetPen(*wxBLACK_PEN
);
279 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
280 dc
.DrawLine( 0, h
-1, w
, h
-1 );
283 void wxPreviewControlBar::OnClose(wxCommandEvent
& WXUNUSED(event
))
285 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
289 void wxPreviewControlBar::OnPrint(wxCommandEvent
& WXUNUSED(event
))
291 wxPrintPreviewBase
*preview
= GetPrintPreview();
292 preview
->Print(TRUE
);
295 void wxPreviewControlBar::OnNext(wxCommandEvent
& WXUNUSED(event
))
297 wxPrintPreviewBase
*preview
= GetPrintPreview();
300 int currentPage
= preview
->GetCurrentPage();
301 if ((preview
->GetMaxPage() > 0) &&
302 (currentPage
< preview
->GetMaxPage()) &&
303 preview
->GetPrintout()->HasPage(currentPage
+ 1))
305 preview
->SetCurrentPage(currentPage
+ 1);
310 void wxPreviewControlBar::OnPrevious(wxCommandEvent
& WXUNUSED(event
))
312 wxPrintPreviewBase
*preview
= GetPrintPreview();
315 int currentPage
= preview
->GetCurrentPage();
316 if ((preview
->GetMinPage() > 0) &&
317 (currentPage
> preview
->GetMinPage()) &&
318 preview
->GetPrintout()->HasPage(currentPage
- 1))
320 preview
->SetCurrentPage(currentPage
- 1);
325 void wxPreviewControlBar::OnZoom(wxCommandEvent
& WXUNUSED(event
))
327 int zoom
= GetZoomControl();
328 if (GetPrintPreview())
329 GetPrintPreview()->SetZoom(zoom
);
332 void wxPreviewControlBar::CreateButtons(void)
334 #ifdef __GOOD_COMPILER__ // Robert Roebling
336 SetSize(0, 0, 400, 40);
345 buttonFont
= wxTheFontList
->FindOrCreateFont(fontSize
, wxSWISS
, wxNORMAL
, wxBOLD
);
346 SetButtonFont(*buttonFont
);
348 int buttonWidth
= 65;
349 int buttonHeight
= 24;
355 closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, "Close",
356 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
358 x
+= gap
+ buttonWidth
;
360 if (buttonFlags
& wxPREVIEW_PRINT
)
362 printButton
= new wxButton(this, wxID_PREVIEW_PRINT
, "Print...", wxPoint(x
, y
),
363 wxSize(buttonWidth
, buttonHeight
));
364 x
+= gap
+ buttonWidth
;
367 if (buttonFlags
& wxPREVIEW_PREVIOUS
)
369 previousPageButton
= new wxButton(this, wxID_PREVIEW_PREVIOUS
, "<<", wxPoint(x
, y
),
370 wxSize(buttonWidth
, buttonHeight
));
371 x
+= gap
+ buttonWidth
;
374 if (buttonFlags
& wxPREVIEW_NEXT
)
376 nextPageButton
= new wxButton(this, wxID_PREVIEW_NEXT
, ">>",
377 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
378 x
+= gap
+ buttonWidth
;
381 static wxString choices
[] = { "10%", "20%", "25%", "30%", "35%", "40%", "45%", "50%", "55%", "60%",
382 "65%", "70%", "75%", "80%", "85%", "90%", "95%", "100%", "110%", "120%", "150%", "200%" };
384 if (buttonFlags
& wxPREVIEW_ZOOM
)
386 zoomControl
= new wxChoice(this, wxID_PREVIEW_ZOOM
, wxPoint(x
, y
),
387 wxSize(100, -1), n
, (wxString
*)choices
);
388 SetZoomControl(printPreview
->GetZoom());
391 closeButton
->SetDefault();
396 void wxPreviewControlBar::SetZoomControl(int zoom
)
398 #ifdef __GOOD_COMPILER__ // Robert Roebling
400 sprintf(buf
, "%d%%", zoom
);
402 zoomControl
->SetStringSelection(buf
);
406 int wxPreviewControlBar::GetZoomControl(void)
408 #ifdef __GOOD_COMPILER__ // Robert Roebling
410 if (zoomControl
&& zoomControl
->GetStringSelection())
412 strcpy(buf
, zoomControl
->GetStringSelection());
413 buf
[strlen(buf
) - 1] = 0;
414 return (int)atoi(buf
);
427 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxFrame
*parent
, const wxString
& title
,
428 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
429 wxFrame(parent
, -1, title
, pos
, size
, style
, name
)
431 #ifdef __GOOD_COMPILER__ // Robert Roebling
433 printPreview
= preview
;
435 previewCanvas
= NULL
;
439 wxPreviewFrame::~wxPreviewFrame(void)
443 bool wxPreviewFrame::OnClose(void)
445 #ifdef __GOOD_COMPILER__ // Robert Roebling
449 // Need to delete the printout and the print preview
450 wxPrintout
*printout
= printPreview
->GetPrintout();
454 printPreview
->SetPrintout(NULL
);
455 printPreview
->SetCanvas(NULL
);
456 printPreview
->SetFrame(NULL
);
465 void wxPreviewFrame::Initialize(void)
468 #ifdef __GOOD_COMPILER__ // Robert Roebling
475 printPreview
->SetCanvas(previewCanvas
);
476 printPreview
->SetFrame(this);
478 // Set layout constraints here
480 // Control bar constraints
481 wxLayoutConstraints
*c1
= new wxLayoutConstraints
;
483 // controlBar->GetSize(&w, &h);
491 c1
->left
.SameAs (this, wxLeft
);
492 c1
->top
.SameAs (this, wxTop
);
493 c1
->right
.SameAs (this, wxRight
);
494 c1
->height
.Absolute (h
);
496 controlBar
->SetConstraints(c1
);
498 // Canvas constraints
499 wxLayoutConstraints
*c2
= new wxLayoutConstraints
;
501 c2
->left
.SameAs (this, wxLeft
);
502 c2
->top
.Below (controlBar
);
503 c2
->right
.SameAs (this, wxRight
);
504 c2
->bottom
.SameAs (this, wxBottom
);
506 previewCanvas
->SetConstraints(c2
);
517 void wxPreviewFrame::CreateCanvas(void)
519 #ifdef __GOOD_COMPILER__ // Robert Roebling
521 previewCanvas
= new wxPreviewCanvas(printPreview
, this);
526 void wxPreviewFrame::CreateControlBar(void)
528 #ifdef __GOOD_COMPILER__ // Robert Roebling
530 long buttons
= wxPREVIEW_DEFAULT
;
531 if (printPreview
->GetPrintoutForPrinting())
532 buttons
|= wxPREVIEW_PRINT
;
534 controlBar
= new wxPreviewControlBar(printPreview
, buttons
, this, wxPoint(0, 0), wxSize(400, 40));
535 controlBar
->CreateButtons();
543 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
, wxPrintout
*printoutForPrinting
, wxPrintData
*data
)
546 #ifdef __GOOD_COMPILER__ // Robert Roebling
549 previewPrintout
= printout
;
551 previewPrintout
->SetIsPreview(TRUE
);
553 printPrintout
= printoutForPrinting
;
557 previewCanvas
= NULL
;
559 previewBitmap
= NULL
;
567 printout
->OnPreparePrinting();
569 // Get some parameters from the printout, if defined
571 printout
->GetPageInfo(&minPage
, &maxPage
, &selFrom
, &selTo
);
576 wxPrintPreviewBase::~wxPrintPreviewBase(void)
578 #ifdef __GOOD_COMPILER__ // Robert Roebling
581 delete previewPrintout
;
583 delete previewBitmap
;
585 delete printPrintout
;
590 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
592 #ifdef __GOOD_COMPILER__ // Robert Roebling
593 if (currentPage
== pageNum
)
596 currentPage
= pageNum
;
599 delete previewBitmap
;
600 previewBitmap
= NULL
;
606 previewCanvas
->Refresh();
613 bool wxPrintPreviewBase::PaintPage(wxWindow
*canvas
, wxDC
& dc
)
616 #ifdef __GOOD_COMPILER__ // Robert Roebling
618 DrawBlankPage(canvas
, dc
);
621 RenderPage(currentPage
);
629 int canvasWidth
, canvasHeight
;
630 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
632 float zoomScale
= (float)((float)currentZoom
/(float)100);
633 float actualWidth
= (float)(zoomScale
*pageWidth
*previewScale
);
634 // float actualHeight = (float)(zoomScale*pageHeight*previewScale);
636 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
638 x
= (float)leftMargin
;
639 float y
= (float)topMargin
;
642 temp_dc
.SelectObject(*previewBitmap
);
644 dc
.Blit((float)x
, (float)y
, (float)previewBitmap
->GetWidth(), (float)previewBitmap
->GetHeight(), &temp_dc
, (float)0, (float)0);
646 temp_dc
.SelectObject(wxNullBitmap
);
653 bool wxPrintPreviewBase::RenderPage(int pageNum
)
655 int canvasWidth
, canvasHeight
;
657 #ifdef __GOOD_COMPILER__ // Robert Roebling
661 wxMessageBox("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!",
662 "Print Preview Failure", wxOK
);
665 previewCanvas
->GetSize(&canvasWidth
, &canvasHeight
);
667 float zoomScale
= (float)((float)currentZoom
/(float)100);
668 float actualWidth
= (float)(zoomScale
*pageWidth
*previewScale
);
669 float actualHeight
= (float)(zoomScale
*pageHeight
*previewScale
);
671 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
673 x
= (float)leftMargin
;
674 // float y = topMargin;
679 previewBitmap
= new wxBitmap((int)actualWidth
, (int)actualHeight
);
680 if (!previewBitmap
|| !previewBitmap
->Ok())
683 delete previewBitmap
;
684 wxMessageBox("Sorry, not enough memory to create a preview.", "Print Preview Failure", wxOK
);
690 memoryDC
.SelectObject(*previewBitmap
);
694 previewPrintout
->SetDC(&memoryDC
);
695 previewPrintout
->SetPageSizePixels(pageWidth
, pageHeight
);
697 previewPrintout
->OnBeginPrinting();
700 if (!previewPrintout
->OnBeginDocument(printData
.GetFromPage(), printData
.GetToPage()))
702 wxMessageBox("Could not start document preview.", "Print Preview Failure", wxOK
);
704 memoryDC
.SelectObject(wxNullBitmap
);
706 delete previewBitmap
;
710 previewPrintout
->OnPrintPage(pageNum
);
711 previewPrintout
->OnEndDocument();
712 previewPrintout
->OnEndPrinting();
714 previewPrintout
->SetDC(NULL
);
716 memoryDC
.SelectObject(wxNullBitmap
);
721 sprintf(buf
, "Page %d of %d", pageNum
, maxPage
);
723 sprintf(buf
, "Page %d", pageNum
);
726 previewFrame
->SetStatusText(buf
);
732 bool wxPrintPreviewBase::DrawBlankPage(wxWindow
*canvas
, wxDC
& dc
)
735 #ifdef __GOOD_COMPILER__ // Robert Roebling
737 int canvasWidth
, canvasHeight
;
738 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
740 float zoomScale
= (float)((float)currentZoom
/(float)100);
741 float actualWidth
= zoomScale
*pageWidth
*previewScale
;
742 float actualHeight
= zoomScale
*pageHeight
*previewScale
;
744 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
746 x
= (float)leftMargin
;
747 float y
= (float)topMargin
;
749 // Draw shadow, allowing for 1-pixel border AROUND the actual page
750 int shadowOffset
= 4;
751 dc
.SetPen(*wxBLACK_PEN
);
752 dc
.SetBrush(*wxBLACK_BRUSH
);
753 dc
.DrawRectangle(x
-1 + shadowOffset
, y
-1 + shadowOffset
, actualWidth
+2, actualHeight
+2);
755 // Draw blank page allowing for 1-pixel border AROUND the actual page
756 dc
.SetPen(*wxBLACK_PEN
);
757 dc
.SetBrush(*wxWHITE_BRUSH
);
760 dc
.DrawRectangle(x
-1, y
-1, actualWidth
+2, actualHeight
+2);
767 void wxPrintPreviewBase::SetZoom(int percent
)
769 #ifdef __GOOD_COMPILER__ // Robert Roebling
770 if (currentZoom
== percent
)
773 currentZoom
= percent
;
776 delete previewBitmap
;
777 previewBitmap
= NULL
;
779 RenderPage(currentPage
);
783 previewCanvas
->Clear();
784 previewCanvas
->Refresh();