]> git.saurik.com Git - wxWidgets.git/blob - tests/menu/menu.cpp
79b1e3ec498304eb85149776fbd3da5201480f80
[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 "wx/uiaction.h"
26
27 #include <stdarg.h>
28
29 // ----------------------------------------------------------------------------
30 // helper
31 // ----------------------------------------------------------------------------
32
33 namespace
34 {
35
36 enum
37 {
38 MenuTestCase_Foo = 10000,
39 MenuTestCase_Bar,
40 MenuTestCase_First
41 };
42
43 void PopulateMenu(wxMenu* menu, const wxString& name, size_t& itemcount)
44 {
45 // Start at item 1 to make it human-readable ;)
46 for (int n=1; n<6; ++n, ++itemcount)
47 {
48 wxString label = name; label << n;
49 menu->Append(MenuTestCase_First + itemcount, label, label + " help string");
50 }
51 }
52
53 void RecursivelyCountMenuItems(const wxMenu* menu, size_t& count)
54 {
55 CPPUNIT_ASSERT( menu );
56
57 count += menu->GetMenuItemCount();
58 for (size_t n=0; n < menu->GetMenuItemCount(); ++n)
59 {
60 wxMenuItem* item = menu->FindItemByPosition(n);
61 if (item->IsSubMenu())
62 {
63 RecursivelyCountMenuItems(item->GetSubMenu(), count);
64 }
65 }
66 }
67
68 } // anon namespace
69
70
71 // ----------------------------------------------------------------------------
72 // test class
73 // ----------------------------------------------------------------------------
74
75 class MenuTestCase : public CppUnit::TestCase
76 {
77 public:
78 MenuTestCase() {}
79
80 virtual void setUp() { CreateFrame(); }
81 virtual void tearDown() { m_frame->Destroy(); }
82
83 private:
84 CPPUNIT_TEST_SUITE( MenuTestCase );
85 CPPUNIT_TEST( FindInMenubar );
86 CPPUNIT_TEST( FindInMenu );
87 CPPUNIT_TEST( EnableTop );
88 CPPUNIT_TEST( Count );
89 CPPUNIT_TEST( Labels );
90 CPPUNIT_TEST( RadioItems );
91 CPPUNIT_TEST( RemoveAdd );
92 WXUISIM_TEST( Events );
93 CPPUNIT_TEST_SUITE_END();
94
95 void CreateFrame();
96
97 void FindInMenubar();
98 void FindInMenu();
99 void EnableTop();
100 void Count();
101 void Labels();
102 void RadioItems();
103 void RemoveAdd();
104 void Events();
105
106 wxFrame* m_frame;
107
108 // Holds the number of menuitems contained in all the menus
109 size_t m_itemCount;
110
111 // Store here the id of a known submenu item, to be searched for later
112 int m_submenuItemId;
113
114 // and a sub-submenu item
115 int m_subsubmenuItemId;
116
117 wxArrayString m_menuLabels;
118
119 DECLARE_NO_COPY_CLASS(MenuTestCase)
120 };
121
122 // register in the unnamed registry so that these tests are run by default
123 CPPUNIT_TEST_SUITE_REGISTRATION( MenuTestCase );
124
125 // also include in its own registry so that these tests can be run alone
126 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MenuTestCase, "MenuTestCase" );
127
128 void MenuTestCase::CreateFrame()
129 {
130 m_frame = new wxFrame(NULL, wxID_ANY, "test frame");
131
132 wxMenu *fileMenu = new wxMenu;
133 wxMenu *helpMenu = new wxMenu;
134 wxMenu *subMenu = new wxMenu;
135 wxMenu *subsubMenu = new wxMenu;
136
137 size_t itemcount = 0;
138
139 PopulateMenu(subsubMenu, "Subsubmenu item ", itemcount);
140
141 // Store one of its IDs for later
142 m_subsubmenuItemId = MenuTestCase_First + itemcount - 2;
143
144 PopulateMenu(subMenu, "Submenu item ", itemcount);
145
146 // Store one of its IDs for later
147 m_submenuItemId = MenuTestCase_First + itemcount - 2;
148
149 subMenu->AppendSubMenu(subsubMenu, "Subsubmen&u", "Test a subsubmenu");
150
151 PopulateMenu(fileMenu, "Filemenu item ", itemcount);
152
153 fileMenu->Append(MenuTestCase_Foo, "&Foo\tCtrl-F", "Test item to be found");
154
155
156 PopulateMenu(helpMenu, "Helpmenu item ", itemcount);
157 helpMenu->Append(MenuTestCase_Bar, "Bar\tF1");
158 helpMenu->AppendSubMenu(subMenu, "Sub&menu", "Test a submenu");
159
160 // +2 for "Foo" and "Bar", +2 for the 2 submenus
161 m_itemCount = itemcount + 4;
162
163 // Use an arraystring here, to help with future tests
164 m_menuLabels.Add("&File");
165 m_menuLabels.Add("&Help");
166
167 wxMenuBar *menuBar = new wxMenuBar();
168 menuBar->Append(fileMenu, m_menuLabels[0]);
169 menuBar->Append(helpMenu, m_menuLabels[1]);
170 m_frame->SetMenuBar(menuBar);
171 }
172
173 void MenuTestCase::FindInMenubar()
174 {
175 wxMenuBar* bar = m_frame->GetMenuBar();
176
177 // Find by name:
178 CPPUNIT_ASSERT( bar->FindMenu("File") != wxNOT_FOUND );
179 CPPUNIT_ASSERT( bar->FindMenu("&File") != wxNOT_FOUND );
180 CPPUNIT_ASSERT( bar->FindMenu("&Fail") == wxNOT_FOUND );
181
182 // Find by menu name plus item name:
183 CPPUNIT_ASSERT( bar->FindMenuItem("File", "Foo") != wxNOT_FOUND );
184 CPPUNIT_ASSERT( bar->FindMenuItem("&File", "&Foo") != wxNOT_FOUND );
185 // and using the menu label
186 int index = bar->FindMenu("&File");
187 CPPUNIT_ASSERT( index != wxNOT_FOUND );
188 wxString menulabel = bar->GetMenuLabel(index);
189 CPPUNIT_ASSERT( bar->FindMenuItem(menulabel, "&Foo") != wxNOT_FOUND );
190 // and title
191 wxString menutitle = bar->GetMenu(index)->GetTitle();
192 CPPUNIT_ASSERT( bar->FindMenuItem(menutitle, "&Foo") != wxNOT_FOUND );
193
194 // Find by position:
195 for (size_t n=0; n < bar->GetMenuCount(); ++n)
196 {
197 CPPUNIT_ASSERT( bar->GetMenu(n) );
198 }
199
200 // Find by id:
201 wxMenu* menu = NULL;
202 wxMenuItem* item = NULL;
203 item = bar->FindItem(MenuTestCase_Foo, &menu);
204 CPPUNIT_ASSERT( item );
205 CPPUNIT_ASSERT( menu );
206 // Check that the correct menu was found
207 CPPUNIT_ASSERT( menu->FindChildItem(MenuTestCase_Foo) );
208
209 // Find submenu item:
210 item = bar->FindItem(m_submenuItemId, &menu);
211 CPPUNIT_ASSERT( item );
212 CPPUNIT_ASSERT( menu );
213 // and, for completeness, a subsubmenu one:
214 item = bar->FindItem(m_subsubmenuItemId, &menu);
215 CPPUNIT_ASSERT( item );
216 CPPUNIT_ASSERT( menu );
217 }
218
219 void MenuTestCase::FindInMenu()
220 {
221 wxMenuBar* bar = m_frame->GetMenuBar();
222
223 // Find by name:
224 wxMenu* menuFind = bar->GetMenu(0);
225 CPPUNIT_ASSERT( menuFind->FindItem("Foo") != wxNOT_FOUND );
226 CPPUNIT_ASSERT( menuFind->FindItem("&Foo") != wxNOT_FOUND );
227 // and for submenus
228 wxMenu* menuHelp = bar->GetMenu(1);
229 CPPUNIT_ASSERT( menuHelp->FindItem("Submenu") != wxNOT_FOUND );
230 CPPUNIT_ASSERT( menuHelp->FindItem("Sub&menu") != wxNOT_FOUND );
231
232 // Find by position:
233 size_t n;
234 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
235 {
236 CPPUNIT_ASSERT( menuHelp->FindItemByPosition(n) );
237 }
238
239 // Find by id:
240 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Bar) );
241 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Foo) == NULL );
242
243 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
244 {
245 size_t locatedAt;
246 wxMenuItem* itemByPos = menuHelp->FindItemByPosition(n);
247 CPPUNIT_ASSERT( itemByPos );
248 wxMenuItem* itemById = menuHelp->FindChildItem(itemByPos->GetId(), &locatedAt);
249 CPPUNIT_ASSERT_EQUAL( itemByPos, itemById );
250 CPPUNIT_ASSERT_EQUAL( locatedAt, n );
251 }
252
253 // Find submenu item:
254 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
255 {
256 wxMenuItem* item = menuHelp->FindItemByPosition(n);
257 if (item->IsSubMenu())
258 {
259 wxMenu* submenu;
260 wxMenuItem* submenuItem = menuHelp->FindItem(m_submenuItemId, &submenu);
261 CPPUNIT_ASSERT( submenuItem );
262 CPPUNIT_ASSERT( item->GetSubMenu() == submenu );
263 }
264 }
265 }
266
267 void MenuTestCase::EnableTop()
268 {
269 wxMenuBar* const bar = m_frame->GetMenuBar();
270 CPPUNIT_ASSERT( bar->IsEnabledTop(0) );
271 bar->EnableTop( 0, false );
272 CPPUNIT_ASSERT( !bar->IsEnabledTop(0) );
273 bar->EnableTop( 0, true );
274 CPPUNIT_ASSERT( bar->IsEnabledTop(0) );
275 }
276
277 void MenuTestCase::Count()
278 {
279 wxMenuBar* bar = m_frame->GetMenuBar();
280 // I suppose you could call this "counting menubars" :)
281 CPPUNIT_ASSERT( bar );
282
283 CPPUNIT_ASSERT_EQUAL( bar->GetMenuCount(), 2 );
284
285 size_t count = 0;
286 for (size_t n=0; n < bar->GetMenuCount(); ++n)
287 {
288 RecursivelyCountMenuItems(bar->GetMenu(n), count);
289 }
290 CPPUNIT_ASSERT_EQUAL( count, m_itemCount );
291 }
292
293 void MenuTestCase::Labels()
294 {
295 wxMenuBar* bar = m_frame->GetMenuBar();
296 CPPUNIT_ASSERT( bar );
297 wxMenu* filemenu;
298 wxMenuItem* itemFoo = bar->FindItem(MenuTestCase_Foo, &filemenu);
299 CPPUNIT_ASSERT( itemFoo );
300 CPPUNIT_ASSERT( filemenu );
301
302 // These return labels including mnemonics/accelerators:
303
304 // wxMenuBar
305 CPPUNIT_ASSERT_EQUAL( "&File", bar->GetMenuLabel(0) );
306 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", bar->GetLabel(MenuTestCase_Foo) );
307
308 // wxMenu
309 CPPUNIT_ASSERT_EQUAL( "&File", filemenu->GetTitle() );
310 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", filemenu->GetLabel(MenuTestCase_Foo) );
311
312 // wxMenuItem
313 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", itemFoo->GetItemLabel() );
314
315 // These return labels stripped of mnemonics/accelerators:
316
317 // wxMenuBar
318 CPPUNIT_ASSERT_EQUAL( "File", bar->GetMenuLabelText(0) );
319
320 // wxMenu
321 CPPUNIT_ASSERT_EQUAL( "Foo", filemenu->GetLabelText(MenuTestCase_Foo) );
322
323 // wxMenuItem
324 CPPUNIT_ASSERT_EQUAL( "Foo", itemFoo->GetItemLabelText() );
325 CPPUNIT_ASSERT_EQUAL( "Foo", wxMenuItem::GetLabelText("&Foo\tCtrl-F") );
326 }
327
328 void MenuTestCase::RadioItems()
329 {
330 wxMenuBar * const bar = m_frame->GetMenuBar();
331 wxMenu * const menu = new wxMenu;
332 bar->Append(menu, "&Radio");
333
334 // Adding consecutive radio items creates a radio group.
335 menu->AppendRadioItem(MenuTestCase_First, "Radio 0");
336 menu->AppendRadioItem(MenuTestCase_First + 1, "Radio 1");
337
338 // First item of a radio group is checked by default.
339 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First) );
340
341 // Checking the second one make the first one unchecked however.
342 menu->Check(MenuTestCase_First + 1, true);
343 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First) );
344 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
345
346 // Adding more radio items after a separator creates another radio group...
347 menu->AppendSeparator();
348 menu->AppendRadioItem(MenuTestCase_First + 2, "Radio 2");
349 menu->AppendRadioItem(MenuTestCase_First + 3, "Radio 3");
350 menu->AppendRadioItem(MenuTestCase_First + 4, "Radio 4");
351
352 // ... which is independent from the first one.
353 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 2) );
354
355 menu->Check(MenuTestCase_First + 3, true);
356 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
357 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 2) );
358 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
359
360
361 // Insert an item in the middle of an existing radio group.
362 menu->InsertRadioItem(4, MenuTestCase_First + 5, "Radio 5");
363 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
364
365 menu->Check( MenuTestCase_First + 5, true );
366 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 3) );
367
368
369 // Prepend a couple of items before the first group.
370 menu->PrependRadioItem(MenuTestCase_First + 6, "Radio 6");
371 menu->PrependRadioItem(MenuTestCase_First + 7, "Radio 7");
372 menu->Check(MenuTestCase_First + 7, true);
373 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 1) );
374
375
376 // Check that the last radio group still works as expected.
377 menu->Check(MenuTestCase_First + 4, true);
378 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 5) );
379 }
380
381 void MenuTestCase::RemoveAdd()
382 {
383 wxMenuBar* bar = m_frame->GetMenuBar();
384
385 wxMenu* menu0 = bar->GetMenu(0);
386 wxMenu* menu1 = bar->GetMenu(1);
387 wxMenuItem* item = new wxMenuItem(menu0, MenuTestCase_Foo + 100, "t&ext\tCtrl-E");
388 menu0->Insert(0, item);
389 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) == item );
390 menu0->Remove(item);
391 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) != item );
392 menu1->Insert(0, item);
393 CPPUNIT_ASSERT( menu1->FindItemByPosition(0) == item );
394 menu1->Remove(item);
395 CPPUNIT_ASSERT( menu1->FindItemByPosition(0) != item );
396 menu0->Insert(0, item);
397 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) == item );
398 menu0->Delete(item);
399 }
400
401 void MenuTestCase::Events()
402 {
403 #if wxUSE_UIACTIONSIMULATOR
404 class MenuEventHandler : public wxEvtHandler
405 {
406 public:
407 MenuEventHandler(wxWindow* win)
408 : m_win(win)
409 {
410 m_win->Connect(wxEVT_COMMAND_MENU_SELECTED,
411 wxCommandEventHandler(MenuEventHandler::OnMenu),
412 NULL,
413 this);
414
415 m_gotEvent = false;
416 m_event = NULL;
417 }
418
419 virtual ~MenuEventHandler()
420 {
421 m_win->Disconnect(wxEVT_COMMAND_MENU_SELECTED,
422 wxCommandEventHandler(MenuEventHandler::OnMenu),
423 NULL,
424 this);
425
426 delete m_event;
427 }
428
429 const wxCommandEvent& GetEvent()
430 {
431 CPPUNIT_ASSERT( m_gotEvent );
432
433 m_gotEvent = false;
434
435 return *m_event;
436 }
437
438 private:
439 void OnMenu(wxCommandEvent& event)
440 {
441 CPPUNIT_ASSERT( !m_gotEvent );
442
443 delete m_event;
444 m_event = static_cast<wxCommandEvent*>(event.Clone());
445 m_gotEvent = true;
446 }
447
448 wxWindow* const m_win;
449 wxCommandEvent* m_event;
450 bool m_gotEvent;
451 };
452
453 MenuEventHandler handler(m_frame);
454
455 // Invoke the accelerator.
456 m_frame->Show();
457 m_frame->SetFocus();
458 wxYield();
459
460 wxUIActionSimulator sim;
461 sim.KeyDown(WXK_F1);
462 sim.KeyUp(WXK_F1);
463 wxYield();
464
465 const wxCommandEvent& ev = handler.GetEvent();
466 CPPUNIT_ASSERT_EQUAL( static_cast<int>(MenuTestCase_Bar), ev.GetId() );
467 #endif // wxUSE_UIACTIONSIMULATOR
468 }