]> git.saurik.com Git - wxWidgets.git/blame - samples/menu/menu.cpp
Fixed bug [ 743664 ] wxListCtrl asserts when deleting its m_textCtrl
[wxWidgets.git] / samples / menu / menu.cpp
CommitLineData
717a57c2
VZ
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".
92a19c2e 21#include "wx/wxprec.h"
717a57c2
VZ
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
f91bf72f
GD
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"
5c7766de 34 #include "wx/textdlg.h"
717a57c2
VZ
35#endif
36
6d5b2a57
VZ
37#if !wxUSE_MENUS
38 // nice try...
39 #error "menu sample requires wxUSE_MENUS=1"
40#endif // wxUSE_MENUS
41
fcaf9e70
RR
42#include "copy.xpm"
43
717a57c2
VZ
44// ----------------------------------------------------------------------------
45// classes
46// ----------------------------------------------------------------------------
47
48// Define a new application
49class MyApp: public wxApp
50{
51public:
52 bool OnInit();
53};
54
55// Define a new frame
56class MyFrame: public wxFrame
57{
58public:
59 MyFrame();
60
3ca6a5f0
BP
61 virtual ~MyFrame();
62
63 void LogMenuEvent(const wxCommandEvent& event);
717a57c2 64
e421922f 65protected:
717a57c2 66 void OnQuit(wxCommandEvent& event);
e421922f
VZ
67 void OnClearLog(wxCommandEvent& event);
68
717a57c2
VZ
69 void OnAbout(wxCommandEvent& event);
70
71 void OnDummy(wxCommandEvent& event);
72
73 void OnAppendMenuItem(wxCommandEvent& event);
74 void OnAppendSubMenu(wxCommandEvent& event);
75 void OnDeleteMenuItem(wxCommandEvent& event);
76 void OnInsertMenuItem(wxCommandEvent& event);
77 void OnCheckMenuItem(wxCommandEvent& event);
78 void OnEnableMenuItem(wxCommandEvent& event);
79 void OnGetLabelMenuItem(wxCommandEvent& event);
80 void OnSetLabelMenuItem(wxCommandEvent& event);
a80c322c 81 void OnGetMenuItemInfo(wxCommandEvent& event);
f6d90fb9 82 void OnFindMenuItem(wxCommandEvent& event);
717a57c2
VZ
83
84 void OnAppendMenu(wxCommandEvent& event);
f03ec224 85 void OnInsertMenu(wxCommandEvent& event);
717a57c2
VZ
86 void OnDeleteMenu(wxCommandEvent& event);
87 void OnToggleMenu(wxCommandEvent& event);
88 void OnEnableMenu(wxCommandEvent& event);
89 void OnGetLabelMenu(wxCommandEvent& event);
90 void OnSetLabelMenu(wxCommandEvent& event);
f6d90fb9 91 void OnFindMenu(wxCommandEvent& event);
717a57c2 92
d65c269b
VZ
93 void OnTestNormal(wxCommandEvent& event);
94 void OnTestCheck(wxCommandEvent& event);
95 void OnTestRadio(wxCommandEvent& event);
96
0c2d3577 97#if defined( __WXMSW__ ) || defined( __WXMAC__ )
ccef86c7
VZ
98 void OnContextMenu(wxContextMenuEvent& event)
99 { ShowContextMenu(ScreenToClient(event.GetPosition())); }
100#else
101 void OnRightUp(wxMouseEvent& event)
102 { ShowContextMenu(event.GetPosition()); }
103#endif
104
105 void OnMenuOpen(wxMenuEvent& event)
106 { LogMenuOpenOrClose(event, _T("opened")); }
107 void OnMenuClose(wxMenuEvent& event)
108 { LogMenuOpenOrClose(event, _T("closed")); }
717a57c2
VZ
109
110 void OnUpdateCheckMenuItemUI(wxUpdateUIEvent& event);
111
e421922f
VZ
112 void OnSize(wxSizeEvent& event);
113
717a57c2 114private:
ccef86c7
VZ
115 void LogMenuOpenOrClose(const wxMenuEvent& event, const wxChar *what);
116 void ShowContextMenu(const wxPoint& pos);
117
f03ec224 118 wxMenu *CreateDummyMenu(wxString *title);
717a57c2
VZ
119
120 wxMenuItem *GetLastMenuItem() const;
121
e421922f
VZ
122 // the menu previously detached from the menubar (may be NULL)
123 wxMenu *m_menu;
717a57c2 124
e421922f 125 // the count of dummy menus already created
f03ec224
VZ
126 size_t m_countDummy;
127
e421922f
VZ
128 // the control used for logging
129 wxTextCtrl *m_textctrl;
130
131 // the previous log target
132 wxLog *m_logOld;
133
717a57c2
VZ
134 DECLARE_EVENT_TABLE()
135};
136
3ca6a5f0
BP
137// A small helper class which intercepts all menu events and logs them
138class MyEvtHandler : public wxEvtHandler
139{
140public:
141 MyEvtHandler(MyFrame *frame) { m_frame = frame; }
142
143 void OnMenuEvent(wxCommandEvent& event)
144 {
145 m_frame->LogMenuEvent(event);
146
147 event.Skip();
148 }
149
150private:
151 MyFrame *m_frame;
152
153 DECLARE_EVENT_TABLE()
154};
155
717a57c2
VZ
156// ----------------------------------------------------------------------------
157// constants
158// ----------------------------------------------------------------------------
159
160enum
161{
162 Menu_File_Quit = 100,
e421922f 163 Menu_File_ClearLog,
717a57c2
VZ
164
165 Menu_MenuBar_Toggle = 200,
166 Menu_MenuBar_Append,
f03ec224 167 Menu_MenuBar_Insert,
717a57c2
VZ
168 Menu_MenuBar_Delete,
169 Menu_MenuBar_Enable,
170 Menu_MenuBar_GetLabel,
171 Menu_MenuBar_SetLabel,
f6d90fb9 172 Menu_MenuBar_FindMenu,
717a57c2
VZ
173
174 Menu_Menu_Append = 300,
175 Menu_Menu_AppendSub,
176 Menu_Menu_Insert,
177 Menu_Menu_Delete,
178 Menu_Menu_Enable,
179 Menu_Menu_Check,
180 Menu_Menu_GetLabel,
181 Menu_Menu_SetLabel,
a80c322c 182 Menu_Menu_GetInfo,
f6d90fb9 183 Menu_Menu_FindItem,
717a57c2 184
d65c269b
VZ
185 Menu_Test_Normal = 400,
186 Menu_Test_Check,
187 Menu_Test_Radio1,
188 Menu_Test_Radio2,
189 Menu_Test_Radio3,
190
191 Menu_Dummy_First = 500,
717a57c2
VZ
192 Menu_Dummy_Second,
193 Menu_Dummy_Third,
194 Menu_Dummy_Fourth,
195 Menu_Dummy_Last,
196
197 Menu_Help_About = 1000,
198
199 Menu_Popup_ToBeDeleted = 2000,
200 Menu_Popup_ToBeGreyed,
201 Menu_Popup_ToBeChecked,
202 Menu_Popup_Submenu,
203
204 Menu_Max
205};
206
207// ----------------------------------------------------------------------------
208// event tables
209// ----------------------------------------------------------------------------
210
211BEGIN_EVENT_TABLE(MyFrame, wxFrame)
e421922f
VZ
212 EVT_MENU(Menu_File_Quit, MyFrame::OnQuit)
213 EVT_MENU(Menu_File_ClearLog, MyFrame::OnClearLog)
717a57c2
VZ
214
215 EVT_MENU(Menu_Help_About, MyFrame::OnAbout)
216
217 EVT_MENU(Menu_MenuBar_Toggle, MyFrame::OnToggleMenu)
218 EVT_MENU(Menu_MenuBar_Append, MyFrame::OnAppendMenu)
f03ec224 219 EVT_MENU(Menu_MenuBar_Insert, MyFrame::OnInsertMenu)
717a57c2
VZ
220 EVT_MENU(Menu_MenuBar_Delete, MyFrame::OnDeleteMenu)
221 EVT_MENU(Menu_MenuBar_Enable, MyFrame::OnEnableMenu)
222 EVT_MENU(Menu_MenuBar_GetLabel, MyFrame::OnGetLabelMenu)
223 EVT_MENU(Menu_MenuBar_SetLabel, MyFrame::OnSetLabelMenu)
f6d90fb9 224 EVT_MENU(Menu_MenuBar_FindMenu, MyFrame::OnFindMenu)
717a57c2
VZ
225
226 EVT_MENU(Menu_Menu_Append, MyFrame::OnAppendMenuItem)
227 EVT_MENU(Menu_Menu_AppendSub, MyFrame::OnAppendSubMenu)
228 EVT_MENU(Menu_Menu_Insert, MyFrame::OnInsertMenuItem)
229 EVT_MENU(Menu_Menu_Delete, MyFrame::OnDeleteMenuItem)
230 EVT_MENU(Menu_Menu_Enable, MyFrame::OnEnableMenuItem)
a80c322c 231 EVT_MENU(Menu_Menu_Check, MyFrame::OnCheckMenuItem)
717a57c2
VZ
232 EVT_MENU(Menu_Menu_GetLabel, MyFrame::OnGetLabelMenuItem)
233 EVT_MENU(Menu_Menu_SetLabel, MyFrame::OnSetLabelMenuItem)
a80c322c 234 EVT_MENU(Menu_Menu_GetInfo, MyFrame::OnGetMenuItemInfo)
f6d90fb9 235 EVT_MENU(Menu_Menu_FindItem, MyFrame::OnFindMenuItem)
717a57c2 236
d65c269b
VZ
237 EVT_MENU(Menu_Test_Normal, MyFrame::OnTestNormal)
238 EVT_MENU(Menu_Test_Check, MyFrame::OnTestCheck)
239 EVT_MENU(Menu_Test_Radio1, MyFrame::OnTestRadio)
240 EVT_MENU(Menu_Test_Radio2, MyFrame::OnTestRadio)
241 EVT_MENU(Menu_Test_Radio3, MyFrame::OnTestRadio)
242
717a57c2
VZ
243 EVT_MENU_RANGE(Menu_Dummy_First, Menu_Dummy_Last, MyFrame::OnDummy)
244
245 EVT_UPDATE_UI(Menu_Menu_Check, MyFrame::OnUpdateCheckMenuItemUI)
246
0c2d3577 247#if defined( __WXMSW__ ) || defined( __WXMAC__ )
ccef86c7
VZ
248 EVT_CONTEXT_MENU(MyFrame::OnContextMenu)
249#else
e421922f 250 EVT_RIGHT_UP(MyFrame::OnRightUp)
ccef86c7
VZ
251#endif
252
253 EVT_MENU_OPEN(MyFrame::OnMenuOpen)
254 EVT_MENU_CLOSE(MyFrame::OnMenuClose)
e421922f
VZ
255
256 EVT_SIZE(MyFrame::OnSize)
717a57c2
VZ
257END_EVENT_TABLE()
258
3ca6a5f0
BP
259BEGIN_EVENT_TABLE(MyEvtHandler, wxEvtHandler)
260 EVT_MENU(-1, MyEvtHandler::OnMenuEvent)
261END_EVENT_TABLE()
262
717a57c2
VZ
263// ============================================================================
264// implementation
265// ============================================================================
266
267// ----------------------------------------------------------------------------
268// MyApp
269// ----------------------------------------------------------------------------
270
271IMPLEMENT_APP(MyApp)
272
273// The `main program' equivalent, creating the windows and returning the
274// main frame
275bool MyApp::OnInit()
276{
277 // Create the main frame window
278 MyFrame* frame = new MyFrame;
279
280 frame->Show(TRUE);
281
6d5b2a57 282#if wxUSE_STATUSBAR
42ed7532 283 frame->SetStatusText(_T("Welcome to wxWindows menu sample"));
6d5b2a57 284#endif // wxUSE_STATUSBAR
717a57c2
VZ
285
286 SetTopWindow(frame);
287
288 return TRUE;
289}
290
291// ----------------------------------------------------------------------------
292// MyFrame
293// ----------------------------------------------------------------------------
294
295// Define my frame constructor
296MyFrame::MyFrame()
42ed7532 297 : wxFrame((wxFrame *)NULL, -1, _T("wxWindows menu sample"),
5c7766de 298 wxDefaultPosition, wxSize(400, 250))
717a57c2 299{
268766dd 300 m_textctrl = NULL;
717a57c2 301 m_menu = NULL;
f03ec224 302 m_countDummy = 0;
e421922f 303 m_logOld = NULL;
717a57c2 304
6d5b2a57 305#if wxUSE_STATUSBAR
e421922f 306 CreateStatusBar();
6d5b2a57 307#endif // wxUSE_STATUSBAR
717a57c2
VZ
308
309 // create the menubar
310 wxMenu *fileMenu = new wxMenu;
6d5b2a57 311
e421922f 312 wxMenuItem *item = new wxMenuItem(fileMenu, Menu_File_ClearLog,
42ed7532 313 _T("Clear &log\tCtrl-L"));
e421922f
VZ
314 item->SetBitmap(copy_xpm);
315 fileMenu->Append(item);
316 fileMenu->AppendSeparator();
42ed7532 317 fileMenu->Append(Menu_File_Quit, _T("E&xit\tAlt-X"), _T("Quit menu sample"));
717a57c2
VZ
318
319 wxMenu *menubarMenu = new wxMenu;
42ed7532
MB
320 menubarMenu->Append(Menu_MenuBar_Append, _T("&Append menu\tCtrl-A"),
321 _T("Append a menu to the menubar"));
322 menubarMenu->Append(Menu_MenuBar_Insert, _T("&Insert menu\tCtrl-I"),
323 _T("Insert a menu into the menubar"));
324 menubarMenu->Append(Menu_MenuBar_Delete, _T("&Delete menu\tCtrl-D"),
325 _T("Delete the last menu from the menubar"));
326 menubarMenu->Append(Menu_MenuBar_Toggle, _T("&Toggle menu\tCtrl-T"),
327 _T("Toggle the first menu in the menubar"), TRUE);
717a57c2 328 menubarMenu->AppendSeparator();
42ed7532
MB
329 menubarMenu->Append(Menu_MenuBar_Enable, _T("&Enable menu\tCtrl-E"),
330 _T("Enable or disable the last menu"), TRUE);
717a57c2 331 menubarMenu->AppendSeparator();
42ed7532
MB
332 menubarMenu->Append(Menu_MenuBar_GetLabel, _T("&Get menu label\tCtrl-G"),
333 _T("Get the label of the last menu"));
334 menubarMenu->Append(Menu_MenuBar_SetLabel, _T("&Set menu label\tCtrl-S"),
335 _T("Change the label of the last menu"));
f6d90fb9 336 menubarMenu->AppendSeparator();
42ed7532
MB
337 menubarMenu->Append(Menu_MenuBar_FindMenu, _T("&Find menu from label\tCtrl-F"),
338 _T("Find a menu by searching for its label"));
717a57c2
VZ
339
340 wxMenu *menuMenu = new wxMenu;
42ed7532
MB
341 menuMenu->Append(Menu_Menu_Append, _T("&Append menu item\tAlt-A"),
342 _T("Append a menu item to the last menu"));
343 menuMenu->Append(Menu_Menu_AppendSub, _T("&Append sub menu\tAlt-S"),
344 _T("Append a sub menu to the last menu"));
345 menuMenu->Append(Menu_Menu_Insert, _T("&Insert menu item\tAlt-I"),
346 _T("Insert a menu item in head of the last menu"));
347 menuMenu->Append(Menu_Menu_Delete, _T("&Delete menu item\tAlt-D"),
348 _T("Delete the last menu item from the last menu"));
717a57c2 349 menuMenu->AppendSeparator();
42ed7532
MB
350 menuMenu->Append(Menu_Menu_Enable, _T("&Enable menu item\tAlt-E"),
351 _T("Enable or disable the last menu item"), TRUE);
352 menuMenu->Append(Menu_Menu_Check, _T("&Check menu item\tAlt-C"),
353 _T("Check or uncheck the last menu item"), TRUE);
717a57c2 354 menuMenu->AppendSeparator();
42ed7532
MB
355 menuMenu->Append(Menu_Menu_GetInfo, _T("Get menu item in&fo\tAlt-F"),
356 _T("Show the state of the last menu item"));
a80c322c 357 menuMenu->AppendSeparator();
42ed7532
MB
358 menuMenu->Append(Menu_Menu_FindItem, _T("Find menu item from label"),
359 _T("Find a menu item by searching for its label"));
717a57c2 360
d65c269b 361 wxMenu *testMenu = new wxMenu;
42ed7532 362 testMenu->Append(Menu_Test_Normal, _T("&Normal item"));
d65c269b 363 testMenu->AppendSeparator();
42ed7532 364 testMenu->AppendCheckItem(Menu_Test_Check, _T("&Check item"));
d65c269b 365 testMenu->AppendSeparator();
42ed7532
MB
366 testMenu->AppendRadioItem(Menu_Test_Radio1, _T("Radio item &1"));
367 testMenu->AppendRadioItem(Menu_Test_Radio2, _T("Radio item &2"));
368 testMenu->AppendRadioItem(Menu_Test_Radio3, _T("Radio item &3"));
d65c269b 369
717a57c2 370 wxMenu *helpMenu = new wxMenu;
42ed7532 371 helpMenu->Append(Menu_Help_About, _T("&About\tF1"), _T("About menu sample"));
717a57c2
VZ
372
373 wxMenuBar* menuBar = new wxMenuBar( wxMB_DOCKABLE );
374
42ed7532
MB
375 menuBar->Append(fileMenu, _T("&File"));
376 menuBar->Append(menubarMenu, _T("Menu&bar"));
377 menuBar->Append(menuMenu, _T("&Menu"));
378 menuBar->Append(testMenu, _T("&Test"));
379 menuBar->Append(helpMenu, _T("&Help"));
717a57c2
VZ
380
381 // these items should be initially checked
382 menuBar->Check(Menu_MenuBar_Toggle, TRUE);
383 menuBar->Check(Menu_MenuBar_Enable, TRUE);
384 menuBar->Check(Menu_Menu_Enable, TRUE);
385 menuBar->Check(Menu_Menu_Check, FALSE);
386
387 // associate the menu bar with the frame
388 SetMenuBar(menuBar);
3ca6a5f0
BP
389
390 // intercept all menu events and log them in this custom event handler
391 PushEventHandler(new MyEvtHandler(this));
e421922f
VZ
392
393 // create the log text window
394 m_textctrl = new wxTextCtrl(this, -1, _T(""),
395 wxDefaultPosition, wxDefaultSize,
396 wxTE_MULTILINE);
397 m_textctrl->SetEditable(FALSE);
5c7766de
VZ
398
399 wxLog::SetTimestamp(NULL);
e421922f
VZ
400 m_logOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_textctrl));
401
5c7766de 402 wxLogMessage(_T("Brief explanations: the commands or the \"Menu\" menu ")
e421922f 403 _T("append/insert/delete items to/from the last menu.\n")
5c7766de
VZ
404 _T("The commands from \"Menubar\" menu work with the ")
405 _T("menubar itself.\n\n")
e421922f 406 _T("Right click the band below to test popup menus.\n"));
3ca6a5f0
BP
407}
408
409MyFrame::~MyFrame()
410{
411 delete m_menu;
412
413 // delete the event handler installed in ctor
414 PopEventHandler(TRUE);
e421922f
VZ
415
416 // restore old logger
417 delete wxLog::SetActiveTarget(m_logOld);
717a57c2
VZ
418}
419
f03ec224 420wxMenu *MyFrame::CreateDummyMenu(wxString *title)
717a57c2
VZ
421{
422 wxMenu *menu = new wxMenu;
42ed7532 423 menu->Append(Menu_Dummy_First, _T("&First item\tCtrl-F1"));
717a57c2 424 menu->AppendSeparator();
42ed7532 425 menu->Append(Menu_Dummy_Second, _T("&Second item\tCtrl-F2"), _T(""), TRUE);
717a57c2 426
f03ec224
VZ
427 if ( title )
428 {
eb1ab6f9 429 title->Printf(wxT("Dummy menu &%u"), (unsigned)++m_countDummy);
f03ec224
VZ
430 }
431
717a57c2
VZ
432 return menu;
433}
434
435wxMenuItem *MyFrame::GetLastMenuItem() const
436{
437 wxMenuBar *menubar = GetMenuBar();
438 wxMenu *menu = menubar->GetMenu(menubar->GetMenuCount() - 1);
439
440 wxMenuItemList::Node *node = menu->GetMenuItems().GetLast();
441 if ( !node )
442 {
4693b20c 443 wxLogWarning(wxT("No last item in the last menu!"));
717a57c2
VZ
444
445 return NULL;
446 }
447 else
448 {
449 return node->GetData();
450 }
451}
452
3ca6a5f0
BP
453void MyFrame::LogMenuEvent(const wxCommandEvent& event)
454{
455 int id = event.GetId();
e421922f 456 if ( !GetMenuBar()->FindItem(id) )
d3d69314 457 return;
e421922f 458
4693b20c 459 wxString msg = wxString::Format(wxT("Menu command %d"), id);
3ca6a5f0
BP
460 if ( GetMenuBar()->FindItem(id)->IsCheckable() )
461 {
4693b20c 462 msg += wxString::Format(wxT(" (the item is currently %schecked)"),
3ca6a5f0
BP
463 event.IsChecked() ? "" : "not ");
464 }
465
e421922f 466 wxLogMessage(msg);
3ca6a5f0
BP
467}
468
469// ----------------------------------------------------------------------------
470// menu callbacks
471// ----------------------------------------------------------------------------
472
717a57c2
VZ
473void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
474{
475 Close(TRUE);
476}
477
e421922f
VZ
478void MyFrame::OnClearLog(wxCommandEvent& WXUNUSED(event))
479{
480 m_textctrl->Clear();
481}
482
717a57c2
VZ
483void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
484{
42ed7532
MB
485