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