]> git.saurik.com Git - wxWidgets.git/blob - samples/menu/menu.cpp
Fix testing for existence of paths with trailing separators in wxMSW.
[wxWidgets.git] / samples / menu / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/menu.cpp
3 // Purpose: wxMenu/wxMenuBar sample
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 01.11.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/app.h"
29 #include "wx/frame.h"
30 #include "wx/menu.h"
31 #include "wx/msgdlg.h"
32 #include "wx/log.h"
33 #include "wx/textctrl.h"
34 #include "wx/textdlg.h"
35 #endif
36
37 #if !wxUSE_MENUS
38 // nice try...
39 #error "menu sample requires wxUSE_MENUS=1"
40 #endif // wxUSE_MENUS
41
42 // not all ports have support for EVT_CONTEXT_MENU yet, don't define
43 // USE_CONTEXT_MENU for those which don't
44 #if defined(__WXMOTIF__) || defined(__WXPM__) || defined(__WXX11__)
45 #define USE_CONTEXT_MENU 0
46 #else
47 #define USE_CONTEXT_MENU 1
48 #endif
49
50 // this sample is useful when a new port is developed
51 // and usually a new port has majority of flags turned off
52 #if wxUSE_LOG && wxUSE_TEXTCTRL
53 #define USE_LOG_WINDOW 1
54 #else
55 #define USE_LOG_WINDOW 0
56 #endif
57
58 #include "copy.xpm"
59
60 #ifndef wxHAS_IMAGES_IN_RESOURCES
61 #include "../sample.xpm"
62 #endif
63
64 // ----------------------------------------------------------------------------
65 // classes
66 // ----------------------------------------------------------------------------
67
68 // Define a new application
69 class MyApp: public wxApp
70 {
71 public:
72 bool OnInit();
73 };
74
75 // Define a new frame
76 class MyFrame: public wxFrame
77 {
78 public:
79 MyFrame();
80
81 virtual ~MyFrame();
82
83 void LogMenuEvent(const wxCommandEvent& event);
84
85 protected:
86 void OnQuit(wxCommandEvent& event);
87 #if USE_LOG_WINDOW
88 void OnClearLog(wxCommandEvent& event);
89 void OnClearLogUpdateUI(wxUpdateUIEvent& event);
90 #endif // USE_LOG_WINDOW
91
92 void OnAbout(wxCommandEvent& event);
93
94 void OnDummy(wxCommandEvent& event);
95
96 void OnAppendMenuItem(wxCommandEvent& event);
97 void OnAppendSubMenu(wxCommandEvent& event);
98 void OnDeleteMenuItem(wxCommandEvent& event);
99 void OnDeleteSubMenu(wxCommandEvent& event);
100 void OnInsertMenuItem(wxCommandEvent& event);
101 void OnCheckMenuItem(wxCommandEvent& event);
102 void OnEnableMenuItem(wxCommandEvent& event);
103 void OnGetLabelMenuItem(wxCommandEvent& event);
104 #if wxUSE_TEXTDLG
105 void OnSetLabelMenuItem(wxCommandEvent& event);
106 #endif
107 void OnGetMenuItemInfo(wxCommandEvent& event);
108 #if wxUSE_TEXTDLG
109 void OnFindMenuItem(wxCommandEvent& event);
110 #endif
111
112 void OnAppendMenu(wxCommandEvent& event);
113 void OnInsertMenu(wxCommandEvent& event);
114 void OnDeleteMenu(wxCommandEvent& event);
115 void OnToggleMenu(wxCommandEvent& event);
116 void OnEnableMenu(wxCommandEvent& event);
117 void OnGetLabelMenu(wxCommandEvent& event);
118 void OnSetLabelMenu(wxCommandEvent& event);
119 #if wxUSE_TEXTDLG
120 void OnFindMenu(wxCommandEvent& event);
121 #endif
122
123 void OnTestNormal(wxCommandEvent& event);
124 void OnTestCheck(wxCommandEvent& event);
125 void OnTestRadio(wxCommandEvent& event);
126
127 void OnUpdateSubMenuNormal(wxUpdateUIEvent& event);
128 void OnUpdateSubMenuCheck(wxUpdateUIEvent& event);
129 void OnUpdateSubMenuRadio(wxUpdateUIEvent& event);
130
131 #if USE_CONTEXT_MENU
132 void OnContextMenu(wxContextMenuEvent& event);
133 #else
134 void OnRightUp(wxMouseEvent& event)
135 { ShowContextMenu(event.GetPosition()); }
136 #endif
137
138 void OnMenuOpen(wxMenuEvent& event)
139 {
140 #if USE_LOG_WINDOW
141 LogMenuOpenOrClose(event, wxT("opened")); event.Skip();
142 #endif
143 }
144 void OnMenuClose(wxMenuEvent& event)
145 {
146 #if USE_LOG_WINDOW
147 LogMenuOpenOrClose(event, wxT("closed")); event.Skip();
148 #endif
149 }
150
151 void OnUpdateCheckMenuItemUI(wxUpdateUIEvent& event);
152
153 void OnSize(wxSizeEvent& event);
154
155 private:
156 void LogMenuOpenOrClose(const wxMenuEvent& event, const wxChar *what);
157 void ShowContextMenu(const wxPoint& pos);
158
159 wxMenu *CreateDummyMenu(wxString *title);
160
161 wxMenuItem *GetLastMenuItem() const;
162
163 // the menu previously detached from the menubar (may be NULL)
164 wxMenu *m_menu;
165
166 // the count of dummy menus already created
167 size_t m_countDummy;
168
169 #if USE_LOG_WINDOW
170 // the control used for logging
171 wxTextCtrl *m_textctrl;
172 #endif
173
174 // the previous log target
175 wxLog *m_logOld;
176
177 DECLARE_EVENT_TABLE()
178 };
179
180 // A small helper class which intercepts all menu events and logs them
181 class MyEvtHandler : public wxEvtHandler
182 {
183 public:
184 MyEvtHandler(MyFrame *frame) { m_frame = frame; }
185
186 void OnMenuEvent(wxCommandEvent& event)
187 {
188 m_frame->LogMenuEvent(event);
189
190 event.Skip();
191 }
192
193 private:
194 MyFrame *m_frame;
195
196 DECLARE_EVENT_TABLE()
197 };
198
199 // ----------------------------------------------------------------------------
200 // constants
201 // ----------------------------------------------------------------------------
202
203 enum
204 {
205 Menu_File_Quit = wxID_EXIT,
206 #if USE_LOG_WINDOW
207 Menu_File_ClearLog = 100,
208 #endif
209
210 Menu_MenuBar_Toggle = 200,
211 Menu_MenuBar_Append,
212 Menu_MenuBar_Insert,
213 Menu_MenuBar_Delete,
214 Menu_MenuBar_Enable,
215 Menu_MenuBar_GetLabel,
216 #if wxUSE_TEXTDLG
217 Menu_MenuBar_SetLabel,
218 Menu_MenuBar_FindMenu,
219 #endif
220
221 Menu_Menu_Append = 300,
222 Menu_Menu_AppendSub,
223 Menu_Menu_Insert,
224 Menu_Menu_Delete,
225 Menu_Menu_DeleteSub,
226 Menu_Menu_Enable,
227 Menu_Menu_Check,
228 Menu_Menu_GetLabel,
229 #if wxUSE_TEXTDLG
230 Menu_Menu_SetLabel,
231 #endif
232 Menu_Menu_GetInfo,
233 #if wxUSE_TEXTDLG
234 Menu_Menu_FindItem,
235 #endif
236
237 Menu_Test_Normal = 400,
238 Menu_Test_Check,
239 Menu_Test_Radio1,
240 Menu_Test_Radio2,
241 Menu_Test_Radio3,
242
243 Menu_SubMenu = 450,
244 Menu_SubMenu_Normal,
245 Menu_SubMenu_Check,
246 Menu_SubMenu_Radio1,
247 Menu_SubMenu_Radio2,
248 Menu_SubMenu_Radio3,
249
250 Menu_Dummy_First = 500,
251 Menu_Dummy_Second,
252 Menu_Dummy_Third,
253 Menu_Dummy_Fourth,
254 Menu_Dummy_Last,
255
256 Menu_Help_About = wxID_ABOUT,
257
258 Menu_Popup_ToBeDeleted = 2000,
259 Menu_Popup_ToBeGreyed,
260 Menu_Popup_ToBeChecked,
261 Menu_Popup_Submenu,
262
263 Menu_PopupChoice,
264
265 Menu_Max
266 };
267
268 // ----------------------------------------------------------------------------
269 // event tables
270 // ----------------------------------------------------------------------------
271
272 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
273 EVT_MENU(Menu_File_Quit, MyFrame::OnQuit)
274 #if USE_LOG_WINDOW
275 EVT_MENU(Menu_File_ClearLog, MyFrame::OnClearLog)
276 EVT_UPDATE_UI(Menu_File_ClearLog, MyFrame::OnClearLogUpdateUI)
277 #endif
278
279 EVT_MENU(Menu_Help_About, MyFrame::OnAbout)
280
281 EVT_MENU(Menu_MenuBar_Toggle, MyFrame::OnToggleMenu)
282 EVT_MENU(Menu_MenuBar_Append, MyFrame::OnAppendMenu)
283 EVT_MENU(Menu_MenuBar_Insert, MyFrame::OnInsertMenu)
284 EVT_MENU(Menu_MenuBar_Delete, MyFrame::OnDeleteMenu)
285 EVT_MENU(Menu_MenuBar_Enable, MyFrame::OnEnableMenu)
286 EVT_MENU(Menu_MenuBar_GetLabel, MyFrame::OnGetLabelMenu)
287 #if wxUSE_TEXTDLG
288 EVT_MENU(Menu_MenuBar_SetLabel, MyFrame::OnSetLabelMenu)
289 EVT_MENU(Menu_MenuBar_FindMenu, MyFrame::OnFindMenu)
290 #endif
291
292 EVT_MENU(Menu_Menu_Append, MyFrame::OnAppendMenuItem)
293 EVT_MENU(Menu_Menu_AppendSub, MyFrame::OnAppendSubMenu)
294 EVT_MENU(Menu_Menu_Insert, MyFrame::OnInsertMenuItem)
295 EVT_MENU(Menu_Menu_Delete, MyFrame::OnDeleteMenuItem)
296 EVT_MENU(Menu_Menu_DeleteSub, MyFrame::OnDeleteSubMenu)
297 EVT_MENU(Menu_Menu_Enable, MyFrame::OnEnableMenuItem)
298 EVT_MENU(Menu_Menu_Check, MyFrame::OnCheckMenuItem)
299 EVT_MENU(Menu_Menu_GetLabel, MyFrame::OnGetLabelMenuItem)
300 #if wxUSE_TEXTDLG
301 EVT_MENU(Menu_Menu_SetLabel, MyFrame::OnSetLabelMenuItem)
302 #endif
303 EVT_MENU(Menu_Menu_GetInfo, MyFrame::OnGetMenuItemInfo)
304 #if wxUSE_TEXTDLG
305 EVT_MENU(Menu_Menu_FindItem, MyFrame::OnFindMenuItem)
306 #endif
307
308 EVT_MENU(Menu_Test_Normal, MyFrame::OnTestNormal)
309 EVT_MENU(Menu_Test_Check, MyFrame::OnTestCheck)
310 EVT_MENU(Menu_Test_Radio1, MyFrame::OnTestRadio)
311 EVT_MENU(Menu_Test_Radio2, MyFrame::OnTestRadio)
312 EVT_MENU(Menu_Test_Radio3, MyFrame::OnTestRadio)
313
314 EVT_UPDATE_UI(Menu_SubMenu_Normal, MyFrame::OnUpdateSubMenuNormal)
315 EVT_UPDATE_UI(Menu_SubMenu_Check, MyFrame::OnUpdateSubMenuCheck)
316 EVT_UPDATE_UI(Menu_SubMenu_Radio1, MyFrame::OnUpdateSubMenuRadio)
317 EVT_UPDATE_UI(Menu_SubMenu_Radio2, MyFrame::OnUpdateSubMenuRadio)
318 EVT_UPDATE_UI(Menu_SubMenu_Radio3, MyFrame::OnUpdateSubMenuRadio)
319
320 EVT_MENU_RANGE(Menu_Dummy_First, Menu_Dummy_Last, MyFrame::OnDummy)
321
322 EVT_UPDATE_UI(Menu_Menu_Check, MyFrame::OnUpdateCheckMenuItemUI)
323
324 #if USE_CONTEXT_MENU
325 EVT_CONTEXT_MENU(MyFrame::OnContextMenu)
326 #else
327 EVT_RIGHT_UP(MyFrame::OnRightUp)
328 #endif
329
330 EVT_MENU_OPEN(MyFrame::OnMenuOpen)
331 EVT_MENU_CLOSE(MyFrame::OnMenuClose)
332
333 EVT_SIZE(MyFrame::OnSize)
334 END_EVENT_TABLE()
335
336 BEGIN_EVENT_TABLE(MyEvtHandler, wxEvtHandler)
337 EVT_MENU(wxID_ANY, MyEvtHandler::OnMenuEvent)
338 END_EVENT_TABLE()
339
340 // ============================================================================
341 // implementation
342 // ============================================================================
343
344 // ----------------------------------------------------------------------------
345 // MyApp
346 // ----------------------------------------------------------------------------
347
348 IMPLEMENT_APP(MyApp)
349
350 // The `main program' equivalent, creating the windows and returning the
351 // main frame
352 bool MyApp::OnInit()
353 {
354 if ( !wxApp::OnInit() )
355 return false;
356
357 // Create the main frame window
358 MyFrame* frame = new MyFrame;
359
360 frame->Show(true);
361
362 #if wxUSE_STATUSBAR
363 frame->SetStatusText(wxT("Welcome to wxWidgets menu sample"));
364 #endif // wxUSE_STATUSBAR
365
366 return true;
367 }
368
369 // ----------------------------------------------------------------------------
370 // MyFrame
371 // ----------------------------------------------------------------------------
372
373 // Define my frame constructor
374 MyFrame::MyFrame()
375 : wxFrame((wxFrame *)NULL, wxID_ANY, wxT("wxWidgets menu sample"))
376 {
377 SetIcon(wxICON(sample));
378
379 #if USE_LOG_WINDOW
380 m_textctrl = NULL;
381 #endif
382 m_menu = NULL;
383 m_countDummy = 0;
384 m_logOld = NULL;
385
386 #if wxUSE_STATUSBAR
387 CreateStatusBar();
388 #endif // wxUSE_STATUSBAR
389
390 // create the menubar
391 wxMenu *fileMenu = new wxMenu;
392
393 wxMenu *stockSubMenu = new wxMenu;
394 stockSubMenu->Append(wxID_ADD);
395 stockSubMenu->Append(wxID_APPLY);
396 stockSubMenu->Append(wxID_BACKWARD);
397 stockSubMenu->Append(wxID_BOLD);
398 stockSubMenu->Append(wxID_BOTTOM);
399 stockSubMenu->Append(wxID_CANCEL);
400 stockSubMenu->Append(wxID_CDROM);
401 stockSubMenu->Append(wxID_CLEAR);
402 stockSubMenu->Append(wxID_CLOSE);
403 stockSubMenu->Append(wxID_CONVERT);
404 stockSubMenu->Append(wxID_COPY);
405 stockSubMenu->Append(wxID_CUT);
406 stockSubMenu->Append(wxID_DELETE);
407 stockSubMenu->Append(wxID_DOWN);
408 stockSubMenu->Append(wxID_EXECUTE);
409 stockSubMenu->Append(wxID_EXIT);
410 stockSubMenu->Append(wxID_FIND);
411 stockSubMenu->Append(wxID_FIRST);
412 stockSubMenu->Append(wxID_FLOPPY);
413 stockSubMenu->Append(wxID_FORWARD);
414 stockSubMenu->Append(wxID_HARDDISK);
415 stockSubMenu->Append(wxID_HELP);
416 stockSubMenu->Append(wxID_HOME);
417 stockSubMenu->Append(wxID_INDENT);
418 stockSubMenu->Append(wxID_INDEX);
419 stockSubMenu->Append(wxID_INFO);
420 stockSubMenu->Append(wxID_ITALIC);
421 stockSubMenu->Append(wxID_JUMP_TO);
422 stockSubMenu->Append(wxID_JUSTIFY_CENTER);
423 stockSubMenu->Append(wxID_JUSTIFY_FILL);
424 stockSubMenu->Append(wxID_JUSTIFY_LEFT);
425 stockSubMenu->Append(wxID_JUSTIFY_RIGHT);
426 stockSubMenu->Append(wxID_LAST);
427 stockSubMenu->Append(wxID_NETWORK);
428 stockSubMenu->Append(wxID_NEW);
429 stockSubMenu->Append(wxID_NO);
430 stockSubMenu->Append(wxID_OK);
431 stockSubMenu->Append(wxID_OPEN);
432 stockSubMenu->Append(wxID_PASTE);
433 stockSubMenu->Append(wxID_PREFERENCES);
434 stockSubMenu->Append(wxID_PREVIEW);
435 stockSubMenu->Append(wxID_PRINT);
436 stockSubMenu->Append(wxID_PROPERTIES);
437 stockSubMenu->Append(wxID_REDO);
438 stockSubMenu->Append(wxID_REFRESH);
439 stockSubMenu->Append(wxID_REMOVE);
440 stockSubMenu->Append(wxID_REPLACE);
441 stockSubMenu->Append(wxID_REVERT_TO_SAVED);
442 stockSubMenu->Append(wxID_SAVE);
443 stockSubMenu->Append(wxID_SAVEAS);
444 stockSubMenu->Append(wxID_SELECT_COLOR);
445 stockSubMenu->Append(wxID_SELECT_FONT);
446 stockSubMenu->Append(wxID_SORT_ASCENDING);
447 stockSubMenu->Append(wxID_SORT_DESCENDING);
448 stockSubMenu->Append(wxID_SPELL_CHECK);
449 stockSubMenu->Append(wxID_STOP);
450 stockSubMenu->Append(wxID_STRIKETHROUGH);
451 stockSubMenu->Append(wxID_TOP);
452 stockSubMenu->Append(wxID_UNDELETE);
453 stockSubMenu->Append(wxID_UNDERLINE);
454 stockSubMenu->Append(wxID_UNDO);
455 stockSubMenu->Append(wxID_UNINDENT);
456 stockSubMenu->Append(wxID_UP);
457 stockSubMenu->Append(wxID_YES);
458 stockSubMenu->Append(wxID_ZOOM_100);
459 stockSubMenu->Append(wxID_ZOOM_FIT);
460 stockSubMenu->Append(wxID_ZOOM_IN);
461 stockSubMenu->Append(wxID_ZOOM_OUT);
462 fileMenu->AppendSubMenu(stockSubMenu, wxT("&Standard items demo"));
463
464 #if USE_LOG_WINDOW
465 wxMenuItem *item = new wxMenuItem(fileMenu, Menu_File_ClearLog,
466 wxT("Clear &log\tCtrl-L"));
467 item->SetBitmap(copy_xpm);
468 fileMenu->Append(item);
469 fileMenu->AppendSeparator();
470 #endif // USE_LOG_WINDOW
471
472 fileMenu->Append(Menu_File_Quit, wxT("E&xit\tAlt-X"), wxT("Quit menu sample"));
473
474 wxMenu *menubarMenu = new wxMenu;
475 menubarMenu->Append(Menu_MenuBar_Append, wxT("&Append menu\tCtrl-A"),
476 wxT("Append a menu to the menubar"));
477 menubarMenu->Append(Menu_MenuBar_Insert, wxT("&Insert menu\tCtrl-I"),
478 wxT("Insert a menu into the menubar"));
479 menubarMenu->Append(Menu_MenuBar_Delete, wxT("&Delete menu\tCtrl-D"),
480 wxT("Delete the last menu from the menubar"));
481 menubarMenu->Append(Menu_MenuBar_Toggle, wxT("&Toggle menu\tCtrl-T"),
482 wxT("Toggle the first menu in the menubar"), true);
483 menubarMenu->AppendSeparator();
484 menubarMenu->Append(Menu_MenuBar_Enable, wxT("&Enable menu\tCtrl-E"),
485 wxT("Enable or disable the last menu"), true);
486 menubarMenu->AppendSeparator();
487 menubarMenu->Append(Menu_MenuBar_GetLabel, wxT("&Get menu label\tCtrl-G"),
488 wxT("Get the label of the last menu"));
489 #if wxUSE_TEXTDLG
490 menubarMenu->Append(Menu_MenuBar_SetLabel, wxT("&Set menu label\tCtrl-S"),
491 wxT("Change the label of the last menu"));
492 menubarMenu->AppendSeparator();
493 menubarMenu->Append(Menu_MenuBar_FindMenu, wxT("&Find menu from label\tCtrl-F"),
494 wxT("Find a menu by searching for its label"));
495 #endif
496
497 wxMenu* subMenu = new wxMenu;
498 subMenu->Append(Menu_SubMenu_Normal, wxT("&Normal submenu item"), wxT("Disabled submenu item"));
499 subMenu->AppendCheckItem(Menu_SubMenu_Check, wxT("&Check submenu item"), wxT("Check submenu item"));
500 subMenu->AppendRadioItem(Menu_SubMenu_Radio1, wxT("Radio item &1"), wxT("Radio item"));
501 subMenu->AppendRadioItem(Menu_SubMenu_Radio2, wxT("Radio item &2"), wxT("Radio item"));
502 subMenu->AppendRadioItem(Menu_SubMenu_Radio3, wxT("Radio item &3"), wxT("Radio item"));
503
504 menubarMenu->Append(Menu_SubMenu, wxT("Submenu"), subMenu);
505
506 wxMenu *menuMenu = new wxMenu;
507 menuMenu->Append(Menu_Menu_Append, wxT("&Append menu item\tAlt-A"),
508 wxT("Append a menu item to the 'Test' menu"));
509 menuMenu->Append(Menu_Menu_AppendSub, wxT("&Append sub menu\tAlt-S"),
510 wxT("Append a sub menu to the 'Test' menu"));
511 menuMenu->Append(Menu_Menu_Insert, wxT("&Insert menu item\tAlt-I"),
512 wxT("Insert a menu item in head of the 'Test' menu"));
513 menuMenu->Append(Menu_Menu_Delete, wxT("&Delete menu item\tAlt-D"),
514 wxT("Delete the last menu item from the 'Test' menu"));
515 menuMenu->Append(Menu_Menu_DeleteSub, wxT("Delete last &submenu\tAlt-K"),
516 wxT("Delete the last submenu from the 'Test' menu"));
517 menuMenu->AppendSeparator();
518 menuMenu->Append(Menu_Menu_Enable, wxT("&Enable menu item\tAlt-E"),
519 wxT("Enable or disable the last menu item"), true);
520 menuMenu->Append(Menu_Menu_Check, wxT("&Check menu item\tAlt-C"),
521 wxT("Check or uncheck the last menu item"), true);
522 menuMenu->AppendSeparator();
523 menuMenu->Append(Menu_Menu_GetInfo, wxT("Get menu item in&fo\tAlt-F"),
524 wxT("Show the state of the last menu item"));
525 #if wxUSE_TEXTDLG
526 menuMenu->Append(Menu_Menu_SetLabel, wxT("Set menu item label\tAlt-L"),
527 wxT("Set the label of a menu item"));
528 #endif
529 #if wxUSE_TEXTDLG
530 menuMenu->AppendSeparator();
531 menuMenu->Append(Menu_Menu_FindItem, wxT("Find menu item from label"),
532 wxT("Find a menu item by searching for its label"));
533 #endif
534
535 wxMenu *testMenu = new wxMenu;
536 testMenu->Append(Menu_Test_Normal, wxT("&Normal item"));
537 testMenu->AppendSeparator();
538 testMenu->AppendCheckItem(Menu_Test_Check, wxT("&Check item"));
539 testMenu->AppendSeparator();
540 testMenu->AppendRadioItem(Menu_Test_Radio1, wxT("Radio item &1"));
541 testMenu->AppendRadioItem(Menu_Test_Radio2, wxT("Radio item &2"));
542 testMenu->AppendRadioItem(Menu_Test_Radio3, wxT("Radio item &3"));
543
544 wxMenu *helpMenu = new wxMenu;
545 helpMenu->Append(Menu_Help_About, wxT("&About\tF1"), wxT("About menu sample"));
546
547 wxMenuBar* menuBar = new wxMenuBar( wxMB_DOCKABLE );
548
549 menuBar->Append(fileMenu, wxT("&File"));
550 menuBar->Append(menubarMenu, wxT("Menu&bar"));
551 menuBar->Append(menuMenu, wxT("&Menu"));
552 menuBar->Append(testMenu, wxT("&Test"));
553 menuBar->Append(helpMenu, wxT("&Help"));
554
555 // these items should be initially checked
556 menuBar->Check(Menu_MenuBar_Toggle, true);
557 menuBar->Check(Menu_MenuBar_Enable, true);
558 menuBar->Check(Menu_Menu_Enable, true);
559 menuBar->Check(Menu_Menu_Check, false);
560
561 // associate the menu bar with the frame
562 SetMenuBar(menuBar);
563
564 // intercept all menu events and log them in this custom event handler
565 PushEventHandler(new MyEvtHandler(this));
566
567 #if USE_LOG_WINDOW
568 // create the log text window
569 m_textctrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
570 wxDefaultPosition, wxDefaultSize,
571 wxTE_MULTILINE);
572 m_textctrl->SetEditable(false);
573
574 wxLog::DisableTimestamp();
575 m_logOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_textctrl));
576
577 wxLogMessage(wxT("Brief explanations: the commands in the \"Menu\" menu ")
578 wxT("append/insert/delete items to/from the \"Test\" menu.\n")
579 wxT("The commands in the \"Menubar\" menu work with the ")
580 wxT("menubar itself.\n\n")
581 wxT("Right click the band below to test popup menus.\n"));
582 #endif
583 #ifdef __POCKETPC__
584 EnableContextMenu();
585 #endif
586 }
587
588 MyFrame::~MyFrame()
589 {
590 delete m_menu;
591
592 // delete the event handler installed in ctor
593 PopEventHandler(true);
594
595 #if USE_LOG_WINDOW
596 // restore old logger
597 delete wxLog::SetActiveTarget(m_logOld);
598 #endif
599 }
600
601 wxMenu *MyFrame::CreateDummyMenu(wxString *title)
602 {
603 wxMenu *menu = new wxMenu;
604 menu->Append(Menu_Dummy_First, wxT("&First item\tCtrl-F1"));
605 menu->AppendSeparator();
606 menu->AppendCheckItem(Menu_Dummy_Second, wxT("&Second item\tCtrl-F2"));
607
608 if ( title )
609 {
610 title->Printf(wxT("Dummy menu &%u"), (unsigned)++m_countDummy);
611 }
612
613 return menu;
614 }
615
616 wxMenuItem *MyFrame::GetLastMenuItem() const
617 {
618 wxMenuBar *menubar = GetMenuBar();
619 wxMenu *menu = menubar->GetMenu(menubar->FindMenu("Test"));
620 wxCHECK_MSG( menu, NULL, wxT("no 'Test' menu?") );
621
622 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetLast();
623 if ( !node )
624 {
625 wxLogWarning(wxT("No last item in the 'Test' menu!"));
626
627 return NULL;
628 }
629 else
630 {
631 return node->GetData();
632 }
633 }
634
635 void MyFrame::LogMenuEvent(const wxCommandEvent& event)
636 {
637 int id = event.GetId();
638
639 wxString msg = wxString::Format(wxT("Menu command %d"), id);
640
641 // catch all checkable menubar items and also the check item from the popup
642 // menu
643 wxMenuItem *item = GetMenuBar()->FindItem(id);
644 if ( (item && item->IsCheckable()) || id == Menu_Popup_ToBeChecked )
645 {
646 msg += wxString::Format(wxT(" (the item is currently %schecked)"),
647 event.IsChecked() ? wxT("") : wxT("not "));
648 }
649
650 wxLogMessage(msg);
651 }
652
653 // ----------------------------------------------------------------------------
654 // menu callbacks
655 // ----------------------------------------------------------------------------
656
657 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
658 {
659 Close(true);
660 }
661
662 #if USE_LOG_WINDOW
663
664 void MyFrame::OnClearLog(wxCommandEvent& WXUNUSED(event))
665 {
666 m_textctrl->Clear();
667 }
668
669 void MyFrame::OnClearLogUpdateUI(wxUpdateUIEvent& event)
670 {
671 // if we only enable this item when the log window is empty, we never see
672 // it in the disable state as a message is logged whenever the menu is
673 // opened, so we disable it if there is not "much" text in the window
674 event.Enable( m_textctrl->GetNumberOfLines() > 5 );
675 }
676
677 #endif // USE_LOG_WINDOW
678
679 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
680 {
681 (void)wxMessageBox(wxT("wxWidgets menu sample\n(c) 1999-2001 Vadim Zeitlin"),
682 wxT("About wxWidgets menu sample"),
683 wxOK | wxICON_INFORMATION);
684 }
685
686 void MyFrame::OnDeleteMenu(wxCommandEvent& WXUNUSED(event))
687 {
688 wxMenuBar *mbar = GetMenuBar();
689
690 size_t count = mbar->GetMenuCount();
691 if ( count == 4 )
692 {
693 // don't let delete the first 4 menus
694 wxLogError(wxT("Can't delete any more menus"));
695 }
696 else
697 {
698 delete mbar->Remove(count - 1);
699 }
700 }
701
702 void MyFrame::OnInsertMenu(wxCommandEvent& WXUNUSED(event))
703 {
704 wxString title;
705 wxMenu *menu = CreateDummyMenu(&title);
706 // Insert before the 'Help' menu
707 // Otherwise repeated Deletes will remove the 'Test' menu
708 GetMenuBar()->Insert(4, menu, title);
709 }
710
711 void MyFrame::OnAppendMenu(wxCommandEvent& WXUNUSED(event))
712 {
713 wxString title;
714 wxMenu *menu = CreateDummyMenu(&title);
715 GetMenuBar()->Append(menu, title);
716 }
717
718 void MyFrame::OnToggleMenu(wxCommandEvent& WXUNUSED(event))
719 {
720 wxMenuBar *mbar = GetMenuBar();
721 if ( !m_menu )
722 {
723 // hide the menu
724 m_menu = mbar->Remove(0);
725 }
726 else
727 {
728 // restore it
729 mbar->Insert(0, m_menu, wxT("&File"));
730 m_menu = NULL;
731 }
732 }
733
734 void MyFrame::OnEnableMenu(wxCommandEvent& event)
735 {
736 wxMenuBar *mbar = GetMenuBar();
737 size_t count = mbar->GetMenuCount();
738
739 mbar->EnableTop(count - 1, event.IsChecked());
740 }
741
742 void MyFrame::OnGetLabelMenu(wxCommandEvent& WXUNUSED(event))
743 {
744 wxMenuBar *mbar = GetMenuBar();
745 size_t count = mbar->GetMenuCount();
746
747 wxCHECK_RET( count, wxT("no last menu?") );
748
749 wxLogMessage(wxT("The label of the last menu item is '%s'"),
750 mbar->GetMenuLabel(count - 1).c_str());
751 }
752
753 #if wxUSE_TEXTDLG
754 void MyFrame::OnSetLabelMenu(wxCommandEvent& WXUNUSED(event))
755 {
756 wxMenuBar *mbar = GetMenuBar();
757 size_t count = mbar->GetMenuCount();
758
759 wxCHECK_RET( count, wxT("no last menu?") );
760
761 wxString label = wxGetTextFromUser
762 (
763 wxT("Enter new label: "),
764 wxT("Change last menu text"),
765 mbar->GetMenuLabel(count - 1),
766 this
767 );
768
769 if ( !label.empty() )
770 {
771 mbar->SetMenuLabel(count - 1, label);
772 }
773 }
774
775 void MyFrame::OnFindMenu(wxCommandEvent& WXUNUSED(event))
776 {
777 wxMenuBar *mbar = GetMenuBar();
778 size_t count = mbar->GetMenuCount();
779
780 wxCHECK_RET( count, wxT("no last menu?") );
781
782 wxString label = wxGetTextFromUser
783 (
784 wxT("Enter label to search for: "),
785 wxT("Find menu"),
786 wxEmptyString,
787 this
788 );
789
790 if ( !label.empty() )
791 {
792 int index = mbar->FindMenu(label);
793
794 if (index == wxNOT_FOUND)
795 {
796 wxLogWarning(wxT("No menu with label '%s'"), label.c_str());
797 }
798 else
799 {
800 wxLogMessage(wxT("Menu %d has label '%s'"), index, label.c_str());
801 }
802 }
803 }
804 #endif
805
806 void MyFrame::OnDummy(wxCommandEvent& event)
807 {
808 wxLogMessage(wxT("Dummy item #%d"), event.GetId() - Menu_Dummy_First + 1);
809 }
810
811 void MyFrame::OnAppendMenuItem(wxCommandEvent& WXUNUSED(event))
812 {
813 wxMenuBar *menubar = GetMenuBar();
814 wxMenu *menu = menubar->GetMenu(menubar->FindMenu("Test"));
815 wxCHECK_RET( menu, wxT("no 'Test' menu?") );
816
817 menu->AppendSeparator();
818 menu->Append(Menu_Dummy_Third, wxT("&Third dummy item\tCtrl-F3"),
819 wxT("Checkable item"), true);
820 }
821
822 void MyFrame::OnAppendSubMenu(wxCommandEvent& WXUNUSED(event))
823 {
824 wxMenuBar *menubar = GetMenuBar();
825 wxMenu *menu = menubar->GetMenu(menubar->FindMenu("Test"));
826 wxCHECK_RET( menu, wxT("no 'Test' menu?") );
827
828 menu->Append(Menu_Dummy_Last, wxT("&Dummy sub menu"),
829 CreateDummyMenu(NULL), wxT("Dummy sub menu help"));
830 }
831
832 void MyFrame::OnDeleteMenuItem(wxCommandEvent& WXUNUSED(event))
833 {
834 wxMenuBar *menubar = GetMenuBar();
835 wxMenu *menu = menubar->GetMenu(menubar->FindMenu("Test"));
836 wxCHECK_RET( menu, wxT("no 'Test' menu?") );
837
838 size_t count = menu->GetMenuItemCount();
839 if ( !count )
840 {
841 wxLogWarning(wxT("No items to delete!"));
842 }
843 else
844 {
845 menu->Destroy(menu->GetMenuItems().Item(count - 1)->GetData());
846 }
847 }
848
849 void MyFrame::OnDeleteSubMenu(wxCommandEvent& WXUNUSED(event))
850 {
851 wxMenuBar *menubar = GetMenuBar();
852 wxMenu *menu = menubar->GetMenu(menubar->FindMenu("Test"));
853 wxCHECK_RET( menu, wxT("no 'Test' menu?") );
854
855 for ( int n = menu->GetMenuItemCount() - 1; n >=0 ; --n )
856 {
857 wxMenuItem* item = menu->FindItemByPosition(n);
858 if (item->IsSubMenu())
859 {
860 menu->Destroy(item);
861 return;
862 }
863 }
864
865 wxLogWarning(wxT("No submenu to delete!"));
866 }
867
868 void MyFrame::OnInsertMenuItem(wxCommandEvent& WXUNUSED(event))
869 {
870 wxMenuBar *menubar = GetMenuBar();
871 wxMenu *menu = menubar->GetMenu(menubar->FindMenu("Test"));
872 wxCHECK_RET( menu, wxT("no 'Test' menu?") );
873
874 menu->Insert(0, wxMenuItem::New(menu, Menu_Dummy_Fourth,
875 wxT("Fourth dummy item\tCtrl-F4")));
876 menu->Insert(1, wxMenuItem::New(menu, wxID_SEPARATOR));
877 }
878
879 void MyFrame::OnEnableMenuItem(wxCommandEvent& WXUNUSED(event))
880 {
881 wxMenuItem *item = GetLastMenuItem();
882
883 if ( item )
884 {
885 item->Enable(!item->IsEnabled());
886 }
887 }
888
889 void MyFrame::OnCheckMenuItem(wxCommandEvent& WXUNUSED(event))
890 {
891 wxMenuItem *item = GetLastMenuItem();
892
893 if (item && item->IsCheckable())
894 {
895 item->Toggle();
896 }
897 }
898
899 void MyFrame::OnUpdateCheckMenuItemUI(wxUpdateUIEvent& event)
900 {
901 wxLogNull nolog;
902
903 wxMenuItem *item = GetLastMenuItem();
904
905 event.Enable(item && item->IsCheckable());
906 }
907
908 void MyFrame::OnGetLabelMenuItem(wxCommandEvent& WXUNUSED(event))
909 {
910 wxMenuItem *item = GetLastMenuItem();
911
912 if ( item )
913 {
914 wxString label = item->GetItemLabel();
915 wxLogMessage(wxT("The label of the last menu item is '%s'"),
916 label.c_str());
917 }
918 }
919
920 #if wxUSE_TEXTDLG
921 void MyFrame::OnSetLabelMenuItem(wxCommandEvent& WXUNUSED(event))
922 {
923 wxMenuItem *item = GetLastMenuItem();
924
925 if ( item )
926 {
927 wxString label = wxGetTextFromUser
928 (
929 wxT("Enter new label: "),
930 wxT("Change last menu item text"),
931 item->GetItemLabel(),
932 this
933 );
934 label.Replace( wxT("\\t"), wxT("\t") );
935
936 if ( !label.empty() )
937 {
938 item->SetItemLabel(label);
939 }
940 }
941 }
942 #endif
943
944 void MyFrame::OnGetMenuItemInfo(wxCommandEvent& WXUNUSED(event))
945 {
946 wxMenuItem *item = GetLastMenuItem();
947
948 if ( item )
949 {
950 wxString msg;
951 msg << wxT("The item is ") << (item->IsEnabled() ? wxT("enabled")
952 : wxT("disabled"))
953 << wxT('\n');
954
955 if ( item->IsCheckable() )
956 {
957 msg << wxT("It is checkable and ") << (item->IsChecked() ? wxT("") : wxT("un"))
958 << wxT("checked\n");
959 }
960
961 #if wxUSE_ACCEL
962 wxAcceleratorEntry *accel = item->GetAccel();
963 if ( accel )
964 {
965 msg << wxT("Its accelerator is ");
966
967 int flags = accel->GetFlags();
968 if ( flags & wxACCEL_ALT )
969 msg << wxT("Alt-");
970 if ( flags & wxACCEL_CTRL )
971 msg << wxT("Ctrl-");
972 if ( flags & wxACCEL_SHIFT )
973 msg << wxT("Shift-");
974
975 int code = accel->GetKeyCode();
976 switch ( code )
977 {
978 case WXK_F1:
979 case WXK_F2:
980 case WXK_F3:
981 case WXK_F4:
982 case WXK_F5:
983 case WXK_F6:
984 case WXK_F7:
985 case WXK_F8:
986 case WXK_F9:
987 case WXK_F10:
988 case WXK_F11:
989 case WXK_F12:
990 msg << wxT('F') << code - WXK_F1 + 1;
991 break;
992
993 // if there are any other keys wxGetAccelFromString() may return,
994 // we should process them here
995
996 default:
997 if ( wxIsalnum(code) )
998 {
999 msg << (wxChar)code;
1000
1001 break;
1002 }
1003
1004 wxFAIL_MSG( wxT("unknown keyboard accel") );
1005 }
1006
1007 delete accel;
1008 }
1009 else
1010 {
1011 msg << wxT("It doesn't have an accelerator");
1012 }
1013 #endif // wxUSE_ACCEL
1014
1015 wxLogMessage(msg);
1016 }
1017 }
1018
1019 #if wxUSE_TEXTDLG
1020 void MyFrame::OnFindMenuItem(wxCommandEvent& WXUNUSED(event))
1021 {
1022 wxMenuBar *mbar = GetMenuBar();
1023 size_t count = mbar->GetMenuCount();
1024
1025 wxCHECK_RET( count, wxT("no last menu?") );
1026
1027 wxString label = wxGetTextFromUser
1028 (
1029 wxT("Enter label to search for: "),
1030 wxT("Find menu item"),
1031 wxEmptyString,
1032 this
1033 );
1034
1035 if ( !label.empty() )
1036 {
1037 size_t menuindex;
1038 int index = wxNOT_FOUND;
1039
1040 for (menuindex = 0; (menuindex < count) && (index == wxNOT_FOUND); ++menuindex)
1041 {
1042 index = mbar->FindMenuItem(mbar->GetMenu(menuindex)->GetTitle(), label);
1043 }
1044 if (index == wxNOT_FOUND)
1045 {
1046 wxLogWarning(wxT("No menu item with label '%s'"), label.c_str());
1047 }
1048 else
1049 {
1050 wxLogMessage(wxT("Menu item %d in menu %lu has label '%s'"),
1051 index, (unsigned long)menuindex, label.c_str());
1052 }
1053 }
1054 }
1055 #endif
1056
1057 void MyFrame::ShowContextMenu(const wxPoint& pos)
1058 {
1059 wxMenu menu;
1060
1061 if ( wxGetKeyState(WXK_SHIFT) )
1062 {
1063 // when Shift is pressed, demonstrate the use of a simple function
1064 // returning the id of the item selected in the popup menu
1065 menu.SetTitle("Choose one of:");
1066 static const char *choices[] = { "Apple", "Banana", "Cherry" };
1067 for ( size_t n = 0; n < WXSIZEOF(choices); n++ )
1068 menu.Append(Menu_PopupChoice + n, choices[n]);
1069
1070 const int rc = GetPopupMenuSelectionFromUser(menu, pos);
1071 if ( rc == wxID_NONE )
1072 {
1073 wxLogMessage("No selection");
1074 }
1075 else
1076 {
1077 wxLogMessage("You have selected \"%s\"",
1078 choices[rc - Menu_PopupChoice]);
1079 }
1080 }
1081 else // normal case, shift not pressed
1082 {
1083 menu.Append(Menu_Help_About, wxT("&About"));
1084 menu.Append(Menu_Popup_Submenu, wxT("&Submenu"), CreateDummyMenu(NULL));
1085 menu.Append(Menu_Popup_ToBeDeleted, wxT("To be &deleted"));
1086 menu.AppendCheckItem(Menu_Popup_ToBeChecked, wxT("To be &checked"));
1087 menu.Append(Menu_Popup_ToBeGreyed, wxT("To be &greyed"),
1088 wxT("This menu item should be initially greyed out"));
1089 menu.AppendSeparator();
1090 menu.Append(Menu_File_Quit, wxT("E&xit"));
1091
1092 menu.Delete(Menu_Popup_ToBeDeleted);
1093 menu.Check(Menu_Popup_ToBeChecked, true);
1094 menu.Enable(Menu_Popup_ToBeGreyed, false);
1095
1096 PopupMenu(&menu, pos);
1097
1098 // test for destroying items in popup menus
1099 #if 0 // doesn't work in wxGTK!
1100 menu.Destroy(Menu_Popup_Submenu);
1101
1102 PopupMenu( &menu, event.GetX(), event.GetY() );
1103 #endif // 0
1104 }
1105 }
1106
1107 void MyFrame::OnTestNormal(wxCommandEvent& WXUNUSED(event))
1108 {
1109 wxLogMessage(wxT("Normal item selected"));
1110 }
1111
1112 void MyFrame::OnTestCheck(wxCommandEvent& event)
1113 {
1114 wxLogMessage(wxT("Check item %schecked"),
1115 event.IsChecked() ? wxT("") : wxT("un"));
1116 }
1117
1118 void MyFrame::OnTestRadio(wxCommandEvent& event)
1119 {
1120 wxLogMessage(wxT("Radio item %d selected"),
1121 event.GetId() - Menu_Test_Radio1 + 1);
1122 }
1123
1124 #if USE_LOG_WINDOW
1125 void MyFrame::LogMenuOpenOrClose(const wxMenuEvent& event, const wxChar *what)
1126 {
1127 wxString msg;
1128 msg << wxT("A ")
1129 << ( event.IsPopup() ? wxT("popup ") : wxT("") )
1130 << wxT("menu has been ")
1131 << what
1132 << wxT(".");
1133
1134 wxLogStatus(this, msg.c_str());
1135 }
1136 #endif
1137
1138 void MyFrame::OnUpdateSubMenuNormal(wxUpdateUIEvent& event)
1139 {
1140 event.Enable(false);
1141 }
1142
1143 void MyFrame::OnUpdateSubMenuCheck(wxUpdateUIEvent& event)
1144 {
1145 event.Enable(true);
1146 }
1147
1148 void MyFrame::OnUpdateSubMenuRadio(wxUpdateUIEvent& event)
1149 {
1150 int which = (event.GetId() - Menu_SubMenu_Radio1 + 1);
1151 if (which == 2)
1152 event.Check(true);
1153 else
1154 event.Check(false);
1155 }
1156
1157 #if USE_CONTEXT_MENU
1158 void MyFrame::OnContextMenu(wxContextMenuEvent& event)
1159 {
1160 wxPoint point = event.GetPosition();
1161 // If from keyboard
1162 if (point.x == -1 && point.y == -1) {
1163 wxSize size = GetSize();
1164 point.x = size.x / 2;
1165 point.y = size.y / 2;
1166 } else {
1167 point = ScreenToClient(point);
1168 }
1169 ShowContextMenu(point);
1170 }
1171 #endif
1172
1173 void MyFrame::OnSize(wxSizeEvent& WXUNUSED(event))
1174 {
1175 #if USE_LOG_WINDOW
1176 if ( !m_textctrl )
1177 return;
1178
1179 // leave a band below for popup menu testing
1180 wxSize size = GetClientSize();
1181 m_textctrl->SetSize(0, 0, size.x, (3*size.y)/4);
1182 #endif
1183
1184 // this is really ugly but we have to do it as we can't just call
1185 // event.Skip() because wxFrameBase would make the text control fill the
1186 // entire frame then
1187 #ifdef __WXUNIVERSAL__
1188 PositionMenuBar();
1189 #endif // __WXUNIVERSAL__
1190 }
1191