Harmonize wxMenuEvent handling between all major ports.
Send these events to the menu itself first, then to the menu bar containing it or the window invoking it if it's a popup menu and, finally, to the top level window in all of wxGTK, wxMSW and wxOSX. In particular, this ensures that help strings are now shown in the parent MDI frame status bar by default, even when the menus are attached to the client MDI frame or shown as popup menus. At the implementation level, this logic is now encapsulated in a new static wxMenu::ProcessMenuEvent() method which can be easily modified and reused in other ports. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78230 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -93,6 +93,7 @@ All (GUI):
|
||||
- Add wxUIActionSimulator::Select().
|
||||
- Add wxOwnerDrawnComboBox::Is{List,Text}Empty() methods.
|
||||
- Fix creating/removing mode buttons in wxPG manager (Artur Wieczorek).
|
||||
- Harmonize wxMenuEvent handling between all major ports.
|
||||
|
||||
wxGTK:
|
||||
|
||||
|
@@ -309,6 +309,13 @@ public:
|
||||
// the checked parameter may have boolean value or -1 for uncheckable items
|
||||
bool SendEvent(int itemid, int checked = -1);
|
||||
|
||||
// called to dispatch a wxMenuEvent to the right recipients, menu pointer
|
||||
// can be NULL if we failed to find the associated menu (this happens at
|
||||
// least in wxMSW for the events from the system menus)
|
||||
static
|
||||
bool ProcessMenuEvent(wxMenu* menu, wxMenuEvent& event, wxWindow* win);
|
||||
|
||||
|
||||
// compatibility: these functions are deprecated, use the new ones instead
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@@ -390,8 +397,8 @@ protected:
|
||||
|
||||
|
||||
private:
|
||||
// Helper of SendEvent(): sends the event to its intended recipients,
|
||||
// returns true if it was processed.
|
||||
// Common part of SendEvent() and ProcessMenuEvent(): sends the event to
|
||||
// its intended recipients, returns true if it was processed.
|
||||
static bool DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win);
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxMenuBase);
|
||||
|
@@ -4107,8 +4107,24 @@ public:
|
||||
these do not include menu command events, which are
|
||||
handled using wxCommandEvent objects.
|
||||
|
||||
The default handler for @c wxEVT_MENU_HIGHLIGHT displays help
|
||||
text in the first field of the status bar.
|
||||
Events of this class are generated by both menus that are part of a
|
||||
wxMenuBar, attached to wxFrame, and popup menus shown by
|
||||
wxWindow::PopupMenu(). They are sent to the following objects until one of
|
||||
them handles the event:
|
||||
|
||||
-# The menu object itself, as returned by GetMenu(), if any.
|
||||
-# The wxMenuBar to which this menu is attached, if any.
|
||||
-# The window associated with the menu, e.g. the one calling
|
||||
PopupMenu() for the popup menus.
|
||||
-# The top level parent of that window if it's different from the
|
||||
window itself.
|
||||
|
||||
This is similar to command events generated by the menu items, but, unlike
|
||||
them, wxMenuEvent are only sent to the window itself and its top level
|
||||
parent but not any intermediate windows in the hierarchy.
|
||||
|
||||
The default handler for @c wxEVT_MENU_HIGHLIGHT in wxFrame displays help
|
||||
text in the status bar, see wxFrame::SetStatusBarPane().
|
||||
|
||||
@beginEventTable{wxMenuEvent}
|
||||
@event{EVT_MENU_OPEN(func)}
|
||||
|
@@ -651,16 +651,18 @@ bool wxMenuBase::DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win)
|
||||
{
|
||||
event.SetEventObject(menu);
|
||||
|
||||
if ( menu )
|
||||
{
|
||||
wxMenuBar* const mb = menu->GetMenuBar();
|
||||
|
||||
// Try the menu's event handler first
|
||||
wxEvtHandler *handler = menu->GetEventHandler();
|
||||
if ( handler )
|
||||
{
|
||||
// Indicate to the event processing code that we're going to pass this
|
||||
// event to another handler if it's not processed here to prevent it
|
||||
// from passing the event to wxTheApp: this will be done below if we do
|
||||
// have the associated window.
|
||||
// Indicate to the event processing code that we're going to pass
|
||||
// this event to another handler if it's not processed here to
|
||||
// prevent it from passing the event to wxTheApp: this will be done
|
||||
// below if we do have the associated window.
|
||||
if ( win || mb )
|
||||
event.SetWillBeProcessedAgain();
|
||||
|
||||
@@ -668,10 +670,19 @@ bool wxMenuBase::DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win)
|
||||
return true;
|
||||
}
|
||||
|
||||
// If this menu is part of the menu bar, process the event there: this will
|
||||
// also propagate it upwards to the window containing the menu bar.
|
||||
// If this menu is part of the menu bar, try the event there. this
|
||||
if ( mb )
|
||||
return mb->HandleWindowEvent(event);
|
||||
{
|
||||
if ( mb->HandleWindowEvent(event) )
|
||||
return true;
|
||||
|
||||
// If this already propagated it upwards to the window containing
|
||||
// the menu bar, we don't have to handle it in this window again
|
||||
// below.
|
||||
if ( event.ShouldPropagate() )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Try the window the menu was popped up from.
|
||||
if ( win )
|
||||
@@ -681,6 +692,24 @@ bool wxMenuBase::DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
wxMenuBase::ProcessMenuEvent(wxMenu* menu, wxMenuEvent& event, wxWindow* win)
|
||||
{
|
||||
// Try to process the event in the usual places first.
|
||||
if ( DoProcessEvent(menu, event, win) )
|
||||
return true;
|
||||
|
||||
// But the menu events should also reach the TLW parent if they were not
|
||||
// processed before so, as it's not a command event and hence doesn't
|
||||
// bubble up by default, send it there explicitly if not done yet.
|
||||
wxWindow* const tlw = wxGetTopLevelParent(win);
|
||||
if ( tlw != win && tlw->HandleWindowEvent(event) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMenu attaching/detaching to/from menu bar
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -74,16 +74,7 @@ static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
|
||||
if ( !IsMenuEventAllowed(menu) )
|
||||
return;
|
||||
|
||||
event.SetEventObject( menu );
|
||||
|
||||
wxEvtHandler* handler = menu->GetEventHandler();
|
||||
if (handler && handler->SafelyProcessEvent(event))
|
||||
return;
|
||||
|
||||
wxWindow *win = menu->GetWindow();
|
||||
wxCHECK_RET( win, "event for a menu without associated window?" );
|
||||
|
||||
win->HandleWindowEvent( event );
|
||||
wxMenu::ProcessMenuEvent(menu, event, menu->GetWindow());
|
||||
}
|
||||
|
||||
// Return the top level menu containing this menu (possibly this menu itself).
|
||||
|
@@ -2269,9 +2269,7 @@ wxWindowMSW::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu)
|
||||
item = wxID_NONE;
|
||||
|
||||
wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
|
||||
event.SetEventObject(this);
|
||||
|
||||
if ( HandleWindowEvent(event) )
|
||||
if ( wxMenu::ProcessMenuEvent(MSWFindMenuFromHMENU(hMenu), event, this) )
|
||||
return true;
|
||||
|
||||
// by default, i.e. if the event wasn't handled above, clear the status bar
|
||||
@@ -2291,9 +2289,8 @@ bool
|
||||
wxWindowMSW::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu)
|
||||
{
|
||||
wxMenuEvent event(evtType, menu && !menu->IsAttached() ? wxID_ANY : 0, menu);
|
||||
event.SetEventObject(menu);
|
||||
|
||||
return HandleWindowEvent(event);
|
||||
return wxMenu::ProcessMenuEvent(menu, event, this);
|
||||
}
|
||||
|
||||
bool wxWindowMSW::HandleMenuPopup(wxEventType evtType, WXHMENU hMenu)
|
||||
|
@@ -555,22 +555,7 @@ void wxMenu::HandleMenuClosed()
|
||||
|
||||
bool wxMenu::DoHandleMenuEvent(wxEvent& wxevent)
|
||||
{
|
||||
wxevent.SetEventObject(this);
|
||||
wxEvtHandler* handler = GetEventHandler();
|
||||
if (handler && handler->ProcessEvent(wxevent))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxWindow *win = GetWindow();
|
||||
if (win)
|
||||
{
|
||||
if ( win->HandleWindowEvent(wxevent) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return ProcessMenuEvent(this, wxevent, GetWindow());
|
||||
}
|
||||
|
||||
// Menu Bar
|
||||
|
Reference in New Issue
Block a user