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