+#endif // USE_LOG
+
+#if wxUSE_MENUS
+
+void WidgetsFrame::OnPageChanging(WidgetsBookCtrlEvent& event)
+{
+#if USE_TREEBOOK
+ // don't allow selection of entries without pages (categories)
+ if ( !m_book->GetPage(event.GetSelection()) )
+ event.Veto();
+#else
+ wxUnusedVar(event);
+#endif
+}
+
+void WidgetsFrame::OnPageChanged(WidgetsBookCtrlEvent& event)
+{
+ const int sel = event.GetSelection();
+
+ // adjust "Page" menu selection
+ wxMenuItem *item = GetMenuBar()->FindItem(Widgets_GoToPage + sel);
+ if ( item )
+ item->Check();
+
+ GetMenuBar()->Check(Widgets_BusyCursor, false);
+
+ // create the pages on demand, otherwise the sample startup is too slow as
+ // it creates hundreds of controls
+ WidgetsPage *page = CurrentPage();
+ if ( page->GetChildren().empty() )
+ {
+ wxWindowUpdateLocker noUpdates(page);
+ page->CreateContent();
+ //page->Layout();
+ page->GetSizer()->Fit(page);
+
+ WidgetsBookCtrl *book = wxStaticCast(page->GetParent(), WidgetsBookCtrl);
+ wxSize size;
+ for ( size_t i = 0; i < book->GetPageCount(); ++i )
+ {
+ wxWindow *page = book->GetPage(i);
+ if ( page )
+ {
+ size.IncTo(page->GetSize());
+ }
+ }
+ page->SetSize(size);
+ }
+
+ event.Skip();
+}
+
+void WidgetsFrame::OnGoToPage(wxCommandEvent& event)
+{
+#if USE_TREEBOOK
+ m_book->SetSelection(event.GetId() - Widgets_GoToPage);
+#else
+ m_book->SetSelection(m_book->GetPageCount()-1);
+ WidgetsBookCtrl *book = wxStaticCast(m_book->GetCurrentPage(), WidgetsBookCtrl);
+ book->SetSelection(event.GetId() - Widgets_GoToPage);
+#endif
+}
+
+#if wxUSE_TOOLTIPS
+
+void WidgetsFrame::OnSetTooltip(wxCommandEvent& WXUNUSED(event))
+{
+ static wxString s_tip = wxT("This is a tooltip");
+
+ wxTextEntryDialog dialog
+ (
+ this,
+ wxT("Tooltip text (may use \\n, leave empty to remove): "),
+ wxT("Widgets sample"),
+ s_tip
+ );
+
+ if ( dialog.ShowModal() != wxID_OK )
+ return;
+
+ s_tip = dialog.GetValue();
+ s_tip.Replace(wxT("\\n"), wxT("\n"));
+
+ WidgetsPage *page = CurrentPage();
+
+ const Widgets widgets = page->GetWidgets();
+ for ( Widgets::const_iterator it = widgets.begin();
+ it != widgets.end();
+ ++it )
+ {
+ (*it)->SetToolTip(s_tip);
+ }
+}
+
+#endif // wxUSE_TOOLTIPS
+
+namespace
+{
+
+// Trivial wrapper for wxGetColourFromUser() which also does something even if
+// the colour dialog is not available in the current build (which may happen
+// for the ports in development and it is still useful to see how colours work)
+wxColour GetColourFromUser(wxWindow *parent, const wxColour& colDefault)
+{
+#if wxUSE_COLOURDLG
+ return wxGetColourFromUser(parent, colDefault);
+#else // !wxUSE_COLOURDLG
+ if ( colDefault == *wxBLACK )
+ return *wxWHITE;
+ else
+ return *wxBLACK;
+#endif // wxUSE_COLOURDLG/!wxUSE_COLOURDLG
+}
+
+} // anonymous namespace
+
+void WidgetsFrame::OnSetFgCol(wxCommandEvent& WXUNUSED(event))
+{
+ // allow for debugging the default colour the first time this is called
+ WidgetsPage *page = CurrentPage();
+
+ if (!m_colFg.IsOk())
+ m_colFg = page->GetForegroundColour();
+
+ wxColour col = GetColourFromUser(this, m_colFg);
+ if ( !col.IsOk() )
+ return;
+
+ m_colFg = col;
+
+ const Widgets widgets = page->GetWidgets();
+ for ( Widgets::const_iterator it = widgets.begin();
+ it != widgets.end();
+ ++it )
+ {
+ (*it)->SetForegroundColour(m_colFg);
+ (*it)->Refresh();
+ }
+}
+
+void WidgetsFrame::OnSetBgCol(wxCommandEvent& WXUNUSED(event))
+{
+ WidgetsPage *page = CurrentPage();
+
+ if ( !m_colBg.IsOk() )
+ m_colBg = page->GetBackgroundColour();
+
+ wxColour col = GetColourFromUser(this, m_colBg);
+ if ( !col.IsOk() )
+ return;
+
+ m_colBg = col;
+
+ const Widgets widgets = page->GetWidgets();
+ for ( Widgets::const_iterator it = widgets.begin();
+ it != widgets.end();
+ ++it )
+ {
+ (*it)->SetBackgroundColour(m_colBg);
+ (*it)->Refresh();
+ }
+}
+
+void WidgetsFrame::OnSetPageBg(wxCommandEvent& WXUNUSED(event))
+{
+ wxColour col = GetColourFromUser(this, GetBackgroundColour());
+ if ( !col.IsOk() )
+ return;
+
+ CurrentPage()->SetBackgroundColour(col);
+ CurrentPage()->Refresh();
+}
+
+void WidgetsFrame::OnSetFont(wxCommandEvent& WXUNUSED(event))
+{
+#if wxUSE_FONTDLG
+ WidgetsPage *page = CurrentPage();
+
+ if (!m_font.IsOk())
+ m_font = page->GetFont();
+
+ wxFont font = wxGetFontFromUser(this, m_font);
+ if ( !font.IsOk() )
+ return;
+
+ m_font = font;
+
+ const Widgets widgets = page->GetWidgets();
+ for ( Widgets::const_iterator it = widgets.begin();
+ it != widgets.end();
+ ++it )
+ {
+ (*it)->SetFont(m_font);
+ (*it)->Refresh();
+ }
+#else
+ wxLogMessage(wxT("Font selection dialog not available in current build."));
+#endif
+}
+
+void WidgetsFrame::OnEnable(wxCommandEvent& event)
+{
+ const Widgets widgets = CurrentPage()->GetWidgets();
+ for ( Widgets::const_iterator it = widgets.begin();
+ it != widgets.end();
+ ++it )
+ {
+ (*it)->Enable(event.IsChecked());
+ }
+}
+
+void WidgetsFrame::OnSetBorder(wxCommandEvent& event)
+{
+ int border;
+ switch ( event.GetId() )
+ {
+ case Widgets_BorderNone: border = wxBORDER_NONE; break;
+ case Widgets_BorderStatic: border = wxBORDER_STATIC; break;
+ case Widgets_BorderSimple: border = wxBORDER_SIMPLE; break;
+ case Widgets_BorderRaised: border = wxBORDER_RAISED; break;
+ case Widgets_BorderSunken: border = wxBORDER_SUNKEN; break;
+ case Widgets_BorderDouble: border = wxBORDER_DOUBLE; break;
+
+ default:
+ wxFAIL_MSG( wxT("unknown border style") );
+ // fall through
+
+ case Widgets_BorderDefault: border = wxBORDER_DEFAULT; break;
+ }
+
+ WidgetsPage::ms_defaultFlags &= ~wxBORDER_MASK;
+ WidgetsPage::ms_defaultFlags |= border;
+
+ WidgetsPage *page = CurrentPage();
+
+ page->RecreateWidget();
+}
+
+void WidgetsFrame::OnToggleGlobalBusyCursor(wxCommandEvent& event)
+{
+ if ( event.IsChecked() )
+ wxBeginBusyCursor();
+ else
+ wxEndBusyCursor();
+}
+
+void WidgetsFrame::OnToggleBusyCursor(wxCommandEvent& event)
+{
+ wxCursor cursor(*(event.IsChecked() ? wxHOURGLASS_CURSOR
+ : wxSTANDARD_CURSOR));
+
+ const Widgets widgets = CurrentPage()->GetWidgets();
+ for ( Widgets::const_iterator it = widgets.begin();
+ it != widgets.end();
+ ++it )
+ {
+ (*it)->SetCursor(cursor);
+ }
+}
+
+void WidgetsFrame::OnDisableAutoComplete(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
+ wxCHECK_RET( entry, "menu item should be disabled" );
+
+ if ( entry->AutoComplete(wxArrayString()) )
+ {
+ wxLogMessage("Disabled auto completion.");
+ }
+ else
+ {
+ wxLogMessage("AutoComplete() failed.");
+ }
+}
+
+void WidgetsFrame::OnAutoCompleteFixed(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
+ wxCHECK_RET( entry, "menu item should be disabled" );
+
+ wxArrayString completion_choices;
+
+ // add a few strings so a completion occurs on any letter typed
+ for ( char idxc = 'a'; idxc < 'z'; ++idxc )
+ completion_choices.push_back(wxString::Format("%c%c", idxc, idxc));
+
+ completion_choices.push_back("is this string for test?");
+ completion_choices.push_back("this is a test string");
+ completion_choices.push_back("this is another test string");
+ completion_choices.push_back("this string is for test");
+
+ if ( entry->AutoComplete(completion_choices) )
+ {
+ wxLogMessage("Enabled auto completion of a set of fixed strings.");
+ }
+ else
+ {
+ wxLogMessage("AutoComplete() failed.");
+ }
+}
+
+void WidgetsFrame::OnAutoCompleteFilenames(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
+ wxCHECK_RET( entry, "menu item should be disabled" );
+
+ if ( entry->AutoCompleteFileNames() )
+ {
+ wxLogMessage("Enabled auto completion of file names.");
+ }
+ else
+ {
+ wxLogMessage("AutoCompleteFileNames() failed.");
+ }
+}
+
+void WidgetsFrame::OnAutoCompleteDirectories(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
+ wxCHECK_RET( entry, "menu item should be disabled" );
+
+ if ( entry->AutoCompleteDirectories() )
+ {
+ wxLogMessage("Enabled auto completion of directories.");
+ }
+ else
+ {
+ wxLogMessage("AutoCompleteDirectories() failed.");
+ }
+}
+
+void WidgetsFrame::OnAutoCompleteCustom(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
+ wxCHECK_RET( entry, "menu item should be disabled" );
+
+ // This is a simple (and hence rather useless) example of a custom
+ // completer class that completes the first word (only) initially and only
+ // build the list of the possible second words once the first word is
+ // known. This allows to avoid building the full 676000 item list of
+ // possible strings all at once as the we have 1000 possibilities for the
+ // first word (000..999) and 676 (aa..zz) for the second one.
+ class CustomTextCompleter : public wxTextCompleterSimple
+ {
+ public:
+ virtual void GetCompletions(const wxString& prefix, wxArrayString& res)
+ {
+ // This is used for illustrative purposes only and shows how many
+ // completions we return every time when we're called.
+ class LogCompletions
+ {
+ public:
+ LogCompletions(const wxString& prefix, const wxArrayString& res)
+ : m_prefix(prefix),
+ m_res(res)
+ {
+ }
+
+ ~LogCompletions()
+ {
+ wxLogMessage("Returning %lu possible completions for "
+ "prefix \"%s\"",
+ m_res.size(), m_prefix);
+ }
+
+ private:
+ const wxString& m_prefix;
+ const wxArrayString& m_res;
+ } logCompletions(prefix, res);
+
+
+ // Normally it doesn't make sense to complete empty control, there
+ // are too many choices and listing them all wouldn't be helpful.
+ if ( prefix.empty() )
+ return;
+
+ // The only valid strings start with 3 digits so check for their
+ // presence proposing to complete the remaining ones.
+ if ( !wxIsdigit(prefix[0]) )
+ return;
+
+ if ( prefix.length() == 1 )
+ {
+ for ( int i = 0; i < 10; i++ )
+ for ( int j = 0; j < 10; j++ )
+ res.push_back(wxString::Format("%s%02d",
+ prefix, 10*i + j));
+ return;
+ }
+ else if ( !wxIsdigit(prefix[1]) )
+ return;
+
+ if ( prefix.length() == 2 )
+ {
+ for ( int i = 0; i < 10; i++ )
+ res.push_back(wxString::Format("%s%d", prefix, i));
+ return;
+ }
+ else if ( !wxIsdigit(prefix[2]) )
+ return;
+
+ // Next we must have a space and two letters.
+ wxString prefix2(prefix);
+ if ( prefix.length() == 3 )
+ prefix2 += ' ';
+ else if ( prefix[3] != ' ' )
+ return;
+
+ if ( prefix2.length() == 4 )
+ {
+ for ( char c = 'a'; c <= 'z'; c++ )
+ for ( char d = 'a'; d <= 'z'; d++ )
+ res.push_back(wxString::Format("%s%c%c", prefix2, c, d));
+ return;
+ }
+ else if ( !wxIslower(prefix[4]) )
+ return;
+
+ if ( prefix.length() == 5 )
+ {
+ for ( char c = 'a'; c <= 'z'; c++ )
+ res.push_back(prefix + c);
+ }
+ }
+ };
+
+ if ( entry->AutoComplete(new CustomTextCompleter) )
+ {
+ wxLogMessage("Enabled custom auto completer for \"NNN XX\" items "
+ "(where N is a digit and X is a letter).");
+ }
+ else
+ {
+ wxLogMessage("AutoComplete() failed.");
+ }
+}
+
+void WidgetsFrame::OnSetHint(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
+ wxCHECK_RET( entry, "menu item should be disabled" );
+
+ static wxString s_hint("Type here");
+ wxString
+ hint = wxGetTextFromUser("Text hint:", "Widgets sample", s_hint, this);
+ if ( hint.empty() )
+ return;
+
+ s_hint = hint;
+
+ if ( entry->SetHint(hint) )
+ {
+ wxLogMessage("Set hint to \"%s\".", hint);
+ }
+ else
+ {
+ wxLogMessage("Text hints not supported.");
+ }
+}
+
+#endif // wxUSE_MENUS