Merge in from trunk r67662 to r64801
[wxWidgets.git] / tests / menu / menu.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/menu/menu.cpp
3 // Purpose: wxMenu unit test
4 // Author: wxWidgets team
5 // Created: 2010-11-10
6 // RCS-ID: $Id$
7 // Copyright: (c) 2010 wxWidgets team
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13
14 #include "testprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #ifndef WX_PRECOMP
21 #include "wx/wx.h"
22 #endif // WX_PRECOMP
23
24 #include "wx/menu.h"
25 #include <stdarg.h>
26
27 // ----------------------------------------------------------------------------
28 // helper
29 // ----------------------------------------------------------------------------
30
31 namespace
32 {
33
34 enum
35 {
36 MenuTestCase_Foo = 10000,
37 MenuTestCase_Bar,
38 MenuTestCase_First
39 };
40
41 void PopulateMenu(wxMenu* menu, const wxString& name, size_t& itemcount)
42 {
43 // Start at item 1 to make it human-readable ;)
44 for (int n=1; n<6; ++n, ++itemcount)
45 {
46 wxString label = name; label << n;
47 menu->Append(MenuTestCase_First + itemcount, label, label + " help string");
48 }
49 }
50
51 void RecursivelyCountMenuItems(const wxMenu* menu, size_t& count)
52 {
53 CPPUNIT_ASSERT( menu );
54
55 count += menu->GetMenuItemCount();
56 for (size_t n=0; n < menu->GetMenuItemCount(); ++n)
57 {
58 wxMenuItem* item = menu->FindItemByPosition(n);
59 if (item->IsSubMenu())
60 {
61 RecursivelyCountMenuItems(item->GetSubMenu(), count);
62 }
63 }
64 }
65
66 } // anon namespace
67
68
69 // ----------------------------------------------------------------------------
70 // test class
71 // ----------------------------------------------------------------------------
72
73 class MenuTestCase : public CppUnit::TestCase
74 {
75 public:
76 MenuTestCase() {}
77
78 virtual void setUp() { CreateFrame(); }
79 virtual void tearDown() { m_frame->Destroy(); }
80
81 private:
82 CPPUNIT_TEST_SUITE( MenuTestCase );
83 CPPUNIT_TEST( FindInMenubar );
84 CPPUNIT_TEST( FindInMenu );
85 CPPUNIT_TEST( Count );
86 CPPUNIT_TEST( Labels );
87 CPPUNIT_TEST( RadioItems );
88 CPPUNIT_TEST_SUITE_END();
89
90 void CreateFrame();
91
92 void FindInMenubar();
93 void FindInMenu();
94 void Count();
95 void Labels();
96 void RadioItems();
97
98 wxFrame* m_frame;
99
100 // Holds the number of menuitems contained in all the menus
101 size_t m_itemCount;
102
103 // Store here the id of a known submenu item, to be searched for later
104 int m_submenuItemId;
105
106 // and a sub-submenu item
107 int m_subsubmenuItemId;
108
109 wxArrayString m_menuLabels;
110
111 DECLARE_NO_COPY_CLASS(MenuTestCase)
112 };
113
114 // register in the unnamed registry so that these tests are run by default
115 CPPUNIT_TEST_SUITE_REGISTRATION( MenuTestCase );
116
117 // also include in its own registry so that these tests can be run alone
118 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MenuTestCase, "MenuTestCase" );
119
120 void MenuTestCase::CreateFrame()
121 {
122 m_frame = new wxFrame(NULL, wxID_ANY, "test frame");
123
124 wxMenu *fileMenu = new wxMenu;
125 wxMenu *helpMenu = new wxMenu;
126 wxMenu *subMenu = new wxMenu;
127 wxMenu *subsubMenu = new wxMenu;
128
129 size_t itemcount = 0;
130
131 PopulateMenu(subsubMenu, "Subsubmenu item ", itemcount);
132
133 // Store one of its IDs for later
134 m_subsubmenuItemId = MenuTestCase_First + itemcount - 2;
135
136 PopulateMenu(subMenu, "Submenu item ", itemcount);
137
138 // Store one of its IDs for later
139 m_submenuItemId = MenuTestCase_First + itemcount - 2;
140
141 subMenu->AppendSubMenu(subsubMenu, "Subsubmen&u", "Test a subsubmenu");
142
143 PopulateMenu(fileMenu, "Filemenu item ", itemcount);
144
145 fileMenu->Append(MenuTestCase_Foo, "&Foo\tCtrl-F", "Test item to be found");
146
147
148 PopulateMenu(helpMenu, "Helpmenu item ", itemcount);
149 helpMenu->Append(MenuTestCase_Bar, "Bar");
150 helpMenu->AppendSubMenu(subMenu, "Sub&menu", "Test a submenu");
151
152 // +2 for "Foo" and "Bar", +2 for the 2 submenus
153 m_itemCount = itemcount + 4;
154
155 // Use an arraystring here, to help with future tests
156 m_menuLabels.Add("&File");
157 m_menuLabels.Add("&Help");
158
159 wxMenuBar *menuBar = new wxMenuBar();
160 menuBar->Append(fileMenu, m_menuLabels[0]);
161 menuBar->Append(helpMenu, m_menuLabels[1]);
162 m_frame->SetMenuBar(menuBar);
163 }
164
165 void MenuTestCase::FindInMenubar()
166 {
167 wxMenuBar* bar = m_frame->GetMenuBar();
168
169 // Find by name:
170 CPPUNIT_ASSERT( bar->FindMenu("File") != wxNOT_FOUND );
171 CPPUNIT_ASSERT( bar->FindMenu("&File") != wxNOT_FOUND );
172 CPPUNIT_ASSERT( bar->FindMenu("&Fail") == wxNOT_FOUND );
173
174 // Find by menu name plus item name:
175 CPPUNIT_ASSERT( bar->FindMenuItem("File", "Foo") != wxNOT_FOUND );
176 CPPUNIT_ASSERT( bar->FindMenuItem("&File", "&Foo") != wxNOT_FOUND );
177 // and using the menu label
178 int index = bar->FindMenu("&File");
179 CPPUNIT_ASSERT( index != wxNOT_FOUND );
180 wxString menulabel = bar->GetMenuLabel(index);
181 CPPUNIT_ASSERT( bar->FindMenuItem(menulabel, "&Foo") != wxNOT_FOUND );
182 // and title
183 wxString menutitle = bar->GetMenu(index)->GetTitle();
184 CPPUNIT_ASSERT( bar->FindMenuItem(menutitle, "&Foo") != wxNOT_FOUND );
185
186 // Find by position:
187 for (size_t n=0; n < bar->GetMenuCount(); ++n)
188 {
189 CPPUNIT_ASSERT( bar->GetMenu(n) );
190 }
191
192 // Find by id:
193 wxMenu* menu = NULL;
194 wxMenuItem* item = NULL;
195 item = bar->FindItem(MenuTestCase_Foo, &menu);
196 CPPUNIT_ASSERT( item );
197 CPPUNIT_ASSERT( menu );
198 // Check that the correct menu was found
199 CPPUNIT_ASSERT( menu->FindChildItem(MenuTestCase_Foo) );
200
201 // Find submenu item:
202 item = bar->FindItem(m_submenuItemId, &menu);
203 CPPUNIT_ASSERT( item );
204 CPPUNIT_ASSERT( menu );
205 // and, for completeness, a subsubmenu one:
206 item = bar->FindItem(m_subsubmenuItemId, &menu);
207 CPPUNIT_ASSERT( item );
208 CPPUNIT_ASSERT( menu );
209 }
210
211 void MenuTestCase::FindInMenu()
212 {
213 wxMenuBar* bar = m_frame->GetMenuBar();
214
215 // Find by name:
216 wxMenu* menuFind = bar->GetMenu(0);
217 CPPUNIT_ASSERT( menuFind->FindItem("Foo") != wxNOT_FOUND );
218 CPPUNIT_ASSERT( menuFind->FindItem("&Foo") != wxNOT_FOUND );
219 // and for submenus
220 wxMenu* menuHelp = bar->GetMenu(1);
221 CPPUNIT_ASSERT( menuHelp->FindItem("Submenu") != wxNOT_FOUND );
222 CPPUNIT_ASSERT( menuHelp->FindItem("Sub&menu") != wxNOT_FOUND );
223
224 // Find by position:
225 size_t n;
226 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
227 {
228 CPPUNIT_ASSERT( menuHelp->FindItemByPosition(n) );
229 }
230
231 // Find by id:
232 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Bar) );
233 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Foo) == NULL );
234
235 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
236 {
237 size_t locatedAt;
238 wxMenuItem* itemByPos = menuHelp->FindItemByPosition(n);
239 CPPUNIT_ASSERT( itemByPos );
240 wxMenuItem* itemById = menuHelp->FindChildItem(itemByPos->GetId(), &locatedAt);
241 CPPUNIT_ASSERT_EQUAL( itemByPos, itemById );
242 CPPUNIT_ASSERT_EQUAL( locatedAt, n );
243 }
244
245 // Find submenu item:
246 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
247 {
248 wxMenuItem* item = menuHelp->FindItemByPosition(n);
249 if (item->IsSubMenu())
250 {
251 wxMenu* submenu;
252 wxMenuItem* submenuItem = menuHelp->FindItem(m_submenuItemId, &submenu);
253 CPPUNIT_ASSERT( submenuItem );
254 CPPUNIT_ASSERT( item->GetSubMenu() == submenu );
255 }
256 }
257 }
258
259 void MenuTestCase::Count()
260 {
261 wxMenuBar* bar = m_frame->GetMenuBar();
262 // I suppose you could call this "counting menubars" :)
263 CPPUNIT_ASSERT( bar );
264
265 CPPUNIT_ASSERT_EQUAL( bar->GetMenuCount(), 2 );
266
267 size_t count = 0;
268 for (size_t n=0; n < bar->GetMenuCount(); ++n)
269 {
270 RecursivelyCountMenuItems(bar->GetMenu(n), count);
271 }
272 CPPUNIT_ASSERT_EQUAL( count, m_itemCount );
273 }
274
275 void MenuTestCase::Labels()
276 {
277 wxMenuBar* bar = m_frame->GetMenuBar();
278 CPPUNIT_ASSERT( bar );
279 wxMenu* filemenu;
280 wxMenuItem* itemFoo = bar->FindItem(MenuTestCase_Foo, &filemenu);
281 CPPUNIT_ASSERT( itemFoo );
282 CPPUNIT_ASSERT( filemenu );
283
284 // These return labels including mnemonics/accelerators:
285
286 // wxMenuBar
287 CPPUNIT_ASSERT_EQUAL( "&File", bar->GetMenuLabel(0) );
288 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", bar->GetLabel(MenuTestCase_Foo) );
289
290 // wxMenu
291 CPPUNIT_ASSERT_EQUAL( "&File", filemenu->GetTitle() );
292 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", filemenu->GetLabel(MenuTestCase_Foo) );
293
294 // wxMenuItem
295 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", itemFoo->GetItemLabel() );
296
297 // These return labels stripped of mnemonics/accelerators:
298
299 // wxMenuBar
300 CPPUNIT_ASSERT_EQUAL( "File", bar->GetMenuLabelText(0) );
301
302 // wxMenu
303 CPPUNIT_ASSERT_EQUAL( "Foo", filemenu->GetLabelText(MenuTestCase_Foo) );
304
305 // wxMenuItem
306 CPPUNIT_ASSERT_EQUAL( "Foo", itemFoo->GetItemLabelText() );
307 CPPUNIT_ASSERT_EQUAL( "Foo", wxMenuItem::GetLabelText("&Foo\tCtrl-F") );
308 }
309
310 void MenuTestCase::RadioItems()
311 {
312 wxMenuBar * const bar = m_frame->GetMenuBar();
313 wxMenu * const menu = new wxMenu;
314 bar->Append(menu, "&Radio");
315
316 // Adding consecutive radio items creates a radio group.
317 menu->AppendRadioItem(MenuTestCase_First, "Radio 0");
318 menu->AppendRadioItem(MenuTestCase_First + 1, "Radio 1");
319
320 // First item of a radio group is checked by default.
321 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First) );
322
323 // Checking the second one make the first one unchecked however.
324 menu->Check(MenuTestCase_First + 1, true);
325 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First) );
326 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
327
328 // Adding more radio items after a separator creates another radio group...
329 menu->AppendSeparator();
330 menu->AppendRadioItem(MenuTestCase_First + 2, "Radio 2");
331 menu->AppendRadioItem(MenuTestCase_First + 3, "Radio 3");
332 menu->AppendRadioItem(MenuTestCase_First + 4, "Radio 4");
333
334 // ... which is independent from the first one.
335 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 2) );
336
337 menu->Check(MenuTestCase_First + 3, true);
338 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
339 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 2) );
340 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
341
342
343 // Insert an item in the middle of an existing radio group.
344 menu->InsertRadioItem(4, MenuTestCase_First + 5, "Radio 5");
345 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
346
347 menu->Check( MenuTestCase_First + 5, true );
348 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 3) );
349
350
351 // Prepend a couple of items before the first group.
352 menu->PrependRadioItem(MenuTestCase_First + 6, "Radio 6");
353 menu->PrependRadioItem(MenuTestCase_First + 7, "Radio 7");
354 menu->Check(MenuTestCase_First + 7, true);
355 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 1) );
356
357
358 // Check that the last radio group still works as expected.
359 menu->Check(MenuTestCase_First + 4, true);
360 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 5) );
361 }