+namespace
+{
+
+// This is by the controls in the print preview as the maximal (and hence
+// longest) page number we may have to display.
+enum { MAX_PAGE_NUMBER = 99999 };
+
+} // anonymous namespace
+
+// ----------------------------------------------------------------------------
+// wxPrintPageMaxCtrl
+// ----------------------------------------------------------------------------
+
+// A simple static control showing the maximal number of pages.
+class wxPrintPageMaxCtrl : public wxStaticText
+{
+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_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);
+};
+