diff --git a/docs/changes.txt b/docs/changes.txt index c6f30d83bc..140530df3b 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -178,6 +178,8 @@ All (GUI): - Add Set/GetFooter/Text/Icon() to wxRichMessageDialog (Tobias Taschner) - Add wxFloatingPointValidator::SetFactor(). - Add "hint" property to wxSearchCtrl XRC handler. +- Add wxEVT_SEARCH[_CANCEL] synonyms for wxSearchCtrl events. +- Generate wxEVT_SEARCH on Enter under all platforms. wxGTK: diff --git a/include/wx/compositewin.h b/include/wx/compositewin.h index 567d0e8999..c9a339ac44 100644 --- a/include/wx/compositewin.h +++ b/include/wx/compositewin.h @@ -193,7 +193,10 @@ private: if ( child == this ) return; // not a child, we don't want to Connect() to ourselves - // Always capture wxEVT_KILL_FOCUS: + child->Connect(wxEVT_SET_FOCUS, + wxFocusEventHandler(wxCompositeWindow::OnSetFocus), + NULL, this); + child->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(wxCompositeWindow::OnKillFocus), NULL, this); @@ -221,6 +224,27 @@ private: event.Skip(); } + void OnSetFocus(wxFocusEvent& event) + { + event.Skip(); + + // When a child of a composite window gains focus, the entire composite + // focus gains focus as well -- unless it had it already. + // + // We suppose that we hadn't had focus if the event doesn't carry the + // previously focused window as it normally means that it comes from + // outside of this program. + wxWindow* const oldFocus = event.GetWindow(); + if ( !oldFocus || oldFocus->GetMainWindowOfCompositeControl() != this ) + { + wxFocusEvent eventThis(wxEVT_SET_FOCUS, this->GetId()); + eventThis.SetEventObject(this); + eventThis.SetWindow(event.GetWindow()); + + this->ProcessWindowEvent(eventThis); + } + } + void OnKillFocus(wxFocusEvent& event) { // Ignore focus changes within the composite control: diff --git a/include/wx/generic/srchctlg.h b/include/wx/generic/srchctlg.h index ebcae90e78..188a92aa2e 100644 --- a/include/wx/generic/srchctlg.h +++ b/include/wx/generic/srchctlg.h @@ -88,6 +88,8 @@ public: // operations // ---------- + virtual void ChangeValue(const wxString& value) wxOVERRIDE; + // editing virtual void Clear() wxOVERRIDE; virtual void Replace(long from, long to, const wxString& value) wxOVERRIDE; @@ -223,7 +225,6 @@ protected: void OnCancelButton( wxCommandEvent& event ); - void OnSetFocus( wxFocusEvent& event ); void OnSize( wxSizeEvent& event ); bool HasMenu() const diff --git a/include/wx/srchctrl.h b/include/wx/srchctrl.h index 791fcb8092..8a0fa4da73 100644 --- a/include/wx/srchctrl.h +++ b/include/wx/srchctrl.h @@ -41,8 +41,8 @@ extern WXDLLIMPEXP_DATA_CORE(const char) wxSearchCtrlNameStr[]; -wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SEARCHCTRL_CANCEL_BTN, wxCommandEvent); -wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SEARCHCTRL_SEARCH_BTN, wxCommandEvent); +wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SEARCH_CANCEL, wxCommandEvent); +wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_SEARCH, wxCommandEvent); // ---------------------------------------------------------------------------- // a search ctrl is a text control with a search button and a cancel button @@ -90,13 +90,20 @@ private: // macros for handling search events // ---------------------------------------------------------------------------- -#define EVT_SEARCHCTRL_CANCEL_BTN(id, fn) \ - wx__DECLARE_EVT1(wxEVT_SEARCHCTRL_CANCEL_BTN, id, wxCommandEventHandler(fn)) +#define EVT_SEARCH_CANCEL(id, fn) \ + wx__DECLARE_EVT1(wxEVT_SEARCH_CANCEL, id, wxCommandEventHandler(fn)) -#define EVT_SEARCHCTRL_SEARCH_BTN(id, fn) \ - wx__DECLARE_EVT1(wxEVT_SEARCHCTRL_SEARCH_BTN, id, wxCommandEventHandler(fn)) +#define EVT_SEARCH(id, fn) \ + wx__DECLARE_EVT1(wxEVT_SEARCH, id, wxCommandEventHandler(fn)) -// old wxEVT_COMMAND_* constants +// old synonyms +#define wxEVT_SEARCHCTRL_CANCEL_BTN wxEVT_SEARCH_CANCEL +#define wxEVT_SEARCHCTRL_SEARCH_BTN wxEVT_SEARCH + +#define EVT_SEARCHCTRL_CANCEL_BTN(id, fn) EVT_SEARCH_CANCEL(id, fn) +#define EVT_SEARCHCTRL_SEARCH_BTN(id, fn) EVT_SEARCH(id, fn) + +// even older wxEVT_COMMAND_* constants #define wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN wxEVT_SEARCHCTRL_CANCEL_BTN #define wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN wxEVT_SEARCHCTRL_SEARCH_BTN diff --git a/interface/wx/srchctrl.h b/interface/wx/srchctrl.h index 51410de7bb..975a137703 100644 --- a/interface/wx/srchctrl.h +++ b/interface/wx/srchctrl.h @@ -12,10 +12,6 @@ control, and a cancel button. @beginStyleTable - @style{wxTE_PROCESS_ENTER} - The control will generate the event @c wxEVT_TEXT_ENTER - (otherwise pressing Enter key is either processed internally by the - control or used for navigation between dialog controls). @style{wxTE_PROCESS_TAB} The control will receive @c wxEVT_CHAR events for TAB pressed - normally, TAB is used for passing to the next control in a dialog @@ -39,16 +35,19 @@ @endStyleTable @beginEventEmissionTable{wxCommandEvent} - To retrieve actual search queries, use EVT_TEXT and EVT_TEXT_ENTER events, - just as you would with wxTextCtrl. - @event{EVT_SEARCHCTRL_SEARCH_BTN(id, func)} - Respond to a @c wxEVT_SEARCHCTRL_SEARCH_BTN event, generated when the + To react to the changes in the control contents, use wxEVT_TEXT event, just + as you would do with wxTextCtrl. However it is recommended to use + wxEVT_SEARCH to actually start searching to avoid doing it too soon, while + the user is still typing (note that wxEVT_SEARCH is also triggered by + pressing Enter in the control). + @event{EVT_SEARCH(id, func)} + Respond to a @c wxEVT_SEARCH event, generated when the search button is clicked. Note that this does not initiate a search on its own, you need to perform the appropriate action in your event handler. You may use @code event.GetString() @endcode to retrieve the string to search for in the event handler code. - @event{EVT_SEARCHCTRL_CANCEL_BTN(id, func)} - Respond to a @c wxEVT_SEARCHCTRL_CANCEL_BTN event, generated when the + @event{EVT_SEARCH_CANCEL(id, func)} + Respond to a @c wxEVT_SEARCH_CANCEL event, generated when the cancel button is clicked. @endEventTable @@ -56,7 +55,7 @@ @category{ctrl} @appearance{searchctrl} - @see wxTextCtrl::Create, wxValidator + @see wxTextCtrl */ class wxSearchCtrl : public wxTextCtrl { @@ -162,5 +161,5 @@ public: }; -wxEventType wxEVT_SEARCHCTRL_CANCEL_BTN; -wxEventType wxEVT_SEARCHCTRL_SEARCH_BTN; +wxEventType wxEVT_SEARCH_CANCEL; +wxEventType wxEVT_SEARCH; diff --git a/samples/widgets/searchctrl.cpp b/samples/widgets/searchctrl.cpp index 23750f7a46..7252ab078d 100644 --- a/samples/widgets/searchctrl.cpp +++ b/samples/widgets/searchctrl.cpp @@ -83,9 +83,15 @@ protected: void OnToggleCancelButton(wxCommandEvent&); void OnToggleSearchMenu(wxCommandEvent&); + void OnText(wxCommandEvent& event); + void OnTextEnter(wxCommandEvent& event); + void OnSearch(wxCommandEvent& event); void OnSearchCancel(wxCommandEvent& event); + void OnSetFocus(wxFocusEvent& event); + void OnKillFocus(wxFocusEvent& event); + wxMenu* CreateTestMenu(); // (re)create the control @@ -111,8 +117,11 @@ wxBEGIN_EVENT_TABLE(SearchCtrlWidgetsPage, WidgetsPage) EVT_CHECKBOX(ID_CANCEL_CB, SearchCtrlWidgetsPage::OnToggleCancelButton) EVT_CHECKBOX(ID_MENU_CB, SearchCtrlWidgetsPage::OnToggleSearchMenu) - EVT_SEARCHCTRL_SEARCH_BTN(wxID_ANY, SearchCtrlWidgetsPage::OnSearch) - EVT_SEARCHCTRL_CANCEL_BTN(wxID_ANY, SearchCtrlWidgetsPage::OnSearchCancel) + EVT_TEXT(wxID_ANY, SearchCtrlWidgetsPage::OnText) + EVT_TEXT_ENTER(wxID_ANY, SearchCtrlWidgetsPage::OnTextEnter) + + EVT_SEARCH(wxID_ANY, SearchCtrlWidgetsPage::OnSearch) + EVT_SEARCH_CANCEL(wxID_ANY, SearchCtrlWidgetsPage::OnSearchCancel) wxEND_EVENT_TABLE() // ============================================================================ @@ -171,6 +180,9 @@ void SearchCtrlWidgetsPage::CreateControl() m_srchCtrl = new wxSearchCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxSize(150, -1), style); + + m_srchCtrl->Bind(wxEVT_SET_FOCUS, &SearchCtrlWidgetsPage::OnSetFocus, this); + m_srchCtrl->Bind(wxEVT_KILL_FOCUS, &SearchCtrlWidgetsPage::OnKillFocus, this); } void SearchCtrlWidgetsPage::RecreateWidget() @@ -227,6 +239,18 @@ void SearchCtrlWidgetsPage::OnToggleSearchMenu(wxCommandEvent&) m_srchCtrl->SetMenu(NULL); } +void SearchCtrlWidgetsPage::OnText(wxCommandEvent& event) +{ + wxLogMessage("Search control: text changes, contents is \"%s\".", + event.GetString()); +} + +void SearchCtrlWidgetsPage::OnTextEnter(wxCommandEvent& event) +{ + wxLogMessage("Search control: enter pressed, contents is \"%s\".", + event.GetString()); +} + void SearchCtrlWidgetsPage::OnSearch(wxCommandEvent& event) { wxLogMessage("Search button: search for \"%s\".", event.GetString()); @@ -239,4 +263,18 @@ void SearchCtrlWidgetsPage::OnSearchCancel(wxCommandEvent& event) event.Skip(); } +void SearchCtrlWidgetsPage::OnSetFocus(wxFocusEvent& event) +{ + wxLogMessage("Search control got focus"); + + event.Skip(); +} + +void SearchCtrlWidgetsPage::OnKillFocus(wxFocusEvent& event) +{ + wxLogMessage("Search control lost focus"); + + event.Skip(); +} + #endif // wxUSE_SEARCHCTRL diff --git a/src/common/srchcmn.cpp b/src/common/srchcmn.cpp index 1e524b5394..788b466937 100644 --- a/src/common/srchcmn.cpp +++ b/src/common/srchcmn.cpp @@ -34,8 +34,8 @@ const char wxSearchCtrlNameStr[] = "searchCtrl"; -wxDEFINE_EVENT(wxEVT_SEARCHCTRL_CANCEL_BTN, wxCommandEvent); -wxDEFINE_EVENT(wxEVT_SEARCHCTRL_SEARCH_BTN, wxCommandEvent); +wxDEFINE_EVENT(wxEVT_SEARCH_CANCEL, wxCommandEvent); +wxDEFINE_EVENT(wxEVT_SEARCH, wxCommandEvent); #endif // wxUSE_SEARCHCTRL diff --git a/src/generic/srchctlg.cpp b/src/generic/srchctlg.cpp index 5ad5654fe4..074bee8722 100644 --- a/src/generic/srchctlg.cpp +++ b/src/generic/srchctlg.cpp @@ -92,19 +92,16 @@ protected: m_search->GetEventHandler()->ProcessEvent(event); } - void OnTextUrl(wxTextUrlEvent& eventText) + void OnTextEnter(wxCommandEvent& WXUNUSED(event)) { - // copy constructor is disabled for some reason? - //wxTextUrlEvent event(eventText); - wxTextUrlEvent event( - m_search->GetId(), - eventText.GetMouseEvent(), - eventText.GetURLStart(), - eventText.GetURLEnd() - ); - event.SetEventObject(m_search); + if ( !IsEmpty() ) + { + wxCommandEvent event(wxEVT_SEARCH, m_search->GetId()); + event.SetEventObject(m_search); + event.SetString(m_search->GetValue()); - m_search->GetEventHandler()->ProcessEvent(event); + m_search->ProcessWindowEvent(event); + } } #ifdef __WXMSW__ @@ -149,8 +146,7 @@ private: wxBEGIN_EVENT_TABLE(wxSearchTextCtrl, wxTextCtrl) EVT_TEXT(wxID_ANY, wxSearchTextCtrl::OnText) - EVT_TEXT_ENTER(wxID_ANY, wxSearchTextCtrl::OnText) - EVT_TEXT_URL(wxID_ANY, wxSearchTextCtrl::OnTextUrl) + EVT_TEXT_ENTER(wxID_ANY, wxSearchTextCtrl::OnTextEnter) EVT_TEXT_MAXLEN(wxID_ANY, wxSearchTextCtrl::OnText) wxEND_EVENT_TABLE() @@ -166,7 +162,9 @@ public: m_search(search), m_eventType(eventType), m_bmp(bmp) - { } + { + SetBackgroundStyle(wxBG_STYLE_PAINT); + } void SetBitmapLabel(const wxBitmap& label) { @@ -198,7 +196,7 @@ protected: wxCommandEvent event(m_eventType, m_search->GetId()); event.SetEventObject(m_search); - if ( m_eventType == wxEVT_SEARCHCTRL_SEARCH_BTN ) + if ( m_eventType == wxEVT_SEARCH ) { // it's convenient to have the string to search for directly in the // event instead of having to retrieve it from the control in the @@ -211,7 +209,7 @@ protected: m_search->SetFocus(); #if wxUSE_MENUS - if ( m_eventType == wxEVT_SEARCHCTRL_SEARCH_BTN ) + if ( m_eventType == wxEVT_SEARCH ) { // this happens automatically, just like on Mac OS X m_search->PopupSearchMenu(); @@ -240,8 +238,7 @@ wxBEGIN_EVENT_TABLE(wxSearchButton, wxControl) wxEND_EVENT_TABLE() wxBEGIN_EVENT_TABLE(wxSearchCtrl, wxSearchCtrlBase) - EVT_SEARCHCTRL_CANCEL_BTN(wxID_ANY, wxSearchCtrl::OnCancelButton) - EVT_SET_FOCUS(wxSearchCtrl::OnSetFocus) + EVT_SEARCH_CANCEL(wxID_ANY, wxSearchCtrl::OnCancelButton) EVT_SIZE(wxSearchCtrl::OnSize) wxEND_EVENT_TABLE() @@ -325,10 +322,10 @@ bool wxSearchCtrl::Create(wxWindow *parent, wxWindowID id, m_text = new wxSearchTextCtrl(this, value, style); m_searchButton = new wxSearchButton(this, - wxEVT_SEARCHCTRL_SEARCH_BTN, + wxEVT_SEARCH, m_searchBitmap); m_cancelButton = new wxSearchButton(this, - wxEVT_SEARCHCTRL_CANCEL_BTN, + wxEVT_SEARCH_CANCEL, m_cancelBitmap); SetBackgroundColour( m_text->GetBackgroundColour() ); @@ -916,6 +913,14 @@ wxTextCtrl& operator<<(double d); wxTextCtrl& operator<<(const wxChar c); #endif +// Note that overriding DoSetValue() is currently insufficient because the base +// class ChangeValue() only updates m_hintData of this object (which is null +// anyhow), instead of updating m_text->m_hintData, see #16998. +void wxSearchCtrl::ChangeValue(const wxString& value) +{ + m_text->ChangeValue(value); +} + void wxSearchCtrl::DoSetValue(const wxString& value, int flags) { m_text->DoSetValue(value, flags); @@ -1235,14 +1240,6 @@ void wxSearchCtrl::OnCancelButton( wxCommandEvent& event ) event.Skip(); } -void wxSearchCtrl::OnSetFocus( wxFocusEvent& /*event*/ ) -{ - if ( m_text ) - { - m_text->SetFocus(); - } -} - void wxSearchCtrl::OnSize( wxSizeEvent& WXUNUSED(event) ) { LayoutControls(); diff --git a/src/osx/srchctrl_osx.cpp b/src/osx/srchctrl_osx.cpp index 928bb9340e..fa3101f42e 100644 --- a/src/osx/srchctrl_osx.cpp +++ b/src/osx/srchctrl_osx.cpp @@ -209,7 +209,7 @@ bool wxSearchCtrl::Create(wxWindow *parent, wxWindowID id, bool wxSearchCtrl::HandleSearchFieldSearchHit() { - wxCommandEvent event(wxEVT_SEARCHCTRL_SEARCH_BTN, m_windowId ); + wxCommandEvent event(wxEVT_SEARCH, m_windowId ); event.SetEventObject(this); // provide the string to search for directly in the event, this is more @@ -221,7 +221,7 @@ bool wxSearchCtrl::HandleSearchFieldSearchHit() bool wxSearchCtrl::HandleSearchFieldCancelHit() { - wxCommandEvent event(wxEVT_SEARCHCTRL_CANCEL_BTN, m_windowId ); + wxCommandEvent event(wxEVT_SEARCH_CANCEL, m_windowId ); event.SetEventObject(this); return ProcessCommand(event); } diff --git a/tests/controls/searchctrltest.cpp b/tests/controls/searchctrltest.cpp index a9bfb68103..31dc748322 100644 --- a/tests/controls/searchctrltest.cpp +++ b/tests/controls/searchctrltest.cpp @@ -20,50 +20,41 @@ #include "wx/srchctrl.h" -class SearchCtrlTestCase : public CppUnit::TestCase +class SearchCtrlTestCase { public: - SearchCtrlTestCase() { } + SearchCtrlTestCase() + : m_search(new wxSearchCtrl(wxTheApp->GetTopWindow(), wxID_ANY)) + { + } - virtual void setUp(); - virtual void tearDown(); + ~SearchCtrlTestCase() + { + delete m_search; + } -private: - CPPUNIT_TEST_SUITE( SearchCtrlTestCase ); - CPPUNIT_TEST( Focus ); - CPPUNIT_TEST_SUITE_END(); - - void Focus(); - - wxSearchCtrl* m_search; - - wxDECLARE_NO_COPY_CLASS(SearchCtrlTestCase); +protected: + wxSearchCtrl* const m_search; }; -// register in the unnamed registry so that these tests are run by default -CPPUNIT_TEST_SUITE_REGISTRATION( SearchCtrlTestCase ); +#define SEARCH_CTRL_TEST_CASE(name, tags) \ + TEST_CASE_METHOD(SearchCtrlTestCase, name, tags) -// also include in its own registry so that these tests can be run alone -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SearchCtrlTestCase, "SearchCtrlTestCase" ); - -void SearchCtrlTestCase::setUp() -{ - m_search = new wxSearchCtrl(wxTheApp->GetTopWindow(), wxID_ANY); -} - -void SearchCtrlTestCase::tearDown() -{ - delete m_search; - m_search = NULL; -} - -void SearchCtrlTestCase::Focus() -{ - // TODO OS X test only passes when run solo ... +// TODO OS X test only passes when run solo ... #ifndef __WXOSX__ +SEARCH_CTRL_TEST_CASE("wxSearchCtrl::Focus", "[wxSearchCtrl][focus]") +{ m_search->SetFocus(); - CPPUNIT_ASSERT( m_search->HasFocus() ); -#endif + CHECK( m_search->HasFocus() ); +} +#endif // !__WXOSX__ + +SEARCH_CTRL_TEST_CASE("wxSearchCtrl::ChangeValue", "[wxSearchCtrl][text]") +{ + CHECK( m_search->GetValue() == wxString() ); + + m_search->ChangeValue("foo"); + CHECK( m_search->GetValue() == "foo" ); } #endif // wxUSE_SEARCHCTRL