]> git.saurik.com Git - wxWidgets.git/blob - tests/menu/menu.cpp
Check wxListCtrl::GetItemRect() origin in the unit tests.
[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 // The menu containing the item with MenuTestCase_Bar id.
120 wxMenu* m_menuWithBar;
121
122 DECLARE_NO_COPY_CLASS(MenuTestCase)
123 };
124
125 // register in the unnamed registry so that these tests are run by default
126 CPPUNIT_TEST_SUITE_REGISTRATION( MenuTestCase );
127
128 // also include in its own registry so that these tests can be run alone
129 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MenuTestCase, "MenuTestCase" );
130
131 void MenuTestCase::CreateFrame()
132 {
133 m_frame = new wxFrame(NULL, wxID_ANY, "test frame");
134
135 wxMenu *fileMenu = new wxMenu;
136 wxMenu *helpMenu = new wxMenu;
137 wxMenu *subMenu = new wxMenu;
138 wxMenu *subsubMenu = new wxMenu;
139
140 size_t itemcount = 0;
141
142 PopulateMenu(subsubMenu, "Subsubmenu item ", itemcount);
143
144 // Store one of its IDs for later
145 m_subsubmenuItemId = MenuTestCase_First + itemcount - 2;
146
147 PopulateMenu(subMenu, "Submenu item ", itemcount);
148
149 // Store one of its IDs for later
150 m_submenuItemId = MenuTestCase_First + itemcount - 2;
151
152 subMenu->AppendSubMenu(subsubMenu, "Subsubmen&u", "Test a subsubmenu");
153
154 PopulateMenu(fileMenu, "Filemenu item ", itemcount);
155
156 fileMenu->Append(MenuTestCase_Foo, "&Foo\tCtrl-F", "Test item to be found");
157
158
159 PopulateMenu(helpMenu, "Helpmenu item ", itemcount);
160 helpMenu->Append(MenuTestCase_Bar, "Bar\tF1");
161 m_menuWithBar = helpMenu;
162 helpMenu->AppendSubMenu(subMenu, "Sub&menu", "Test a submenu");
163
164 // +2 for "Foo" and "Bar", +2 for the 2 submenus
165 m_itemCount = itemcount + 4;
166
167 // Use an arraystring here, to help with future tests
168 m_menuLabels.Add("&File");
169 m_menuLabels.Add("&Help");
170
171 wxMenuBar *menuBar = new wxMenuBar();
172 menuBar->Append(fileMenu, m_menuLabels[0]);
173 menuBar->Append(helpMenu, m_menuLabels[1]);
174 m_frame->SetMenuBar(menuBar);
175 }
176
177 void MenuTestCase::FindInMenubar()
178 {
179 wxMenuBar* bar = m_frame->GetMenuBar();
180
181 // Find by name:
182 CPPUNIT_ASSERT( bar->FindMenu("File") != wxNOT_FOUND );
183 CPPUNIT_ASSERT( bar->FindMenu("&File") != wxNOT_FOUND );
184 CPPUNIT_ASSERT( bar->FindMenu("&Fail") == wxNOT_FOUND );
185
186 // Find by menu name plus item name:
187 CPPUNIT_ASSERT( bar->FindMenuItem("File", "Foo") != wxNOT_FOUND );
188 CPPUNIT_ASSERT( bar->FindMenuItem("&File", "&Foo") != wxNOT_FOUND );
189 // and using the menu label
190 int index = bar->FindMenu("&File");
191 CPPUNIT_ASSERT( index != wxNOT_FOUND );
192 wxString menulabel = bar->GetMenuLabel(index);
193 CPPUNIT_ASSERT( bar->FindMenuItem(menulabel, "&Foo") != wxNOT_FOUND );
194 // and title
195 wxString menutitle = bar->GetMenu(index)->GetTitle();
196 CPPUNIT_ASSERT( bar->FindMenuItem(menutitle, "&Foo") != wxNOT_FOUND );
197
198 // Find by position:
199 for (size_t n=0; n < bar->GetMenuCount(); ++n)
200 {
201 CPPUNIT_ASSERT( bar->GetMenu(n) );
202 }
203
204 // Find by id:
205 wxMenu* menu = NULL;
206 wxMenuItem* item = NULL;
207 item = bar->FindItem(MenuTestCase_Foo, &menu);
208 CPPUNIT_ASSERT( item );
209 CPPUNIT_ASSERT( menu );
210 // Check that the correct menu was found
211 CPPUNIT_ASSERT( menu->FindChildItem(MenuTestCase_Foo) );
212
213 // Find submenu item:
214 item = bar->FindItem(m_submenuItemId, &menu);
215 CPPUNIT_ASSERT( item );
216 CPPUNIT_ASSERT( menu );
217 // and, for completeness, a subsubmenu one:
218 item = bar->FindItem(m_subsubmenuItemId, &menu);
219 CPPUNIT_ASSERT( item );
220 CPPUNIT_ASSERT( menu );
221 }
222
223 void MenuTestCase::FindInMenu()
224 {
225 wxMenuBar* bar = m_frame->GetMenuBar();
226
227 // Find by name:
228 wxMenu* menuFind = bar->GetMenu(0);
229 CPPUNIT_ASSERT( menuFind->FindItem("Foo") != wxNOT_FOUND );
230 CPPUNIT_ASSERT( menuFind->FindItem("&Foo") != wxNOT_FOUND );
231 // and for submenus
232 wxMenu* menuHelp = bar->GetMenu(1);
233 CPPUNIT_ASSERT( menuHelp->FindItem("Submenu") != wxNOT_FOUND );
234 CPPUNIT_ASSERT( menuHelp->FindItem("Sub&menu") != wxNOT_FOUND );
235
236 // Find by position:
237 size_t n;
238 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
239 {
240 CPPUNIT_ASSERT( menuHelp->FindItemByPosition(n) );
241 }
242
243 // Find by id:
244 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Bar) );
245 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Foo) == NULL );
246
247 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
248 {
249 size_t locatedAt;
250 wxMenuItem* itemByPos = menuHelp->FindItemByPosition(n);
251 CPPUNIT_ASSERT( itemByPos );
252 wxMenuItem* itemById = menuHelp->FindChildItem(itemByPos->GetId(), &locatedAt);
253 CPPUNIT_ASSERT_EQUAL( itemByPos, itemById );
254 CPPUNIT_ASSERT_EQUAL( locatedAt, n );
255 }
256
257 // Find submenu item:
258 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
259 {
260 wxMenuItem* item = menuHelp->FindItemByPosition(n);
261 if (item->IsSubMenu())
262 {
263 wxMenu* submenu;
264 wxMenuItem* submenuItem = menuHelp->FindItem(m_submenuItemId, &submenu);
265 CPPUNIT_ASSERT( submenuItem );
266 CPPUNIT_ASSERT( item->GetSubMenu() == submenu );
267 }
268 }
269 }
270
271 void MenuTestCase::EnableTop()
272 {
273 wxMenuBar* const bar = m_frame->GetMenuBar();
274 CPPUNIT_ASSERT( bar->IsEnabledTop(0) );
275 bar->EnableTop( 0, false );
276 CPPUNIT_ASSERT( !bar->IsEnabledTop(0) );
277 bar->EnableTop( 0, true );
278 CPPUNIT_ASSERT( bar->IsEnabledTop(0) );
279 }
280
281 void MenuTestCase::Count()
282 {
283 wxMenuBar* bar = m_frame->GetMenuBar();
284 // I suppose you could call this "counting menubars" :)
285 CPPUNIT_ASSERT( bar );
286
287 CPPUNIT_ASSERT_EQUAL( bar->GetMenuCount(), 2 );
288
289 size_t count = 0;
290 for (size_t n=0; n < bar->GetMenuCount(); ++n)
291 {
292 RecursivelyCountMenuItems(bar->GetMenu(n), count);
293 }
294 CPPUNIT_ASSERT_EQUAL( count, m_itemCount );
295 }
296
297 void MenuTestCase::Labels()
298 {
299 wxMenuBar* bar = m_frame->GetMenuBar();
300 CPPUNIT_ASSERT( bar );
301 wxMenu* filemenu;
302 wxMenuItem* itemFoo = bar->FindItem(MenuTestCase_Foo, &filemenu);
303 CPPUNIT_ASSERT( itemFoo );
304 CPPUNIT_ASSERT( filemenu );
305
306 // These return labels including mnemonics/accelerators:
307
308 // wxMenuBar
309 CPPUNIT_ASSERT_EQUAL( "&File", bar->GetMenuLabel(0) );
310 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", bar->GetLabel(MenuTestCase_Foo) );
311
312 // wxMenu
313 CPPUNIT_ASSERT_EQUAL( "&File", filemenu->GetTitle() );
314 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", filemenu->GetLabel(MenuTestCase_Foo) );
315
316 // wxMenuItem
317 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", itemFoo->GetItemLabel() );
318
319 // These return labels stripped of mnemonics/accelerators:
320
321 // wxMenuBar
322 CPPUNIT_ASSERT_EQUAL( "File", bar->GetMenuLabelText(0) );
323
324 // wxMenu
325 CPPUNIT_ASSERT_EQUAL( "Foo", filemenu->GetLabelText(MenuTestCase_Foo) );
326
327 // wxMenuItem
328 CPPUNIT_ASSERT_EQUAL( "Foo", itemFoo->GetItemLabelText() );
329 CPPUNIT_ASSERT_EQUAL( "Foo", wxMenuItem::GetLabelText("&Foo\tCtrl-F") );
330 }
331
332 void MenuTestCase::RadioItems()
333 {
334 wxMenuBar * const bar = m_frame->GetMenuBar();
335 wxMenu * const menu = new wxMenu;
336 bar->Append(menu, "&Radio");
337
338 // Adding consecutive radio items creates a radio group.
339 menu->AppendRadioItem(MenuTestCase_First, "Radio 0");
340 menu->AppendRadioItem(MenuTestCase_First + 1, "Radio 1");
341
342 // First item of a radio group is checked by default.
343 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First) );
344
345 // Checking the second one make the first one unchecked however.
346 menu->Check(MenuTestCase_First + 1, true);
347 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First) );
348 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
349
350 // Adding more radio items after a separator creates another radio group...
351 menu->AppendSeparator();
352 menu->AppendRadioItem(MenuTestCase_First + 2, "Radio 2");
353 menu->AppendRadioItem(MenuTestCase_First + 3, "Radio 3");
354 menu->AppendRadioItem(MenuTestCase_First + 4, "Radio 4");
355
356 // ... which is independent from the first one.
357 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 2) );
358
359 menu->Check(MenuTestCase_First + 3, true);
360 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
361 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 2) );
362 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
363
364
365 // Insert an item in the middle of an existing radio group.
366 menu->InsertRadioItem(4, MenuTestCase_First + 5, "Radio 5");
367 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
368
369 menu->Check( MenuTestCase_First + 5, true );
370 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 3) );
371
372
373 // Prepend a couple of items before the first group.
374 menu->PrependRadioItem(MenuTestCase_First + 6, "Radio 6");
375 menu->PrependRadioItem(MenuTestCase_First + 7, "Radio 7");
376 menu->Check(MenuTestCase_First + 7, true);
377 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 1) );
378
379
380 // Check that the last radio group still works as expected.
381 menu->Check(MenuTestCase_First + 4, true);
382 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 5) );
383 }
384
385 void MenuTestCase::RemoveAdd()
386 {
387 wxMenuBar* bar = m_frame->GetMenuBar();
388
389 wxMenu* menu0 = bar->GetMenu(0);
390 wxMenu* menu1 = bar->GetMenu(1);
391 wxMenuItem* item = new wxMenuItem(menu0, MenuTestCase_Foo + 100, "t&ext\tCtrl-E");
392 menu0->Insert(0, item);
393 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) == item );
394 menu0->Remove(item);
395 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) != item );
396 menu1->Insert(0, item);
397 CPPUNIT_ASSERT( menu1->FindItemByPosition(0) == item );
398 menu1->Remove(item);
399 CPPUNIT_ASSERT( menu1->FindItemByPosition(0) != item );
400 menu0->Insert(0, item);
401 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) == item );
402 menu0->Delete(item);
403 }
404
405 void MenuTestCase::Events()
406 {
407 #ifdef __WXGTK__
408 // FIXME: For some reason, we sporadically fail to get the event in
409 // buildbot slave builds even though the test always passes locally.
410 // There is undoubtedly something wrong here but without being able
411 // to debug it, I have no idea what is it, so let's just disable
412 // this test when running under buildbot to let the entire test
413 // suite pass.
414 if ( IsAutomaticTest() )
415 return;
416 #endif // __WXGTK__
417
418 #if wxUSE_UIACTIONSIMULATOR
419 class MenuEventHandler : public wxEvtHandler
420 {
421 public:
422 MenuEventHandler(wxWindow* win)
423 : m_win(win)
424 {
425 m_win->Connect(wxEVT_MENU,
426 wxCommandEventHandler(MenuEventHandler::OnMenu),
427 NULL,
428 this);
429
430 m_gotEvent = false;
431 m_event = NULL;
432 }
433
434 virtual ~MenuEventHandler()
435 {
436 m_win->Disconnect(wxEVT_MENU,
437 wxCommandEventHandler(MenuEventHandler::OnMenu),
438 NULL,
439 this);
440
441 delete m_event;
442 }
443
444 const wxCommandEvent& GetEvent()
445 {
446 CPPUNIT_ASSERT( m_gotEvent );
447
448 m_gotEvent = false;
449
450 return *m_event;
451 }
452
453 private:
454 void OnMenu(wxCommandEvent& event)
455 {
456 CPPUNIT_ASSERT( !m_gotEvent );
457
458 delete m_event;
459 m_event = static_cast<wxCommandEvent*>(event.Clone());
460 m_gotEvent = true;
461 }
462
463 wxWindow* const m_win;
464 wxCommandEvent* m_event;
465 bool m_gotEvent;
466 };
467
468 MenuEventHandler handler(m_frame);
469
470 // Invoke the accelerator.
471 m_frame->Show();
472 m_frame->SetFocus();
473 wxYield();
474
475 wxUIActionSimulator sim;
476 sim.KeyDown(WXK_F1);
477 sim.KeyUp(WXK_F1);
478 wxYield();
479
480 const wxCommandEvent& ev = handler.GetEvent();
481 CPPUNIT_ASSERT_EQUAL( static_cast<int>(MenuTestCase_Bar), ev.GetId() );
482
483 wxObject* const src = ev.GetEventObject();
484 CPPUNIT_ASSERT( src );
485
486 CPPUNIT_ASSERT_EQUAL( "wxMenu",
487 wxString(src->GetClassInfo()->GetClassName()) );
488 CPPUNIT_ASSERT_EQUAL( static_cast<wxObject*>(m_menuWithBar),
489 src );
490 #endif // wxUSE_UIACTIONSIMULATOR
491 }