Fix accel handling when removing item from submenu

wxMSW propagates accelerators to the top menu in wxMenu::UpdateAccel(),
but the reverse operation in wxMenu::DoRemove() didn't do it, resulting
in leaked leftover accelerator entries that could prevent the same
accelerator from working if an item using it was later added. Fix by
adding RemoveAccel() helper method that behaves analogously to
UpdateAccel().

(backport of 60542745f6 from master)
This commit is contained in:
Václav Slavík
2016-12-05 18:03:04 +01:00
parent 97330c2706
commit 90b124835e
2 changed files with 31 additions and 13 deletions

View File

@@ -94,6 +94,9 @@ public:
// called by wxMenuItem when its accels changes // called by wxMenuItem when its accels changes
void UpdateAccel(wxMenuItem *item); void UpdateAccel(wxMenuItem *item);
#if wxABI_VERSION >= 30002
void RemoveAccel(wxMenuItem *item);
#endif
// helper used by wxMenu itself (returns the index in m_accels) // helper used by wxMenu itself (returns the index in m_accels)
int FindAccel(int id) const; int FindAccel(int id) const;

View File

@@ -458,6 +458,33 @@ void wxMenu::UpdateAccel(wxMenuItem *item)
//else: it is a separator, they can't have accels, nothing to do //else: it is a separator, they can't have accels, nothing to do
} }
void wxMenu::RemoveAccel(wxMenuItem *item)
{
// recurse upwards: we should only modify m_accels of the top level
// menus, not of the submenus as wxMenuBar doesn't look at them
// (alternative and arguable cleaner solution would be to recurse
// downwards in GetAccelCount() and CopyAccels())
if ( GetParent() )
{
GetParent()->RemoveAccel(item);
return;
}
// remove the corresponding accel from the accel table
int n = FindAccel(item->GetId());
if ( n != wxNOT_FOUND )
{
delete m_accels[n];
m_accels.RemoveAt(n);
#if wxUSE_OWNER_DRAWN
ResetMaxAccelWidth();
#endif
}
//else: this item doesn't have an accel, nothing to do
}
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
namespace namespace
@@ -863,19 +890,7 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") ); wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
#if wxUSE_ACCEL #if wxUSE_ACCEL
// remove the corresponding accel from the accel table RemoveAccel(item);
int n = FindAccel(item->GetId());
if ( n != wxNOT_FOUND )
{
delete m_accels[n];
m_accels.RemoveAt(n);
#if wxUSE_OWNER_DRAWN
ResetMaxAccelWidth();
#endif
}
//else: this item doesn't have an accel, nothing to do
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
// Update indices of radio groups. // Update indices of radio groups.