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