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
63 #if !defined(APIENTRY) // NT defines APIENTRY, 3.x not
64 #define APIENTRY FAR PASCAL
70 #define _EXPORT _export
71 typedef signed short int SHORT
;
74 #if !defined(__WIN32__) // 3.x uses FARPROC for dialogs
75 #define DLGPROC FARPROC
78 LONG APIENTRY _EXPORT
wxAbortProc(HDC hPr
, int Code
);
82 #if !USE_SHARED_LIBRARY
83 IMPLEMENT_CLASS(wxPrinterBase
, wxObject
)
84 IMPLEMENT_ABSTRACT_CLASS(wxPrintout
, wxObject
)
85 IMPLEMENT_CLASS(wxPreviewCanvas
, wxWindow
)
86 IMPLEMENT_CLASS(wxPreviewControlBar
, wxWindow
)
87 IMPLEMENT_CLASS(wxPreviewFrame
, wxFrame
)
88 IMPLEMENT_CLASS(wxPrintPreviewBase
, wxObject
)
90 BEGIN_EVENT_TABLE(wxPrintAbortDialog
, wxDialog
)
91 EVT_BUTTON(wxID_CANCEL
, wxPrintAbortDialog::OnCancel
)
94 BEGIN_EVENT_TABLE(wxPreviewCanvas
, wxScrolledWindow
)
95 EVT_PAINT(wxPreviewCanvas::OnPaint
)
96 EVT_SYS_COLOUR_CHANGED(wxPreviewCanvas::OnSysColourChanged
)
104 wxPrinterBase::wxPrinterBase(wxPrintData
*data
)
106 currentPrintout
= NULL
;
113 wxWindow
*wxPrinterBase::abortWindow
= NULL
;
114 bool wxPrinterBase::abortIt
= FALSE
;
116 wxPrinterBase::~wxPrinterBase(void)
120 void wxPrintAbortDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
))
122 wxPrinterBase::abortIt
= TRUE
;
123 wxPrinterBase::abortWindow
->Show(FALSE
);
124 wxPrinterBase::abortWindow
->Close(TRUE
);
125 wxPrinterBase::abortWindow
= NULL
;
128 wxWindow
*wxPrinterBase::CreateAbortWindow(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
))
130 wxPrintAbortDialog
*dialog
= new wxPrintAbortDialog(parent
, _("Printing"), wxPoint(0, 0), wxSize(400, 400));
131 (void) new wxStaticText(dialog
, -1, _("Please wait..."), wxPoint(5, 5));
133 wxButton
*button
= new wxButton(dialog
, wxID_CANCEL
, _("Cancel"), wxPoint(5, 30));
136 button
->Centre(wxHORIZONTAL
);
142 void wxPrinterBase::ReportError(wxWindow
*parent
, wxPrintout
*WXUNUSED(printout
), char *message
)
144 wxMessageBox(message
, "Printing Error", wxOK
, parent
);
151 wxPrintout::wxPrintout(const char *title
)
153 printoutTitle
= title
? copystring(title
) : NULL
;
158 pageHeightPixels
= 0;
166 wxPrintout::~wxPrintout(void)
169 delete[] printoutTitle
;
172 bool wxPrintout::OnBeginDocument(int WXUNUSED(startPage
), int WXUNUSED(endPage
))
174 return GetDC()->StartDoc("Printing");
177 void wxPrintout::OnEndDocument(void)
182 void wxPrintout::OnBeginPrinting(void)
186 void wxPrintout::OnEndPrinting(void)
190 bool wxPrintout::HasPage(int page
)
195 void wxPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *fromPage
, int *toPage
)
207 wxPreviewCanvas::wxPreviewCanvas(wxPrintPreviewBase
*preview
, wxWindow
*parent
,
208 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
209 wxScrolledWindow(parent
, -1, pos
, size
, style
, name
)
211 printPreview
= preview
;
212 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
214 SetScrollbars(40, 40, 100, 100);
217 wxPreviewCanvas::~wxPreviewCanvas(void)
221 void wxPreviewCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
227 printPreview
->PaintPage(this, dc
);
231 // Responds to colour changes, and passes event on to children.
232 void wxPreviewCanvas::OnSysColourChanged(wxSysColourChangedEvent
& event
)
234 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
));
237 // Propagate the event to the non-top-level children
238 wxWindow::OnSysColourChanged(event
);
242 * Preview control bar
245 BEGIN_EVENT_TABLE(wxPreviewControlBar
, wxPanel
)
246 EVT_BUTTON(wxID_PREVIEW_CLOSE
, wxPreviewControlBar::OnClose
)
247 EVT_BUTTON(wxID_PREVIEW_PRINT
, wxPreviewControlBar::OnPrint
)
248 EVT_BUTTON(wxID_PREVIEW_PREVIOUS
, wxPreviewControlBar::OnPrevious
)
249 EVT_BUTTON(wxID_PREVIEW_NEXT
, wxPreviewControlBar::OnNext
)
250 EVT_CHOICE(wxID_PREVIEW_ZOOM
, wxPreviewControlBar::OnZoom
)
251 EVT_PAINT(wxPreviewControlBar::OnPaint
)
254 wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase
*preview
, long buttons
,
255 wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
,
256 long style
, const wxString
& name
):
257 wxPanel(parent
, -1, pos
, size
, style
, name
)
259 printPreview
= preview
;
261 nextPageButton
= NULL
;
262 previousPageButton
= NULL
;
265 buttonFlags
= buttons
;
268 wxFont
*wxPreviewControlBar::buttonFont
= NULL
;
270 wxPreviewControlBar::~wxPreviewControlBar(void)
274 void wxPreviewControlBar::OnPaint(wxPaintEvent
& WXUNUSED(event
))
280 dc
.SetPen(*wxBLACK_PEN
);
281 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
282 dc
.DrawLine( 0, h
-1, w
, h
-1 );
285 void wxPreviewControlBar::OnClose(wxCommandEvent
& WXUNUSED(event
))
287 wxPreviewFrame
*frame
= (wxPreviewFrame
*)GetParent();
291 void wxPreviewControlBar::OnPrint(wxCommandEvent
& WXUNUSED(event
))
293 wxPrintPreviewBase
*preview
= GetPrintPreview();
294 preview
->Print(TRUE
);
297 void wxPreviewControlBar::OnNext(wxCommandEvent
& WXUNUSED(event
))
299 wxPrintPreviewBase
*preview
= GetPrintPreview();
302 int currentPage
= preview
->GetCurrentPage();
303 if ((preview
->GetMaxPage() > 0) &&
304 (currentPage
< preview
->GetMaxPage()) &&
305 preview
->GetPrintout()->HasPage(currentPage
+ 1))
307 preview
->SetCurrentPage(currentPage
+ 1);
312 void wxPreviewControlBar::OnPrevious(wxCommandEvent
& WXUNUSED(event
))
314 wxPrintPreviewBase
*preview
= GetPrintPreview();
317 int currentPage
= preview
->GetCurrentPage();
318 if ((preview
->GetMinPage() > 0) &&
319 (currentPage
> preview
->GetMinPage()) &&
320 preview
->GetPrintout()->HasPage(currentPage
- 1))
322 preview
->SetCurrentPage(currentPage
- 1);
327 void wxPreviewControlBar::OnZoom(wxCommandEvent
& WXUNUSED(event
))
329 int zoom
= GetZoomControl();
330 if (GetPrintPreview())
331 GetPrintPreview()->SetZoom(zoom
);
334 void wxPreviewControlBar::CreateButtons(void)
336 #ifdef __GOOD_COMPILER__ // Robert Roebling
338 SetSize(0, 0, 400, 40);
347 buttonFont
= wxTheFontList
->FindOrCreateFont(fontSize
, wxSWISS
, wxNORMAL
, wxBOLD
);
348 SetButtonFont(*buttonFont
);
350 int buttonWidth
= 65;
351 int buttonHeight
= 24;
357 closeButton
= new wxButton(this, wxID_PREVIEW_CLOSE
, "Close",
358 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
360 x
+= gap
+ buttonWidth
;
362 if (buttonFlags
& wxPREVIEW_PRINT
)
364 printButton
= new wxButton(this, wxID_PREVIEW_PRINT
, "Print...", wxPoint(x
, y
),
365 wxSize(buttonWidth
, buttonHeight
));
366 x
+= gap
+ buttonWidth
;
369 if (buttonFlags
& wxPREVIEW_PREVIOUS
)
371 previousPageButton
= new wxButton(this, wxID_PREVIEW_PREVIOUS
, "<<", wxPoint(x
, y
),
372 wxSize(buttonWidth
, buttonHeight
));
373 x
+= gap
+ buttonWidth
;
376 if (buttonFlags
& wxPREVIEW_NEXT
)
378 nextPageButton
= new wxButton(this, wxID_PREVIEW_NEXT
, ">>",
379 wxPoint(x
, y
), wxSize(buttonWidth
, buttonHeight
));
380 x
+= gap
+ buttonWidth
;
383 static wxString choices
[] = { "10%", "20%", "25%", "30%", "35%", "40%", "45%", "50%", "55%", "60%",
384 "65%", "70%", "75%", "80%", "85%", "90%", "95%", "100%", "110%", "120%", "150%", "200%" };
386 if (buttonFlags
& wxPREVIEW_ZOOM
)
388 zoomControl
= new wxChoice(this, wxID_PREVIEW_ZOOM
, wxPoint(x
, y
),
389 wxSize(100, -1), n
, (wxString
*)choices
);
390 SetZoomControl(printPreview
->GetZoom());
393 closeButton
->SetDefault();
398 void wxPreviewControlBar::SetZoomControl(int zoom
)
400 #ifdef __GOOD_COMPILER__ // Robert Roebling
402 sprintf(buf
, "%d%%", zoom
);
404 zoomControl
->SetStringSelection(buf
);
408 int wxPreviewControlBar::GetZoomControl(void)
410 #ifdef __GOOD_COMPILER__ // Robert Roebling
412 if (zoomControl
&& zoomControl
->GetStringSelection())
414 strcpy(buf
, zoomControl
->GetStringSelection());
415 buf
[strlen(buf
) - 1] = 0;
416 return (int)atoi(buf
);
429 wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase
*preview
, wxFrame
*parent
, const wxString
& title
,
430 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
):
431 wxFrame(parent
, -1, title
, pos
, size
, style
, name
)
433 #ifdef __GOOD_COMPILER__ // Robert Roebling
435 printPreview
= preview
;
437 previewCanvas
= NULL
;
441 wxPreviewFrame::~wxPreviewFrame(void)
445 bool wxPreviewFrame::OnClose(void)
447 #ifdef __GOOD_COMPILER__ // Robert Roebling
451 // Need to delete the printout and the print preview
452 wxPrintout
*printout
= printPreview
->GetPrintout();
456 printPreview
->SetPrintout(NULL
);
457 printPreview
->SetCanvas(NULL
);
458 printPreview
->SetFrame(NULL
);
467 void wxPreviewFrame::Initialize(void)
470 #ifdef __GOOD_COMPILER__ // Robert Roebling
477 printPreview
->SetCanvas(previewCanvas
);
478 printPreview
->SetFrame(this);
480 // Set layout constraints here
482 // Control bar constraints
483 wxLayoutConstraints
*c1
= new wxLayoutConstraints
;
485 // controlBar->GetSize(&w, &h);
493 c1
->left
.SameAs (this, wxLeft
);
494 c1
->top
.SameAs (this, wxTop
);
495 c1
->right
.SameAs (this, wxRight
);
496 c1
->height
.Absolute (h
);
498 controlBar
->SetConstraints(c1
);
500 // Canvas constraints
501 wxLayoutConstraints
*c2
= new wxLayoutConstraints
;
503 c2
->left
.SameAs (this, wxLeft
);
504 c2
->top
.Below (controlBar
);
505 c2
->right
.SameAs (this, wxRight
);
506 c2
->bottom
.SameAs (this, wxBottom
);
508 previewCanvas
->SetConstraints(c2
);
519 void wxPreviewFrame::CreateCanvas(void)
521 #ifdef __GOOD_COMPILER__ // Robert Roebling
523 previewCanvas
= new wxPreviewCanvas(printPreview
, this);
528 void wxPreviewFrame::CreateControlBar(void)
530 #ifdef __GOOD_COMPILER__ // Robert Roebling
532 long buttons
= wxPREVIEW_DEFAULT
;
533 if (printPreview
->GetPrintoutForPrinting())
534 buttons
|= wxPREVIEW_PRINT
;
536 controlBar
= new wxPreviewControlBar(printPreview
, buttons
, this, wxPoint(0, 0), wxSize(400, 40));
537 controlBar
->CreateButtons();
545 wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout
*printout
, wxPrintout
*printoutForPrinting
, wxPrintData
*data
)
548 #ifdef __GOOD_COMPILER__ // Robert Roebling
551 previewPrintout
= printout
;
553 previewPrintout
->SetIsPreview(TRUE
);
555 printPrintout
= printoutForPrinting
;
559 previewCanvas
= NULL
;
561 previewBitmap
= NULL
;
569 printout
->OnPreparePrinting();
571 // Get some parameters from the printout, if defined
573 printout
->GetPageInfo(&minPage
, &maxPage
, &selFrom
, &selTo
);
578 wxPrintPreviewBase::~wxPrintPreviewBase(void)
580 #ifdef __GOOD_COMPILER__ // Robert Roebling
583 delete previewPrintout
;
585 delete previewBitmap
;
587 delete printPrintout
;
592 bool wxPrintPreviewBase::SetCurrentPage(int pageNum
)
594 #ifdef __GOOD_COMPILER__ // Robert Roebling
595 if (currentPage
== pageNum
)
598 currentPage
= pageNum
;
601 delete previewBitmap
;
602 previewBitmap
= NULL
;
608 previewCanvas
->Refresh();
615 bool wxPrintPreviewBase::PaintPage(wxWindow
*canvas
, wxDC
& dc
)
618 #ifdef __GOOD_COMPILER__ // Robert Roebling
620 DrawBlankPage(canvas
, dc
);
623 RenderPage(currentPage
);
631 int canvasWidth
, canvasHeight
;
632 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
634 float zoomScale
= (float)((float)currentZoom
/(float)100);
635 float actualWidth
= (float)(zoomScale
*pageWidth
*previewScale
);
636 // float actualHeight = (float)(zoomScale*pageHeight*previewScale);
638 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
640 x
= (float)leftMargin
;
641 float y
= (float)topMargin
;
644 temp_dc
.SelectObject(*previewBitmap
);
646 dc
.Blit((float)x
, (float)y
, (float)previewBitmap
->GetWidth(), (float)previewBitmap
->GetHeight(), &temp_dc
, (float)0, (float)0);
648 temp_dc
.SelectObject(wxNullBitmap
);
655 bool wxPrintPreviewBase::RenderPage(int pageNum
)
657 int canvasWidth
, canvasHeight
;
659 #ifdef __GOOD_COMPILER__ // Robert Roebling
663 wxMessageBox("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!",
664 "Print Preview Failure", wxOK
);
667 previewCanvas
->GetSize(&canvasWidth
, &canvasHeight
);
669 float zoomScale
= (float)((float)currentZoom
/(float)100);
670 float actualWidth
= (float)(zoomScale
*pageWidth
*previewScale
);
671 float actualHeight
= (float)(zoomScale
*pageHeight
*previewScale
);
673 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
675 x
= (float)leftMargin
;
676 // float y = topMargin;
681 previewBitmap
= new wxBitmap((int)actualWidth
, (int)actualHeight
);
682 if (!previewBitmap
|| !previewBitmap
->Ok())
685 delete previewBitmap
;
686 wxMessageBox("Sorry, not enough memory to create a preview.", "Print Preview Failure", wxOK
);
692 memoryDC
.SelectObject(*previewBitmap
);
696 previewPrintout
->SetDC(&memoryDC
);
697 previewPrintout
->SetPageSizePixels(pageWidth
, pageHeight
);
699 previewPrintout
->OnBeginPrinting();
702 if (!previewPrintout
->OnBeginDocument(printData
.GetFromPage(), printData
.GetToPage()))
704 wxMessageBox("Could not start document preview.", "Print Preview Failure", wxOK
);
706 memoryDC
.SelectObject(wxNullBitmap
);
708 delete previewBitmap
;
712 previewPrintout
->OnPrintPage(pageNum
);
713 previewPrintout
->OnEndDocument();
714 previewPrintout
->OnEndPrinting();
716 previewPrintout
->SetDC(NULL
);
718 memoryDC
.SelectObject(wxNullBitmap
);
723 sprintf(buf
, "Page %d of %d", pageNum
, maxPage
);
725 sprintf(buf
, "Page %d", pageNum
);
728 previewFrame
->SetStatusText(buf
);
734 bool wxPrintPreviewBase::DrawBlankPage(wxWindow
*canvas
, wxDC
& dc
)
737 #ifdef __GOOD_COMPILER__ // Robert Roebling
739 int canvasWidth
, canvasHeight
;
740 canvas
->GetSize(&canvasWidth
, &canvasHeight
);
742 float zoomScale
= (float)((float)currentZoom
/(float)100);
743 float actualWidth
= zoomScale
*pageWidth
*previewScale
;
744 float actualHeight
= zoomScale
*pageHeight
*previewScale
;
746 float x
= (float)((canvasWidth
- actualWidth
)/2.0);
748 x
= (float)leftMargin
;
749 float y
= (float)topMargin
;
751 // Draw shadow, allowing for 1-pixel border AROUND the actual page
752 int shadowOffset
= 4;
753 dc
.SetPen(*wxBLACK_PEN
);
754 dc
.SetBrush(*wxBLACK_BRUSH
);
755 dc
.DrawRectangle(x
-1 + shadowOffset
, y
-1 + shadowOffset
, actualWidth
+2, actualHeight
+2);
757 // Draw blank page allowing for 1-pixel border AROUND the actual page
758 dc
.SetPen(*wxBLACK_PEN
);
759 dc
.SetBrush(*wxWHITE_BRUSH
);
762 dc
.DrawRectangle(x
-1, y
-1, actualWidth
+2, actualHeight
+2);
769 void wxPrintPreviewBase::SetZoom(int percent
)
771 #ifdef __GOOD_COMPILER__ // Robert Roebling
772 if (currentZoom
== percent
)
775 currentZoom
= percent
;
778 delete previewBitmap
;
779 previewBitmap
= NULL
;
781 RenderPage(currentPage
);
785 previewCanvas
->Clear();
786 previewCanvas
->Refresh();