From 0f1d1d2ae9b6138db068c1a38538460bbc6becfb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 4 Apr 2021 14:21:27 +0200 Subject: [PATCH] Update wxSearchCtrl popup menu state after showing it Fix the state of the check/radio items in the menu by updating the template used by macOS to create the actual menu after showing it and possibly changing the items state. This is not ideal because changing the state from the program, e.g. using wxMenuItem::Check(), still doesn't work correctly, i.e. isn't reflected in the menu when it's shown, but better than nothing until a better solution (which ideally would update the menu just before showing it, but it's not clear how exactly can we do it, knowing that we don't get wxEVT_MENU_OPEN for this menu neither) can be found. --- include/wx/osx/srchctrl.h | 4 ++++ include/wx/osx/window.h | 5 +++++ samples/widgets/searchctrl.cpp | 5 +++-- src/osx/menu_osx.cpp | 6 ++++++ src/osx/srchctrl_osx.cpp | 8 ++++++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/include/wx/osx/srchctrl.h b/include/wx/osx/srchctrl.h index 1fdc12cd4a..62cea42955 100644 --- a/include/wx/osx/srchctrl.h +++ b/include/wx/osx/srchctrl.h @@ -62,6 +62,10 @@ public: wxSearchWidgetImpl * GetSearchPeer() const; +#if wxUSE_MENUS + virtual void OSXAfterMenuEvent() wxOVERRIDE; +#endif // wxUSE_MENUS + protected: wxSize DoGetBestSize() const wxOVERRIDE; diff --git a/include/wx/osx/window.h b/include/wx/osx/window.h index f761a598bc..67832b462b 100644 --- a/include/wx/osx/window.h +++ b/include/wx/osx/window.h @@ -299,6 +299,11 @@ public: // Return the DPI corresponding to the given scale factor. static wxSize OSXMakeDPIFromScaleFactor(double scaleFactor); +#if wxUSE_MENUS + // Called on the invoking window after handling the menu event. + virtual void OSXAfterMenuEvent() { } +#endif // wxUSE_MENUS + protected: // For controls like radio buttons which are genuinely composite wxList m_subControls; diff --git a/samples/widgets/searchctrl.cpp b/samples/widgets/searchctrl.cpp index c3e586b25d..1e8d3683d3 100644 --- a/samples/widgets/searchctrl.cpp +++ b/samples/widgets/searchctrl.cpp @@ -199,7 +199,7 @@ wxMenu* SearchCtrlWidgetsPage::CreateTestMenu() { wxString itemText = wxString::Format("item %i",i); wxString tipText = wxString::Format("tip %i",i); - menu->Append(ID_SEARCHMENU+i, itemText, tipText, wxITEM_NORMAL); + menu->Append(ID_SEARCHMENU+i, itemText, tipText, wxITEM_CHECK); } return menu; } @@ -243,7 +243,8 @@ void SearchCtrlWidgetsPage::OnTextEnter(wxCommandEvent& event) void SearchCtrlWidgetsPage::OnSearchMenu(wxCommandEvent& event) { int id = event.GetId() - ID_SEARCHMENU; - wxLogMessage("Search menu: \"item %i\" selected (%s).", id); + wxLogMessage("Search menu: \"item %i\" selected (%s).", + id, event.IsChecked() ? "checked" : "unchecked"); } void SearchCtrlWidgetsPage::OnSearch(wxCommandEvent& event) diff --git a/src/osx/menu_osx.cpp b/src/osx/menu_osx.cpp index df85dc2c89..85bcdf44bc 100644 --- a/src/osx/menu_osx.cpp +++ b/src/osx/menu_osx.cpp @@ -375,6 +375,12 @@ bool wxMenu::HandleCommandProcess( wxMenuItem* item, wxWindow* senderWindow ) processed = item->GetPeer()->DoDefault(); } + if (wxWindow* const w = GetInvokingWindow()) + { + // Let the invoking window update itself if necessary. + w->OSXAfterMenuEvent(); + } + return processed; } diff --git a/src/osx/srchctrl_osx.cpp b/src/osx/srchctrl_osx.cpp index 9b48e7c0e7..0fb0c0e5fc 100644 --- a/src/osx/srchctrl_osx.cpp +++ b/src/osx/srchctrl_osx.cpp @@ -119,6 +119,14 @@ wxMenu* wxSearchCtrl::GetMenu() return m_menu; } +void wxSearchCtrl::OSXAfterMenuEvent() +{ + // The menu is used as a template for creating the actual menu shown by the + // control, so update this template with the latest menu state after a menu + // command as the state of check/radio items could have changed after it. + GetSearchPeer()->SetSearchMenu( m_menu ); +} + #endif // wxUSE_MENUS void wxSearchCtrl::ShowSearchButton( bool show )