+public:
+ wxPrintPageMaxCtrl(wxWindow *parent)
+ : wxStaticText(
+ parent,
+ wxID_ANY,
+ wxString(),
+ wxDefaultPosition,
+ wxSize
+ (
+ parent->GetTextExtent(MaxAsString(MAX_PAGE_NUMBER)).x,
+ wxDefaultCoord
+ ),
+ wxST_NO_AUTORESIZE | wxALIGN_CENTRE
+ )
+ {
+ }
+
+ // Set the maximal page to display once we really know what it is.
+ void SetMaxPage(int maxPage)
+ {
+ SetLabel(MaxAsString(maxPage));
+ }
+
+private:
+ static wxString MaxAsString(int maxPage)
+ {
+ return wxString::Format("/ %d", maxPage);
+ }
+
+ wxDECLARE_NO_COPY_CLASS(wxPrintPageMaxCtrl);
+};
+
+// ----------------------------------------------------------------------------
+// wxPrintPageTextCtrl
+// ----------------------------------------------------------------------------
+
+// This text control contains the page number in the specified interval.
+//
+// Invalid pages are not accepted and the control contents is validated when it
+// loses focus. Conversely, if the user changes the page to another valid one
+// or presses Enter, OnGotoPage() method of the preview object will be called.
+class wxPrintPageTextCtrl : public wxTextCtrl
+{
+public:
+ wxPrintPageTextCtrl(wxPreviewControlBar *preview)
+ : wxTextCtrl(preview,
+ wxID_PREVIEW_GOTO,
+ wxString(),
+ wxDefaultPosition,
+ // We use hardcoded maximal page number for the width
+ // instead of fitting it to the values we can show because
+ // the control looks uncomfortably narrow if the real page
+ // number is just one or two digits.
+ wxSize
+ (
+ preview->GetTextExtent(PageAsString(MAX_PAGE_NUMBER)).x,
+ wxDefaultCoord
+ ),
+ wxTE_PROCESS_ENTER
+#if wxUSE_VALIDATORS
+ , wxTextValidator(wxFILTER_DIGITS)
+#endif // wxUSE_VALIDATORS
+ ),
+ m_preview(preview)
+ {
+ m_minPage =
+ m_maxPage =
+ m_page = 1;
+
+ Connect(wxEVT_KILL_FOCUS,
+ wxFocusEventHandler(wxPrintPageTextCtrl::OnKillFocus));
+ Connect(wxEVT_COMMAND_TEXT_ENTER,
+ wxCommandEventHandler(wxPrintPageTextCtrl::OnTextEnter));
+ }
+
+ // Update the pages range, must be called after OnPreparePrinting() as
+ // these values are not known before.
+ void SetPageInfo(int minPage, int maxPage)
+ {
+ m_minPage = minPage;
+ m_maxPage = maxPage;
+
+ // Show the first page by default.
+ SetPageNumber(minPage);
+ }
+
+ // Helpers to conveniently set or get the current page number. Return value
+ // is 0 if the current controls contents is invalid.
+ void SetPageNumber(int page)
+ {
+ wxASSERT( IsValidPage(page) );
+
+ SetValue(PageAsString(page));
+ }
+
+ int GetPageNumber() const
+ {
+ long value;
+ if ( !GetValue().ToLong(&value) || !IsValidPage(value) )
+ return 0;
+
+ // Cast is safe because the value is less than (int) m_maxPage.
+ return static_cast<int>(value);
+ }
+
+private:
+ static wxString PageAsString(int page)
+ {
+ return wxString::Format("%d", page);
+ }
+
+ bool IsValidPage(int page) const
+ {
+ return page >= m_minPage && page <= m_maxPage;
+ }
+
+ bool DoChangePage()
+ {
+ const int page = GetPageNumber();
+
+ if ( !page )
+ return false;
+
+ if ( page != m_page )
+ {
+ // We have a valid page, remember it.
+ m_page = page;
+
+ // And notify the owner about the change.
+ m_preview->OnGotoPage();
+ }
+ //else: Nothing really changed.
+
+ return true;
+ }
+
+ void OnKillFocus(wxFocusEvent& event)
+ {
+ if ( !DoChangePage() )
+ {
+ // The current contents is invalid so reset it back to the last
+ // known good page index.
+ SetPageNumber(m_page);
+ }
+
+ event.Skip();
+ }
+
+ void OnTextEnter(wxCommandEvent& WXUNUSED(event))
+ {
+ DoChangePage();
+ }
+
+
+ wxPreviewControlBar * const m_preview;
+
+ int m_minPage,
+ m_maxPage;
+
+ // This is the last valid page value that we had, we revert to it if an
+ // invalid page is entered.
+ int m_page;
+
+ wxDECLARE_NO_COPY_CLASS(wxPrintPageTextCtrl);
+};
+
+//----------------------------------------------------------------------------
+// wxPreviewControlBar
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxPreviewControlBar, wxWindow)
+
+BEGIN_EVENT_TABLE(wxPreviewControlBar, wxPanel)
+ EVT_BUTTON(wxID_PREVIEW_CLOSE, wxPreviewControlBar::OnWindowClose)
+ EVT_BUTTON(wxID_PREVIEW_PRINT, wxPreviewControlBar::OnPrintButton)
+ EVT_BUTTON(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnPreviousButton)
+ EVT_BUTTON(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnNextButton)
+ EVT_BUTTON(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnFirstButton)
+ EVT_BUTTON(wxID_PREVIEW_LAST, wxPreviewControlBar::OnLastButton)
+ EVT_BUTTON(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnZoomInButton)
+ EVT_BUTTON(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnZoomOutButton)
+
+ EVT_UPDATE_UI(wxID_PREVIEW_PREVIOUS, wxPreviewControlBar::OnUpdatePreviousButton)
+ EVT_UPDATE_UI(wxID_PREVIEW_NEXT, wxPreviewControlBar::OnUpdateNextButton)
+ EVT_UPDATE_UI(wxID_PREVIEW_FIRST, wxPreviewControlBar::OnUpdateFirstButton)
+ EVT_UPDATE_UI(wxID_PREVIEW_LAST, wxPreviewControlBar::OnUpdateLastButton)
+ EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_IN, wxPreviewControlBar::OnUpdateZoomInButton)
+ EVT_UPDATE_UI(wxID_PREVIEW_ZOOM_OUT, wxPreviewControlBar::OnUpdateZoomOutButton)
+
+ EVT_CHOICE(wxID_PREVIEW_ZOOM, wxPreviewControlBar::OnZoomChoice)
+ EVT_PAINT(wxPreviewControlBar::OnPaint)
+
+END_EVENT_TABLE()
+
+wxPreviewControlBar::wxPreviewControlBar(wxPrintPreviewBase *preview, long buttons,
+ wxWindow *parent, const wxPoint& pos, const wxSize& size,
+ long style, const wxString& name):
+wxPanel(parent, wxID_ANY, pos, size, style, name)
+{
+ m_printPreview = preview;
+ m_closeButton = NULL;
+ m_zoomControl = NULL;
+ m_currentPageText = NULL;
+ m_maxPageText = NULL;
+ m_buttonFlags = buttons;
+}
+
+wxPreviewControlBar::~wxPreviewControlBar()
+{
+}
+
+void wxPreviewControlBar::OnPaint(wxPaintEvent& WXUNUSED(event))
+{
+ wxPaintDC dc(this);
+
+ int w, h;
+ GetSize(&w, &h);
+ dc.SetPen(*wxBLACK_PEN);
+ dc.SetBrush(*wxTRANSPARENT_BRUSH);
+ dc.DrawLine( 0, h-1, w, h-1 );
+}
+
+void wxPreviewControlBar::OnWindowClose(wxCommandEvent& WXUNUSED(event))
+{
+ wxPreviewFrame *frame = (wxPreviewFrame *)GetParent();
+ frame->Close(true);
+}
+
+void wxPreviewControlBar::OnPrint(void)
+{
+ wxPrintPreviewBase *preview = GetPrintPreview();
+ preview->Print(true);
+}
+
+void wxPreviewControlBar::OnNext()
+{
+ if ( IsNextEnabled() )
+ DoGotoPage(GetPrintPreview()->GetCurrentPage() + 1);
+}
+
+void wxPreviewControlBar::OnPrevious()
+{
+ if ( IsPreviousEnabled() )
+ DoGotoPage(GetPrintPreview()->GetCurrentPage() - 1);
+}
+
+void wxPreviewControlBar::OnFirst()
+{
+ if ( IsFirstEnabled() )
+ DoGotoPage(GetPrintPreview()->GetMinPage());
+}
+
+void wxPreviewControlBar::OnLast()
+{
+ if ( IsLastEnabled() )
+ DoGotoPage(GetPrintPreview()->GetMaxPage());
+}
+
+bool wxPreviewControlBar::IsNextEnabled() const
+{
+ wxPrintPreviewBase *preview = GetPrintPreview();
+ if ( !preview )
+ return false;
+
+ const int currentPage = preview->GetCurrentPage();
+ return currentPage < preview->GetMaxPage() &&
+ preview->GetPrintout()->HasPage(currentPage + 1);
+}
+
+bool wxPreviewControlBar::IsPreviousEnabled() const
+{
+ wxPrintPreviewBase *preview = GetPrintPreview();
+ if ( !preview )
+ return false;
+
+ const int currentPage = preview->GetCurrentPage();
+ return currentPage > preview->GetMinPage() &&
+ preview->GetPrintout()->HasPage(currentPage - 1);
+}
+
+bool wxPreviewControlBar::IsFirstEnabled() const
+{
+ wxPrintPreviewBase *preview = GetPrintPreview();
+ if (!preview)
+ return false;
+
+ return preview->GetPrintout()->HasPage(preview->GetMinPage());
+}
+
+bool wxPreviewControlBar::IsLastEnabled() const
+{
+ wxPrintPreviewBase *preview = GetPrintPreview();
+ if (!preview)
+ return false;
+
+ return preview->GetPrintout()->HasPage(preview->GetMaxPage());
+}
+
+void wxPreviewControlBar::DoGotoPage(int page)
+{
+ wxPrintPreviewBase *preview = GetPrintPreview();
+ wxCHECK_RET( preview, "Shouldn't be called if there is no preview." );
+
+ preview->SetCurrentPage(page);
+
+ if ( m_currentPageText )
+ m_currentPageText->SetPageNumber(page);
+}
+
+void wxPreviewControlBar::OnGotoPage()
+{
+ wxPrintPreviewBase *preview = GetPrintPreview();
+ if (preview)
+ {
+ if (preview->GetMinPage() > 0)
+ {
+ long currentPage = m_currentPageText->GetPageNumber();
+ if ( currentPage )
+ {
+ if (preview->GetPrintout()->HasPage(currentPage))
+ {
+ preview->SetCurrentPage(currentPage);
+ }
+ }
+ }
+ }
+}
+
+void wxPreviewControlBar::DoZoom()
+{
+ int zoom = GetZoomControl();
+ if (GetPrintPreview())
+ GetPrintPreview()->SetZoom(zoom);
+}
+
+bool wxPreviewControlBar::IsZoomInEnabled() const
+{
+ if ( !m_zoomControl )
+ return false;
+
+ const unsigned sel = m_zoomControl->GetSelection();
+ return sel < m_zoomControl->GetCount() - 1;
+}
+
+bool wxPreviewControlBar::IsZoomOutEnabled() const
+{
+ return m_zoomControl && m_zoomControl->GetSelection() > 0;
+}
+
+void wxPreviewControlBar::DoZoomIn()
+{
+ if (IsZoomInEnabled())
+ {
+ m_zoomControl->SetSelection(m_zoomControl->GetSelection() + 1);
+ DoZoom();
+ }
+}
+
+void wxPreviewControlBar::DoZoomOut()
+{
+ if (IsZoomOutEnabled())
+ {
+ m_zoomControl->SetSelection(m_zoomControl->GetSelection() - 1);
+ DoZoom();
+ }
+}
+
+namespace
+{
+
+// Helper class used by wxPreviewControlBar::CreateButtons() to add buttons
+// sequentially to it in the simplest way possible.
+class SizerWithButtons
+{
+public:
+ // Constructor creates the sizer that will hold the buttons and stores the
+ // parent that will be used for their creation.
+ SizerWithButtons(wxWindow *parent)
+ : m_sizer(new wxBoxSizer(wxHORIZONTAL)),
+ m_parent(parent)
+ {
+ m_hasContents =
+ m_needsSeparator = false;
+ }
+
+ // Destructor associates the sizer with the parent window.
+ ~SizerWithButtons()
+ {
+ m_parent->SetSizer(m_sizer);
+ m_sizer->Fit(m_parent);
+ }
+
+
+ // Add an arbitrary window to the sizer.
+ void Add(wxWindow *win)
+ {
+ if ( m_needsSeparator )
+ {
+ m_needsSeparator = false;
+
+ m_sizer->AddSpacer(2*wxSizerFlags::GetDefaultBorder());
+ }
+
+ m_hasContents = true;
+
+ m_sizer->Add(win,
+ wxSizerFlags().Border(wxLEFT | wxTOP | wxBOTTOM).Center());
+ }
+
+ // Add a button with the specified id, bitmap and tooltip.
+ void AddButton(wxWindowID btnId,
+ const wxArtID& artId,
+ const wxString& tooltip)
+ {
+ // We don't use (smaller) images inside a button with a text label but
+ // rather toolbar-like bitmap buttons hence use wxART_TOOLBAR and not
+ // wxART_BUTTON here.
+ wxBitmap bmp = wxArtProvider::GetBitmap(artId, wxART_TOOLBAR);
+ wxBitmapButton * const btn = new wxBitmapButton(m_parent, btnId, bmp);
+ btn->SetToolTip(tooltip);
+
+ Add(btn);
+ }
+
+ // Add a control at the right end of the window. This should be called last
+ // as everything else added after it will be added on the right side too.
+ void AddAtEnd(wxWindow *win)
+ {
+ m_sizer->AddStretchSpacer();
+ m_sizer->Add(win,
+ wxSizerFlags().Border(wxTOP | wxBOTTOM | wxRIGHT).Center());
+ }
+
+ // Indicates the end of a group of buttons, a separator will be added after
+ // it.
+ void EndOfGroup()
+ {
+ if ( m_hasContents )
+ {
+ m_needsSeparator = true;
+ m_hasContents = false;
+ }
+ }
+
+private:
+ wxSizer * const m_sizer;
+ wxWindow * const m_parent;
+
+ // If true, we have some controls since the last group beginning. This is
+ // used to avoid inserting two consecutive separators if EndOfGroup() is
+ // called twice.
+ bool m_hasContents;
+
+ // If true, a separator should be inserted before adding the next button.
+ bool m_needsSeparator;
+
+ wxDECLARE_NO_COPY_CLASS(SizerWithButtons);
+};
+
+} // anonymous namespace
+
+void wxPreviewControlBar::CreateButtons()
+{
+ SizerWithButtons sizer(this);
+
+ // Print button group (a single button).
+ if (m_buttonFlags & wxPREVIEW_PRINT)
+ {
+ sizer.AddButton(wxID_PREVIEW_PRINT, wxART_PRINT, _("Print"));
+ sizer.EndOfGroup();
+ }
+
+ // Page selection buttons group.
+ if (m_buttonFlags & wxPREVIEW_FIRST)
+ {
+ sizer.AddButton(wxID_PREVIEW_FIRST, wxART_GOTO_FIRST, _("First page"));
+ }
+
+ if (m_buttonFlags & wxPREVIEW_PREVIOUS)
+ {
+ sizer.AddButton(wxID_PREVIEW_PREVIOUS, wxART_GO_BACK, _("Previous page"));
+ }
+
+ if (m_buttonFlags & wxPREVIEW_GOTO)
+ {
+ m_currentPageText = new wxPrintPageTextCtrl(this);
+ sizer.Add(m_currentPageText);
+
+ m_maxPageText = new wxPrintPageMaxCtrl(this);
+ sizer.Add(m_maxPageText);
+ }
+
+ if (m_buttonFlags & wxPREVIEW_NEXT)
+ {
+ sizer.AddButton(wxID_PREVIEW_NEXT, wxART_GO_FORWARD, _("Next page"));
+ }
+
+ if (m_buttonFlags & wxPREVIEW_LAST)
+ {
+ sizer.AddButton(wxID_PREVIEW_LAST, wxART_GOTO_LAST, _("Last page"));
+ }
+
+ sizer.EndOfGroup();
+
+ // Zoom controls group.
+ if (m_buttonFlags & wxPREVIEW_ZOOM)
+ {
+ sizer.AddButton(wxID_PREVIEW_ZOOM_OUT, wxART_MINUS, _("Zoom Out"));
+
+ wxString choices[] =
+ {
+ wxT("10%"), wxT("15%"), wxT("20%"), wxT("25%"), wxT("30%"), wxT("35%"), wxT("40%"), wxT("45%"), wxT("50%"), wxT("55%"),
+ wxT("60%"), wxT("65%"), wxT("70%"), wxT("75%"), wxT("80%"), wxT("85%"), wxT("90%"), wxT("95%"), wxT("100%"), wxT("110%"),
+ wxT("120%"), wxT("150%"), wxT("200%")
+ };
+ int n = WXSIZEOF(choices);
+
+ m_zoomControl = new wxChoice( this, wxID_PREVIEW_ZOOM, wxDefaultPosition, wxSize(70,wxDefaultCoord), n, choices, 0 );
+ sizer.Add(m_zoomControl);
+ SetZoomControl(m_printPreview->GetZoom());
+
+ sizer.AddButton(wxID_PREVIEW_ZOOM_IN, wxART_PLUS, _("Zoom In"));
+
+ sizer.EndOfGroup();
+ }
+
+ // Close button group (single button again).
+ m_closeButton = new wxButton(this, wxID_PREVIEW_CLOSE, _("&Close"));
+ sizer.AddAtEnd(m_closeButton);
+}
+
+void wxPreviewControlBar::SetPageInfo(int minPage, int maxPage)
+{
+ if ( m_currentPageText )
+ m_currentPageText->SetPageInfo(minPage, maxPage);
+
+ if ( m_maxPageText )
+ m_maxPageText->SetMaxPage(maxPage);
+}
+
+void wxPreviewControlBar::SetZoomControl(int zoom)
+{
+ if (m_zoomControl)
+ {
+ int n, count = m_zoomControl->GetCount();
+ long val;
+ for (n=0; n<count; n++)
+ {
+ if (m_zoomControl->GetString(n).BeforeFirst(wxT('%')).ToLong(&val) &&
+ (val >= long(zoom)))
+ {
+ m_zoomControl->SetSelection(n);
+ return;
+ }
+ }
+
+ m_zoomControl->SetSelection(count-1);
+ }
+}
+
+int wxPreviewControlBar::GetZoomControl()
+{
+ if (m_zoomControl && (m_zoomControl->GetStringSelection() != wxEmptyString))
+ {
+ long val;
+ if (m_zoomControl->GetStringSelection().BeforeFirst(wxT('%')).ToLong(&val))
+ return int(val);
+ }
+
+ return 0;
+}
+
+
+/*
+* Preview frame
+*/
+
+IMPLEMENT_CLASS(wxPreviewFrame, wxFrame)
+
+BEGIN_EVENT_TABLE(wxPreviewFrame, wxFrame)
+ EVT_CHAR_HOOK(wxPreviewFrame::OnChar)
+ EVT_CLOSE(wxPreviewFrame::OnCloseWindow)
+END_EVENT_TABLE()
+
+void wxPreviewFrame::OnChar(wxKeyEvent &event)
+{
+ if ( event.GetKeyCode() == WXK_ESCAPE )
+ {
+ Close(true);
+ }
+ else
+ {
+ event.Skip();
+ }
+}
+
+wxPreviewFrame::wxPreviewFrame(wxPrintPreviewBase *preview, wxWindow *parent, const wxString& title,
+ const wxPoint& pos, const wxSize& size, long style, const wxString& name):
+wxFrame(parent, wxID_ANY, title, pos, size, style, name)
+{
+ m_printPreview = preview;
+ m_controlBar = NULL;
+ m_previewCanvas = NULL;
+ m_windowDisabler = NULL;
+ m_modalityKind = wxPreviewFrame_NonModal;
+
+ // Give the application icon
+#ifdef __WXMSW__
+ wxFrame* topFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
+ if (topFrame)
+ SetIcons(topFrame->GetIcons());
+#endif
+}
+
+wxPreviewFrame::~wxPreviewFrame()
+{
+ wxPrintout *printout = m_printPreview->GetPrintout();
+ if (printout)
+ {
+ delete printout;
+ m_printPreview->SetPrintout(NULL);
+ m_printPreview->SetCanvas(NULL);
+ m_printPreview->SetFrame(NULL);
+ }
+
+ m_previewCanvas->SetPreview(NULL);
+ delete m_printPreview;
+}
+
+void wxPreviewFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
+{
+ // Reenable any windows we disabled by undoing whatever we did in our
+ // Initialize().
+ switch ( m_modalityKind )
+ {
+ case wxPreviewFrame_AppModal:
+ delete m_windowDisabler;
+ m_windowDisabler = NULL;
+ break;
+
+ case wxPreviewFrame_WindowModal:
+ if ( GetParent() )
+ GetParent()->Enable();
+ break;
+
+ case wxPreviewFrame_NonModal:
+ break;
+ }
+
+ Destroy();
+}
+
+void wxPreviewFrame::InitializeWithModality(wxPreviewFrameModalityKind kind)
+{
+#if wxUSE_STATUSBAR
+ CreateStatusBar();
+#endif
+ CreateCanvas();
+ CreateControlBar();
+
+ m_printPreview->SetCanvas(m_previewCanvas);
+ m_printPreview->SetFrame(this);
+
+ wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
+
+ item0->Add( m_controlBar, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
+ item0->Add( m_previewCanvas, 1, wxGROW|wxALIGN_CENTER_VERTICAL, 5 );
+
+ SetAutoLayout( true );
+ SetSizer( item0 );
+
+ m_modalityKind = kind;
+ switch ( m_modalityKind )
+ {
+ case wxPreviewFrame_AppModal:
+ // Disable everything.
+ m_windowDisabler = new wxWindowDisabler( this );
+ break;
+
+ case wxPreviewFrame_WindowModal:
+ // Disable our parent if we have one.
+ if ( GetParent() )
+ GetParent()->Disable();
+ break;
+
+ case wxPreviewFrame_NonModal:
+ // Nothing to do, we don't need to disable any windows.
+ break;
+ }
+
+
+ Layout();
+
+ m_printPreview->AdjustScrollbars(m_previewCanvas);
+ m_previewCanvas->SetFocus();
+ m_controlBar->SetFocus();
+}
+
+void wxPreviewFrame::CreateCanvas()
+{
+ m_previewCanvas = new wxPreviewCanvas(m_printPreview, this);
+}
+
+void wxPreviewFrame::CreateControlBar()
+{
+ long buttons = wxPREVIEW_DEFAULT;
+ if (m_printPreview->GetPrintoutForPrinting())
+ buttons |= wxPREVIEW_PRINT;
+
+ m_controlBar = new wxPreviewControlBar(m_printPreview, buttons, this);
+ m_controlBar->CreateButtons();
+}
+
+/*
+* Print preview
+*/
+
+IMPLEMENT_CLASS(wxPrintPreviewBase, wxObject)
+
+wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
+ wxPrintout *printoutForPrinting,
+ wxPrintData *data)
+{
+ if (data)
+ m_printDialogData = (*data);
+
+ Init(printout, printoutForPrinting);
+}
+
+wxPrintPreviewBase::wxPrintPreviewBase(wxPrintout *printout,
+ wxPrintout *printoutForPrinting,
+ wxPrintDialogData *data)
+{
+ if (data)
+ m_printDialogData = (*data);
+
+ Init(printout, printoutForPrinting);
+}
+
+void wxPrintPreviewBase::Init(wxPrintout *printout,
+ wxPrintout *printoutForPrinting)
+{
+ m_isOk = true;
+ m_previewPrintout = printout;
+ if (m_previewPrintout)
+ m_previewPrintout->SetPreview(static_cast<wxPrintPreview *>(this));
+
+ m_printPrintout = printoutForPrinting;
+
+ m_previewCanvas = NULL;
+ m_previewFrame = NULL;
+ m_previewBitmap = NULL;
+ m_previewFailed = false;
+ m_currentPage = 1;
+ m_currentZoom = 70;
+ m_topMargin =
+ m_leftMargin = 2*wxSizerFlags::GetDefaultBorder();
+ m_pageWidth = 0;
+ m_pageHeight = 0;
+ m_printingPrepared = false;
+ m_minPage = 1;
+ m_maxPage = 1;
+}
+
+wxPrintPreviewBase::~wxPrintPreviewBase()
+{
+ if (m_previewPrintout)
+ delete m_previewPrintout;
+ if (m_previewBitmap)
+ delete m_previewBitmap;
+ if (m_printPrintout)
+ delete m_printPrintout;
+}
+
+bool wxPrintPreviewBase::SetCurrentPage(int pageNum)
+{
+ if (m_currentPage == pageNum)
+ return true;
+
+ m_currentPage = pageNum;
+
+ InvalidatePreviewBitmap();
+
+ if (m_previewCanvas)
+ {
+ AdjustScrollbars(m_previewCanvas);
+
+ m_previewCanvas->Refresh();
+ m_previewCanvas->SetFocus();
+ }
+ return true;
+}
+
+int wxPrintPreviewBase::GetCurrentPage() const
+ { return m_currentPage; }
+void wxPrintPreviewBase::SetPrintout(wxPrintout *printout)
+ { m_previewPrintout = printout; }
+wxPrintout *wxPrintPreviewBase::GetPrintout() const
+ { return m_previewPrintout; }
+wxPrintout *wxPrintPreviewBase::GetPrintoutForPrinting() const
+ { return m_printPrintout; }
+void wxPrintPreviewBase::SetFrame(wxFrame *frame)
+ { m_previewFrame = frame; }
+void wxPrintPreviewBase::SetCanvas(wxPreviewCanvas *canvas)
+ { m_previewCanvas = canvas; }
+wxFrame *wxPrintPreviewBase::GetFrame() const
+ { return m_previewFrame; }
+wxPreviewCanvas *wxPrintPreviewBase::GetCanvas() const
+ { return m_previewCanvas; }
+
+void wxPrintPreviewBase::CalcRects(wxPreviewCanvas *canvas, wxRect& pageRect, wxRect& paperRect)
+{
+ // Calculate the rectangles for the printable area of the page and the
+ // entire paper as they appear on the canvas on-screen.
+ int canvasWidth, canvasHeight;
+ canvas->GetSize(&canvasWidth, &canvasHeight);
+
+ float zoomScale = float(m_currentZoom) / 100;
+ float screenPrintableWidth = zoomScale * m_pageWidth * m_previewScaleX;
+ float screenPrintableHeight = zoomScale * m_pageHeight * m_previewScaleY;
+
+ wxRect devicePaperRect = m_previewPrintout->GetPaperRectPixels();
+ wxCoord devicePrintableWidth, devicePrintableHeight;
+ m_previewPrintout->GetPageSizePixels(&devicePrintableWidth, &devicePrintableHeight);
+ float scaleX = screenPrintableWidth / devicePrintableWidth;
+ float scaleY = screenPrintableHeight / devicePrintableHeight;
+ paperRect.width = wxCoord(scaleX * devicePaperRect.width);
+ paperRect.height = wxCoord(scaleY * devicePaperRect.height);
+
+ paperRect.x = wxCoord((canvasWidth - paperRect.width)/ 2.0);
+ if (paperRect.x < m_leftMargin)
+ paperRect.x = m_leftMargin;
+ paperRect.y = wxCoord((canvasHeight - paperRect.height)/ 2.0);
+ if (paperRect.y < m_topMargin)
+ paperRect.y = m_topMargin;
+
+ pageRect.x = paperRect.x - wxCoord(scaleX * devicePaperRect.x);
+ pageRect.y = paperRect.y - wxCoord(scaleY * devicePaperRect.y);
+ pageRect.width = wxCoord(screenPrintableWidth);
+ pageRect.height = wxCoord(screenPrintableHeight);
+}
+
+
+void wxPrintPreviewBase::InvalidatePreviewBitmap()
+{
+ wxDELETE(m_previewBitmap);
+ // if there was a problem with rendering the preview, try again now
+ // that it changed in some way (less memory may be needed, for example):
+ m_previewFailed = false;
+}
+
+bool wxPrintPreviewBase::UpdatePageRendering()
+{
+ if ( m_previewBitmap )
+ return false;
+
+ if ( m_previewFailed )
+ return false;
+
+ if ( !RenderPage(m_currentPage) )
+ {
+ m_previewFailed = true; // don't waste time failing again
+ return false;
+ }
+
+ return true;
+}
+
+bool wxPrintPreviewBase::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
+{
+ DrawBlankPage(canvas, dc);
+
+ if (!m_previewBitmap)
+ return false;
+ if (!canvas)
+ return false;
+
+ wxRect pageRect, paperRect;
+ CalcRects(canvas, pageRect, paperRect);
+ wxMemoryDC temp_dc;
+ temp_dc.SelectObject(*m_previewBitmap);
+
+ dc.Blit(pageRect.x, pageRect.y,
+ m_previewBitmap->GetWidth(), m_previewBitmap->GetHeight(), &temp_dc, 0, 0);
+
+ temp_dc.SelectObject(wxNullBitmap);
+ return true;
+}
+
+// Adjusts the scrollbars for the current scale
+void wxPrintPreviewBase::AdjustScrollbars(wxPreviewCanvas *canvas)
+{
+ if (!canvas)
+ return ;
+
+ wxRect pageRect, paperRect;
+ CalcRects(canvas, pageRect, paperRect);
+ int totalWidth = paperRect.width + 2 * m_leftMargin;
+ int totalHeight = paperRect.height + 2 * m_topMargin;
+ int scrollUnitsX = totalWidth / 10;
+ int scrollUnitsY = totalHeight / 10;
+ wxSize virtualSize = canvas->GetVirtualSize();
+ if (virtualSize.GetWidth() != totalWidth || virtualSize.GetHeight() != totalHeight)
+ canvas->SetScrollbars(10, 10, scrollUnitsX, scrollUnitsY, 0, 0, true);
+}
+
+bool wxPrintPreviewBase::RenderPageIntoDC(wxDC& dc, int pageNum)
+{
+ m_previewPrintout->SetDC(&dc);
+ m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
+
+ // Need to delay OnPreparePrinting() until here, so we have enough
+ // information and a wxDC.
+ if (!m_printingPrepared)
+ {
+ m_printingPrepared = true;
+
+ m_previewPrintout->OnPreparePrinting();
+ int selFrom, selTo;
+ m_previewPrintout->GetPageInfo(&m_minPage, &m_maxPage, &selFrom, &selTo);
+
+ // Update the wxPreviewControlBar page range display.
+ if ( m_previewFrame )
+ {
+ wxPreviewControlBar * const
+ controlBar = ((wxPreviewFrame*)m_previewFrame)->GetControlBar();
+ if ( controlBar )
+ controlBar->SetPageInfo(m_minPage, m_maxPage);
+ }
+ }
+
+ m_previewPrintout->OnBeginPrinting();
+
+ if (!m_previewPrintout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
+ {
+ wxMessageBox(_("Could not start document preview."), _("Print Preview Failure"), wxOK);
+ return false;
+ }
+
+ m_previewPrintout->OnPrintPage(pageNum);
+ m_previewPrintout->OnEndDocument();
+ m_previewPrintout->OnEndPrinting();
+
+ m_previewPrintout->SetDC(NULL);
+
+ return true;
+}
+
+bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap& bmp, int pageNum)
+{
+ wxMemoryDC memoryDC;
+ memoryDC.SelectObject(bmp);
+ memoryDC.Clear();
+
+ return RenderPageIntoDC(memoryDC, pageNum);
+}
+
+bool wxPrintPreviewBase::RenderPage(int pageNum)
+{
+ wxBusyCursor busy;
+
+ if (!m_previewCanvas)
+ {
+ wxFAIL_MSG(wxT("wxPrintPreviewBase::RenderPage: must use wxPrintPreviewBase::SetCanvas to let me know about the canvas!"));
+ return false;
+ }
+
+ wxRect pageRect, paperRect;
+ CalcRects(m_previewCanvas, pageRect, paperRect);
+
+ if (!m_previewBitmap)
+ {
+ m_previewBitmap = new wxBitmap(pageRect.width, pageRect.height);
+
+ if (!m_previewBitmap || !m_previewBitmap->IsOk())
+ {
+ InvalidatePreviewBitmap();
+ wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
+ return false;
+ }
+ }
+
+ if ( !RenderPageIntoBitmap(*m_previewBitmap, pageNum) )
+ {
+ InvalidatePreviewBitmap();
+ wxMessageBox(_("Sorry, not enough memory to create a preview."), _("Print Preview Failure"), wxOK);
+ return false;
+ }
+
+#if wxUSE_STATUSBAR
+ wxString status;
+ if (m_maxPage != 0)
+ status = wxString::Format(_("Page %d of %d"), pageNum, m_maxPage);
+ else
+ status = wxString::Format(_("Page %d"), pageNum);
+
+ if (m_previewFrame)
+ m_previewFrame->SetStatusText(status);
+#endif
+
+ return true;
+}
+
+bool wxPrintPreviewBase::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
+{
+ wxRect pageRect, paperRect;
+
+ CalcRects(canvas, pageRect, paperRect);
+
+ // Draw shadow, allowing for 1-pixel border AROUND the actual paper
+ wxCoord shadowOffset = 4;
+
+ dc.SetPen(*wxBLACK_PEN);
+ dc.SetBrush(*wxBLACK_BRUSH);
+ dc.DrawRectangle(paperRect.x + shadowOffset, paperRect.y + paperRect.height + 1,
+ paperRect.width, shadowOffset);
+
+ dc.DrawRectangle(paperRect.x + paperRect.width, paperRect.y + shadowOffset,
+ shadowOffset, paperRect.height);
+
+ // Draw blank page allowing for 1-pixel border AROUND the actual paper
+ dc.SetPen(*wxBLACK_PEN);
+ dc.SetBrush(*wxWHITE_BRUSH);
+ dc.DrawRectangle(paperRect.x - 2, paperRect.y - 1,
+ paperRect.width + 3, paperRect.height + 2);
+
+ return true;
+}
+
+void wxPrintPreviewBase::SetZoom(int percent)
+{
+ if (m_currentZoom == percent)
+ return;
+
+ m_currentZoom = percent;
+
+ InvalidatePreviewBitmap();
+
+ if (m_previewCanvas)
+ {
+ AdjustScrollbars(m_previewCanvas);
+ ((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
+ m_previewCanvas->ClearBackground();
+ m_previewCanvas->Refresh();
+ m_previewCanvas->SetFocus();
+ }
+}
+
+wxPrintDialogData& wxPrintPreviewBase::GetPrintDialogData()
+{
+ return m_printDialogData;
+}
+
+int wxPrintPreviewBase::GetZoom() const
+{ return m_currentZoom; }
+int wxPrintPreviewBase::GetMaxPage() const
+{ return m_maxPage; }
+int wxPrintPreviewBase::GetMinPage() const
+{ return m_minPage; }
+bool wxPrintPreviewBase::IsOk() const
+{ return m_isOk; }
+void wxPrintPreviewBase::SetOk(bool ok)
+{ m_isOk = ok; }
+
+//----------------------------------------------------------------------------
+// wxPrintPreview
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxPrintPreview, wxPrintPreviewBase)
+
+wxPrintPreview::wxPrintPreview(wxPrintout *printout,
+ wxPrintout *printoutForPrinting,
+ wxPrintDialogData *data) :
+ wxPrintPreviewBase( printout, printoutForPrinting, data )
+{
+ m_pimpl = wxPrintFactory::GetFactory()->
+ CreatePrintPreview( printout, printoutForPrinting, data );
+}
+
+wxPrintPreview::wxPrintPreview(wxPrintout *printout,
+ wxPrintout *printoutForPrinting,
+ wxPrintData *data ) :
+ wxPrintPreviewBase( printout, printoutForPrinting, data )
+{
+ m_pimpl = wxPrintFactory::GetFactory()->
+ CreatePrintPreview( printout, printoutForPrinting, data );
+}
+
+wxPrintPreview::~wxPrintPreview()
+{
+ delete m_pimpl;
+
+ // don't delete twice
+ m_printPrintout = NULL;
+ m_previewPrintout = NULL;
+ m_previewBitmap = NULL;
+}
+
+bool wxPrintPreview::SetCurrentPage(int pageNum)
+{
+ return m_pimpl->SetCurrentPage( pageNum );
+}
+
+int wxPrintPreview::GetCurrentPage() const
+{
+ return m_pimpl->GetCurrentPage();
+}
+
+void wxPrintPreview::SetPrintout(wxPrintout *printout)
+{
+ m_pimpl->SetPrintout( printout );
+}
+
+wxPrintout *wxPrintPreview::GetPrintout() const
+{
+ return m_pimpl->GetPrintout();
+}
+
+wxPrintout *wxPrintPreview::GetPrintoutForPrinting() const
+{
+ return m_pimpl->GetPrintoutForPrinting();
+}
+
+void wxPrintPreview::SetFrame(wxFrame *frame)
+{
+ m_pimpl->SetFrame( frame );
+}
+
+void wxPrintPreview::SetCanvas(wxPreviewCanvas *canvas)
+{
+ m_pimpl->SetCanvas( canvas );
+}
+
+wxFrame *wxPrintPreview::GetFrame() const
+{
+ return m_pimpl->GetFrame();
+}
+
+wxPreviewCanvas *wxPrintPreview::GetCanvas() const
+{
+ return m_pimpl->GetCanvas();
+}
+
+bool wxPrintPreview::PaintPage(wxPreviewCanvas *canvas, wxDC& dc)
+{
+ return m_pimpl->PaintPage( canvas, dc );
+}
+
+bool wxPrintPreview::UpdatePageRendering()
+{
+ return m_pimpl->UpdatePageRendering();
+}
+
+bool wxPrintPreview::DrawBlankPage(wxPreviewCanvas *canvas, wxDC& dc)
+{
+ return m_pimpl->DrawBlankPage( canvas, dc );
+}
+
+void wxPrintPreview::AdjustScrollbars(wxPreviewCanvas *canvas)
+{
+ m_pimpl->AdjustScrollbars( canvas );
+}
+
+bool wxPrintPreview::RenderPage(int pageNum)
+{
+ return m_pimpl->RenderPage( pageNum );
+}
+
+void wxPrintPreview::SetZoom(int percent)
+{
+ m_pimpl->SetZoom( percent );
+}
+
+int wxPrintPreview::GetZoom() const
+{
+ return m_pimpl->GetZoom();
+}
+
+wxPrintDialogData& wxPrintPreview::GetPrintDialogData()
+{
+ return m_pimpl->GetPrintDialogData();
+}
+
+int wxPrintPreview::GetMaxPage() const
+{
+ return m_pimpl->GetMaxPage();
+}
+
+int wxPrintPreview::GetMinPage() const
+{
+ return m_pimpl->GetMinPage();
+}
+
+bool wxPrintPreview::IsOk() const
+{
+ return m_pimpl->IsOk();
+}
+
+void wxPrintPreview::SetOk(bool ok)
+{
+ m_pimpl->SetOk( ok );
+}
+
+bool wxPrintPreview::Print(bool interactive)
+{
+ return m_pimpl->Print( interactive );
+}
+
+void wxPrintPreview::DetermineScaling()
+{
+ m_pimpl->DetermineScaling();
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE