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