Rewrote wxMSW radio menu items code to support not only appending them.

Previously the radio menu items could only be appended to a menu in wxMSW,
inserting them (either in an existing radio group or to start a new one) not
only didn't work but could even result in crashes because invalid iterators in
the menu items list could be used.

Fix this by storing the ranges of all radio groups in wxMenu itself instead of
storing the information about the radio group an item belongs to in the item
itself and by updating this data whenever a new radio item is inserted. Also
get rid of the notion of "current radio group" in wxMenu which doesn't really
make any sense.

Finally add a unit test checking that inserting radio items works as expected.

Closes #13200.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67720 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2011-05-10 08:50:38 +00:00
parent a6ca624a27
commit 89511b4268
5 changed files with 194 additions and 129 deletions

View File

@@ -84,6 +84,7 @@ private:
CPPUNIT_TEST( FindInMenu );
CPPUNIT_TEST( Count );
CPPUNIT_TEST( Labels );
CPPUNIT_TEST( RadioItems );
CPPUNIT_TEST_SUITE_END();
void CreateFrame();
@@ -92,6 +93,7 @@ private:
void FindInMenu();
void Count();
void Labels();
void RadioItems();
wxFrame* m_frame;
@@ -304,3 +306,56 @@ void MenuTestCase::Labels()
CPPUNIT_ASSERT_EQUAL( "Foo", itemFoo->GetItemLabelText() );
CPPUNIT_ASSERT_EQUAL( "Foo", wxMenuItem::GetLabelText("&Foo\tCtrl-F") );
}
void MenuTestCase::RadioItems()
{
wxMenuBar * const bar = m_frame->GetMenuBar();
wxMenu * const menu = new wxMenu;
bar->Append(menu, "&Radio");
// Adding consecutive radio items creates a radio group.
menu->AppendRadioItem(MenuTestCase_First, "Radio 0");
menu->AppendRadioItem(MenuTestCase_First + 1, "Radio 1");
// First item of a radio group is checked by default.
CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First) );
// Checking the second one make the first one unchecked however.
menu->Check(MenuTestCase_First + 1, true);
CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First) );
CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
// Adding more radio items after a separator creates another radio group...
menu->AppendSeparator();
menu->AppendRadioItem(MenuTestCase_First + 2, "Radio 2");
menu->AppendRadioItem(MenuTestCase_First + 3, "Radio 3");
menu->AppendRadioItem(MenuTestCase_First + 4, "Radio 4");
// ... which is independent from the first one.
CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 2) );
menu->Check(MenuTestCase_First + 3, true);
CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 2) );
CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
// Insert an item in the middle of an existing radio group.
menu->InsertRadioItem(4, MenuTestCase_First + 5, "Radio 5");
CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
menu->Check( MenuTestCase_First + 5, true );
CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 3) );
// Prepend a couple of items before the first group.
menu->PrependRadioItem(MenuTestCase_First + 6, "Radio 6");
menu->PrependRadioItem(MenuTestCase_First + 7, "Radio 7");
menu->Check(MenuTestCase_First + 7, true);
CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 1) );
// Check that the last radio group still works as expected.
menu->Check(MenuTestCase_First + 4, true);
CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 5) );
}