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 wxUIActionSimulator::Select().
|
||||||
- Add wxOwnerDrawnComboBox::Is{List,Text}Empty() methods.
|
- Add wxOwnerDrawnComboBox::Is{List,Text}Empty() methods.
|
||||||
- Fix creating/removing mode buttons in wxPG manager (Artur Wieczorek).
|
- Fix creating/removing mode buttons in wxPG manager (Artur Wieczorek).
|
||||||
|
- Harmonize wxMenuEvent handling between all major ports.
|
||||||
|
|
||||||
wxGTK:
|
wxGTK:
|
||||||
|
|
||||||
|
@@ -309,6 +309,13 @@ public:
|
|||||||
// the checked parameter may have boolean value or -1 for uncheckable items
|
// the checked parameter may have boolean value or -1 for uncheckable items
|
||||||
bool SendEvent(int itemid, int checked = -1);
|
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
|
// compatibility: these functions are deprecated, use the new ones instead
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -390,8 +397,8 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Helper of SendEvent(): sends the event to its intended recipients,
|
// Common part of SendEvent() and ProcessMenuEvent(): sends the event to
|
||||||
// returns true if it was processed.
|
// its intended recipients, returns true if it was processed.
|
||||||
static bool DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win);
|
static bool DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win);
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxMenuBase);
|
wxDECLARE_NO_COPY_CLASS(wxMenuBase);
|
||||||
|
@@ -4107,8 +4107,24 @@ public:
|
|||||||
these do not include menu command events, which are
|
these do not include menu command events, which are
|
||||||
handled using wxCommandEvent objects.
|
handled using wxCommandEvent objects.
|
||||||
|
|
||||||
The default handler for @c wxEVT_MENU_HIGHLIGHT displays help
|
Events of this class are generated by both menus that are part of a
|
||||||
text in the first field of the status bar.
|
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}
|
@beginEventTable{wxMenuEvent}
|
||||||
@event{EVT_MENU_OPEN(func)}
|
@event{EVT_MENU_OPEN(func)}
|
||||||
|
@@ -651,28 +651,39 @@ bool wxMenuBase::DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win)
|
|||||||
{
|
{
|
||||||
event.SetEventObject(menu);
|
event.SetEventObject(menu);
|
||||||
|
|
||||||
wxMenuBar* const mb = menu->GetMenuBar();
|
if ( menu )
|
||||||
|
|
||||||
// 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
|
wxMenuBar* const mb = menu->GetMenuBar();
|
||||||
// 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();
|
|
||||||
|
|
||||||
if ( handler->SafelyProcessEvent(event) )
|
// Try the menu's event handler first
|
||||||
return true;
|
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.
|
||||||
|
if ( win || mb )
|
||||||
|
event.SetWillBeProcessedAgain();
|
||||||
|
|
||||||
|
if ( handler->SafelyProcessEvent(event) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this menu is part of the menu bar, try the event there. this
|
||||||
|
if ( mb )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 ( mb )
|
|
||||||
return mb->HandleWindowEvent(event);
|
|
||||||
|
|
||||||
// Try the window the menu was popped up from.
|
// Try the window the menu was popped up from.
|
||||||
if ( win )
|
if ( win )
|
||||||
return win->HandleWindowEvent(event);
|
return win->HandleWindowEvent(event);
|
||||||
@@ -681,6 +692,24 @@ bool wxMenuBase::DoProcessEvent(wxMenuBase* menu, wxEvent& event, wxWindow* win)
|
|||||||
return false;
|
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
|
// wxMenu attaching/detaching to/from menu bar
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -74,16 +74,7 @@ static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
|
|||||||
if ( !IsMenuEventAllowed(menu) )
|
if ( !IsMenuEventAllowed(menu) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event.SetEventObject( menu );
|
wxMenu::ProcessMenuEvent(menu, event, menu->GetWindow());
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the top level menu containing this menu (possibly this menu itself).
|
// 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;
|
item = wxID_NONE;
|
||||||
|
|
||||||
wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
|
wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
|
||||||
event.SetEventObject(this);
|
if ( wxMenu::ProcessMenuEvent(MSWFindMenuFromHMENU(hMenu), event, this) )
|
||||||
|
|
||||||
if ( HandleWindowEvent(event) )
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// by default, i.e. if the event wasn't handled above, clear the status bar
|
// 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)
|
wxWindowMSW::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu)
|
||||||
{
|
{
|
||||||
wxMenuEvent event(evtType, menu && !menu->IsAttached() ? wxID_ANY : 0, 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)
|
bool wxWindowMSW::HandleMenuPopup(wxEventType evtType, WXHMENU hMenu)
|
||||||
|
@@ -555,22 +555,7 @@ void wxMenu::HandleMenuClosed()
|
|||||||
|
|
||||||
bool wxMenu::DoHandleMenuEvent(wxEvent& wxevent)
|
bool wxMenu::DoHandleMenuEvent(wxEvent& wxevent)
|
||||||
{
|
{
|
||||||
wxevent.SetEventObject(this);
|
return ProcessMenuEvent(this, wxevent, GetWindow());
|
||||||
wxEvtHandler* handler = GetEventHandler();
|
|
||||||
if (handler && handler->ProcessEvent(wxevent))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wxWindow *win = GetWindow();
|
|
||||||
if (win)
|
|
||||||
{
|
|
||||||
if ( win->HandleWindowEvent(wxevent) )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Menu Bar
|
// Menu Bar
|
||||||
|
Reference in New Issue
Block a user