Implement wxMenuBar::EnableTop() for wxMSW and wxGTK.
[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( EnableTop );
86 CPPUNIT_TEST( Count );
87 CPPUNIT_TEST( Labels );
88 CPPUNIT_TEST( RadioItems );
89 CPPUNIT_TEST( RemoveAdd );
90 CPPUNIT_TEST_SUITE_END();
91
92 void CreateFrame();
93
94 void FindInMenubar();
95 void FindInMenu();
96 void EnableTop();
97 void Count();
98 void Labels();
99 void RadioItems();
100 void RemoveAdd();
101
102 wxFrame* m_frame;
103
104 // Holds the number of menuitems contained in all the menus
105 size_t m_itemCount;
106
107 // Store here the id of a known submenu item, to be searched for later
108 int m_submenuItemId;
109
110 // and a sub-submenu item
111 int m_subsubmenuItemId;
112
113 wxArrayString m_menuLabels;
114
115 DECLARE_NO_COPY_CLASS(MenuTestCase)
116 };
117
118 // register in the unnamed registry so that these tests are run by default
119 CPPUNIT_TEST_SUITE_REGISTRATION( MenuTestCase );
120
121 // also include in its own registry so that these tests can be run alone
122 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MenuTestCase, "MenuTestCase" );
123
124 void MenuTestCase::CreateFrame()
125 {
126 m_frame = new wxFrame(NULL, wxID_ANY, "test frame");
127
128 wxMenu *fileMenu = new wxMenu;
129 wxMenu *helpMenu = new wxMenu;
130 wxMenu *subMenu = new wxMenu;
131 wxMenu *subsubMenu = new wxMenu;
132
133 size_t itemcount = 0;
134
135 PopulateMenu(subsubMenu, "Subsubmenu item ", itemcount);
136
137 // Store one of its IDs for later
138 m_subsubmenuItemId = MenuTestCase_First + itemcount - 2;
139
140 PopulateMenu(subMenu, "Submenu item ", itemcount);
141
142 // Store one of its IDs for later
143 m_submenuItemId = MenuTestCase_First + itemcount - 2;
144
145 subMenu->AppendSubMenu(subsubMenu, "Subsubmen&u", "Test a subsubmenu");
146
147 PopulateMenu(fileMenu, "Filemenu item ", itemcount);
148
149 fileMenu->Append(MenuTestCase_Foo, "&Foo\tCtrl-F", "Test item to be found");
150
151
152 PopulateMenu(helpMenu, "Helpmenu item ", itemcount);
153 helpMenu->Append(MenuTestCase_Bar, "Bar");
154 helpMenu->AppendSubMenu(subMenu, "Sub&menu", "Test a submenu");
155
156 // +2 for "Foo" and "Bar", +2 for the 2 submenus
157 m_itemCount = itemcount + 4;
158
159 // Use an arraystring here, to help with future tests
160 m_menuLabels.Add("&File");
161 m_menuLabels.Add("&Help");
162
163 wxMenuBar *menuBar = new wxMenuBar();
164 menuBar->Append(fileMenu, m_menuLabels[0]);
165 menuBar->Append(helpMenu, m_menuLabels[1]);
166 m_frame->SetMenuBar(menuBar);
167 }
168
169 void MenuTestCase::FindInMenubar()
170 {
171 wxMenuBar* bar = m_frame->GetMenuBar();
172
173 // Find by name:
174 CPPUNIT_ASSERT( bar->FindMenu("File") != wxNOT_FOUND );
175 CPPUNIT_ASSERT( bar->FindMenu("&File") != wxNOT_FOUND );
176 CPPUNIT_ASSERT( bar->FindMenu("&Fail") == wxNOT_FOUND );
177
178 // Find by menu name plus item name:
179 CPPUNIT_ASSERT( bar->FindMenuItem("File", "Foo") != wxNOT_FOUND );
180 CPPUNIT_ASSERT( bar->FindMenuItem("&File", "&Foo") != wxNOT_FOUND );
181 // and using the menu label
182 int index = bar->FindMenu("&File");
183 CPPUNIT_ASSERT( index != wxNOT_FOUND );
184 wxString menulabel = bar->GetMenuLabel(index);
185 CPPUNIT_ASSERT( bar->FindMenuItem(menulabel, "&Foo") != wxNOT_FOUND );
186 // and title
187 wxString menutitle = bar->GetMenu(index)->GetTitle();
188 CPPUNIT_ASSERT( bar->FindMenuItem(menutitle, "&Foo") != wxNOT_FOUND );
189
190 // Find by position:
191 for (size_t n=0; n < bar->GetMenuCount(); ++n)
192 {
193 CPPUNIT_ASSERT( bar->GetMenu(n) );
194 }
195
196 // Find by id:
197 wxMenu* menu = NULL;
198 wxMenuItem* item = NULL;
199 item = bar->FindItem(MenuTestCase_Foo, &menu);
200 CPPUNIT_ASSERT( item );
201 CPPUNIT_ASSERT( menu );
202 // Check that the correct menu was found
203 CPPUNIT_ASSERT( menu->FindChildItem(MenuTestCase_Foo) );
204
205 // Find submenu item:
206 item = bar->FindItem(m_submenuItemId, &menu);
207 CPPUNIT_ASSERT( item );
208 CPPUNIT_ASSERT( menu );
209 // and, for completeness, a subsubmenu one:
210 item = bar->FindItem(m_subsubmenuItemId, &menu);
211 CPPUNIT_ASSERT( item );
212 CPPUNIT_ASSERT( menu );
213 }
214
215 void MenuTestCase::FindInMenu()
216 {
217 wxMenuBar* bar = m_frame->GetMenuBar();
218
219 // Find by name:
220 wxMenu* menuFind = bar->GetMenu(0);
221 CPPUNIT_ASSERT( menuFind->FindItem("Foo") != wxNOT_FOUND );
222 CPPUNIT_ASSERT( menuFind->FindItem("&Foo") != wxNOT_FOUND );
223 // and for submenus
224 wxMenu* menuHelp = bar->GetMenu(1);
225 CPPUNIT_ASSERT( menuHelp->FindItem("Submenu") != wxNOT_FOUND );
226 CPPUNIT_ASSERT( menuHelp->FindItem("Sub&menu") != wxNOT_FOUND );
227
228 // Find by position:
229 size_t n;
230 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
231 {
232 CPPUNIT_ASSERT( menuHelp->FindItemByPosition(n) );
233 }
234
235 // Find by id:
236 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Bar) );
237 CPPUNIT_ASSERT( menuHelp->FindItem(MenuTestCase_Foo) == NULL );
238
239 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
240 {
241 size_t locatedAt;
242 wxMenuItem* itemByPos = menuHelp->FindItemByPosition(n);
243 CPPUNIT_ASSERT( itemByPos );
244 wxMenuItem* itemById = menuHelp->FindChildItem(itemByPos->GetId(), &locatedAt);
245 CPPUNIT_ASSERT_EQUAL( itemByPos, itemById );
246 CPPUNIT_ASSERT_EQUAL( locatedAt, n );
247 }
248
249 // Find submenu item:
250 for (n=0; n < menuHelp->GetMenuItemCount(); ++n)
251 {
252 wxMenuItem* item = menuHelp->FindItemByPosition(n);
253 if (item->IsSubMenu())
254 {
255 wxMenu* submenu;
256 wxMenuItem* submenuItem = menuHelp->FindItem(m_submenuItemId, &submenu);
257 CPPUNIT_ASSERT( submenuItem );
258 CPPUNIT_ASSERT( item->GetSubMenu() == submenu );
259 }
260 }
261 }
262
263 void MenuTestCase::EnableTop()
264 {
265 wxMenuBar* const bar = m_frame->GetMenuBar();
266 CPPUNIT_ASSERT( bar->IsEnabledTop(0) );
267 bar->EnableTop( 0, false );
268 CPPUNIT_ASSERT( !bar->IsEnabledTop(0) );
269 bar->EnableTop( 0, true );
270 CPPUNIT_ASSERT( bar->IsEnabledTop(0) );
271 }
272
273 void MenuTestCase::Count()
274 {
275 wxMenuBar* bar = m_frame->GetMenuBar();
276 // I suppose you could call this "counting menubars" :)
277 CPPUNIT_ASSERT( bar );
278
279 CPPUNIT_ASSERT_EQUAL( bar->GetMenuCount(), 2 );
280
281 size_t count = 0;
282 for (size_t n=0; n < bar->GetMenuCount(); ++n)
283 {
284 RecursivelyCountMenuItems(bar->GetMenu(n), count);
285 }
286 CPPUNIT_ASSERT_EQUAL( count, m_itemCount );
287 }
288
289 void MenuTestCase::Labels()
290 {
291 wxMenuBar* bar = m_frame->GetMenuBar();
292 CPPUNIT_ASSERT( bar );
293 wxMenu* filemenu;
294 wxMenuItem* itemFoo = bar->FindItem(MenuTestCase_Foo, &filemenu);
295 CPPUNIT_ASSERT( itemFoo );
296 CPPUNIT_ASSERT( filemenu );
297
298 // These return labels including mnemonics/accelerators:
299
300 // wxMenuBar
301 CPPUNIT_ASSERT_EQUAL( "&File", bar->GetMenuLabel(0) );
302 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", bar->GetLabel(MenuTestCase_Foo) );
303
304 // wxMenu
305 CPPUNIT_ASSERT_EQUAL( "&File", filemenu->GetTitle() );
306 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", filemenu->GetLabel(MenuTestCase_Foo) );
307
308 // wxMenuItem
309 CPPUNIT_ASSERT_EQUAL( "&Foo\tCtrl-F", itemFoo->GetItemLabel() );
310
311 // These return labels stripped of mnemonics/accelerators:
312
313 // wxMenuBar
314 CPPUNIT_ASSERT_EQUAL( "File", bar->GetMenuLabelText(0) );
315
316 // wxMenu
317 CPPUNIT_ASSERT_EQUAL( "Foo", filemenu->GetLabelText(MenuTestCase_Foo) );
318
319 // wxMenuItem
320 CPPUNIT_ASSERT_EQUAL( "Foo", itemFoo->GetItemLabelText() );
321 CPPUNIT_ASSERT_EQUAL( "Foo", wxMenuItem::GetLabelText("&Foo\tCtrl-F") );
322 }
323
324 void MenuTestCase::RadioItems()
325 {
326 wxMenuBar * const bar = m_frame->GetMenuBar();
327 wxMenu * const menu = new wxMenu;
328 bar->Append(menu, "&Radio");
329
330 // Adding consecutive radio items creates a radio group.
331 menu->AppendRadioItem(MenuTestCase_First, "Radio 0");
332 menu->AppendRadioItem(MenuTestCase_First + 1, "Radio 1");
333
334 // First item of a radio group is checked by default.
335 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First) );
336
337 // Checking the second one make the first one unchecked however.
338 menu->Check(MenuTestCase_First + 1, true);
339 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First) );
340 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
341
342 // Adding more radio items after a separator creates another radio group...
343 menu->AppendSeparator();
344 menu->AppendRadioItem(MenuTestCase_First + 2, "Radio 2");
345 menu->AppendRadioItem(MenuTestCase_First + 3, "Radio 3");
346 menu->AppendRadioItem(MenuTestCase_First + 4, "Radio 4");
347
348 // ... which is independent from the first one.
349 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 2) );
350
351 menu->Check(MenuTestCase_First + 3, true);
352 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
353 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 2) );
354 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 1) );
355
356
357 // Insert an item in the middle of an existing radio group.
358 menu->InsertRadioItem(4, MenuTestCase_First + 5, "Radio 5");
359 CPPUNIT_ASSERT( menu->IsChecked(MenuTestCase_First + 3) );
360
361 menu->Check( MenuTestCase_First + 5, true );
362 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 3) );
363
364
365 // Prepend a couple of items before the first group.
366 menu->PrependRadioItem(MenuTestCase_First + 6, "Radio 6");
367 menu->PrependRadioItem(MenuTestCase_First + 7, "Radio 7");
368 menu->Check(MenuTestCase_First + 7, true);
369 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 1) );
370
371
372 // Check that the last radio group still works as expected.
373 menu->Check(MenuTestCase_First + 4, true);
374 CPPUNIT_ASSERT( !menu->IsChecked(MenuTestCase_First + 5) );
375 }
376
377 void MenuTestCase::RemoveAdd()
378 {
379 wxMenuBar* bar = m_frame->GetMenuBar();
380
381 wxMenu* menu0 = bar->GetMenu(0);
382 wxMenu* menu1 = bar->GetMenu(1);
383 wxMenuItem* item = new wxMenuItem(menu0, MenuTestCase_Foo + 100, "t&ext\tCtrl-E");
384 menu0->Insert(0, item);
385 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) == item );
386 menu0->Remove(item);
387 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) != item );
388 menu1->Insert(0, item);
389 CPPUNIT_ASSERT( menu1->FindItemByPosition(0) == item );
390 menu1->Remove(item);
391 CPPUNIT_ASSERT( menu1->FindItemByPosition(0) != item );
392 menu0->Insert(0, item);
393 CPPUNIT_ASSERT( menu0->FindItemByPosition(0) == item );
394 menu0->Delete(item);
395 }