]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/menu.cpp
Corrected small mistake (set static variable)
[wxWidgets.git] / src / gtk1 / menu.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: menu.cpp
3// Purpose:
4// Author: Robert Roebling
96fd301f 5// Id: $Id$
a81258be 6// Copyright: (c) 1998 Robert Roebling
96fd301f 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
c801d85f
KB
10#ifdef __GNUG__
11#pragma implementation "menu.h"
6ca41e57 12#pragma implementation "menuitem.h"
c801d85f
KB
13#endif
14
96fd301f 15#include "wx/log.h"
30dea054 16#include "wx/intl.h"
06cfab17 17#include "wx/app.h"
3dfac970 18#include "wx/menu.h"
c801d85f 19
974e8d94
VZ
20#if wxUSE_ACCEL
21 #include "wx/accel.h"
22#endif // wxUSE_ACCEL
23
83624f79
RR
24#include "gdk/gdk.h"
25#include "gtk/gtk.h"
26
acfd422a
RR
27//-----------------------------------------------------------------------------
28// idle system
29//-----------------------------------------------------------------------------
30
31extern void wxapp_install_idle_handler();
32extern bool g_isIdle;
33
c801d85f
KB
34//-----------------------------------------------------------------------------
35// wxMenuBar
36//-----------------------------------------------------------------------------
37
38IMPLEMENT_DYNAMIC_CLASS(wxMenuBar,wxWindow)
39
3502e687
RR
40wxMenuBar::wxMenuBar( long style )
41{
1e133b7d 42 /* the parent window is known after wxFrame::SetMenu() */
23280650 43 m_needParent = FALSE;
ae53c98c 44 m_style = style;
9c884972 45 m_invokingWindow = (wxWindow*) NULL;
23280650 46
4dcaf11a 47 if (!PreCreation( (wxWindow*) NULL, wxDefaultPosition, wxDefaultSize ) ||
223d09f6 48 !CreateBase( (wxWindow*) NULL, -1, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("menubar") ))
4dcaf11a 49 {
223d09f6 50 wxFAIL_MSG( wxT("wxMenuBar creation failed") );
455fadaa 51 return;
4dcaf11a 52 }
3502e687
RR
53
54 m_menus.DeleteContents( TRUE );
55
1e133b7d
RR
56 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
57#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
58 m_accel = gtk_accel_group_new();
59 m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
60 m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
23280650 61#else
3502e687 62 m_menubar = gtk_menu_bar_new();
1e133b7d 63#endif
3502e687
RR
64
65 if (style & wxMB_DOCKABLE)
66 {
67 m_widget = gtk_handle_box_new();
c626a8b7
VZ
68 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_menubar) );
69 gtk_widget_show( GTK_WIDGET(m_menubar) );
3502e687
RR
70 }
71 else
72 {
73 m_widget = GTK_WIDGET(m_menubar);
74 }
75
76 PostCreation();
3502e687
RR
77}
78
96fd301f 79wxMenuBar::wxMenuBar()
c801d85f 80{
1e133b7d
RR
81 /* the parent window is known after wxFrame::SetMenu() */
82 m_needParent = FALSE;
ae53c98c 83 m_style = 0;
9c884972 84 m_invokingWindow = (wxWindow*) NULL;
23280650 85
4dcaf11a 86 if (!PreCreation( (wxWindow*) NULL, wxDefaultPosition, wxDefaultSize ) ||
223d09f6 87 !CreateBase( (wxWindow*) NULL, -1, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, wxT("menubar") ))
4dcaf11a 88 {
223d09f6 89 wxFAIL_MSG( wxT("wxMenuBar creation failed") );
455fadaa 90 return;
4dcaf11a 91 }
974e8d94 92
83624f79 93 m_menus.DeleteContents( TRUE );
96fd301f 94
1e133b7d
RR
95 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
96#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
97 m_accel = gtk_accel_group_new();
98 m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
99 m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
23280650 100#else
83624f79 101 m_menubar = gtk_menu_bar_new();
1e133b7d 102#endif
8bbe427f 103
828f655f 104 m_widget = GTK_WIDGET(m_menubar);
96fd301f 105
83624f79 106 PostCreation();
6de97a3b 107}
c801d85f 108
1e133b7d
RR
109wxMenuBar::~wxMenuBar()
110{
d1b15f03 111// gtk_object_unref( GTK_OBJECT(m_factory) ); why not ?
1e133b7d
RR
112}
113
5bd9e519
RR
114static void wxMenubarUnsetInvokingWindow( wxMenu *menu, wxWindow *win )
115{
116 menu->SetInvokingWindow( (wxWindow*) NULL );
117
118#if (GTK_MINOR_VERSION > 0)
119 wxWindow *top_frame = win;
974e8d94 120 while (top_frame->GetParent() && !(top_frame->GetParent()->m_isFrame))
bd77da97 121 top_frame = top_frame->GetParent();
5bd9e519
RR
122
123 /* support for native hot keys */
124 gtk_accel_group_detach( menu->m_accel, GTK_OBJECT(top_frame->m_widget) );
125#endif
126
127 wxNode *node = menu->GetItems().First();
128 while (node)
129 {
130 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
131 if (menuitem->IsSubMenu())
132 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu(), win );
133 node = node->Next();
134 }
135}
136
137static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
138{
139 menu->SetInvokingWindow( win );
140
141#if (GTK_MINOR_VERSION > 0)
142 wxWindow *top_frame = win;
974e8d94 143 while (top_frame->GetParent() && !(top_frame->GetParent()->m_isFrame))
bd77da97 144 top_frame = top_frame->GetParent();
5bd9e519
RR
145
146 /* support for native hot keys */
147 gtk_accel_group_attach( menu->m_accel, GTK_OBJECT(top_frame->m_widget) );
148#endif
149
150 wxNode *node = menu->GetItems().First();
151 while (node)
152 {
153 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
154 if (menuitem->IsSubMenu())
155 wxMenubarSetInvokingWindow( menuitem->GetSubMenu(), win );
156 node = node->Next();
157 }
158}
159
160void wxMenuBar::SetInvokingWindow( wxWindow *win )
161{
9c884972 162 m_invokingWindow = win;
5bd9e519
RR
163#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
164 wxWindow *top_frame = win;
974e8d94 165 while (top_frame->GetParent() && !(top_frame->GetParent()->m_isFrame))
bd77da97 166 top_frame = top_frame->GetParent();
5bd9e519
RR
167
168 /* support for native key accelerators indicated by underscroes */
169 gtk_accel_group_attach( m_accel, GTK_OBJECT(top_frame->m_widget) );
170#endif
171
172 wxNode *node = m_menus.First();
173 while (node)
174 {
175 wxMenu *menu = (wxMenu*)node->Data();
176 wxMenubarSetInvokingWindow( menu, win );
177 node = node->Next();
178 }
179}
180
181void wxMenuBar::UnsetInvokingWindow( wxWindow *win )
182{
9c884972 183 m_invokingWindow = (wxWindow*) NULL;
5bd9e519
RR
184#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
185 wxWindow *top_frame = win;
974e8d94 186 while (top_frame->GetParent() && !(top_frame->GetParent()->m_isFrame))
bd77da97 187 top_frame = top_frame->GetParent();
5bd9e519
RR
188
189 /* support for native key accelerators indicated by underscroes */
190 gtk_accel_group_detach( m_accel, GTK_OBJECT(top_frame->m_widget) );
191#endif
192
193 wxNode *node = m_menus.First();
194 while (node)
195 {
196 wxMenu *menu = (wxMenu*)node->Data();
197 wxMenubarUnsetInvokingWindow( menu, win );
198 node = node->Next();
199 }
200}
201
3dfac970 202bool wxMenuBar::Append( wxMenu *menu, const wxString &title )
c801d85f 203{
83624f79 204 m_menus.Append( menu );
23280650 205
a533f5c1 206 const wxChar *pc;
23280650 207
1e133b7d
RR
208 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
209 wxString str;
223d09f6 210 for ( pc = title; *pc != wxT('\0'); pc++ )
83624f79 211 {
223d09f6 212 if (*pc == wxT('&'))
23280650 213 {
1e133b7d 214#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
223d09f6 215 str << wxT('_');
455fadaa 216 }
223d09f6 217 else if (*pc == wxT('/'))
23280650 218 {
223d09f6 219 str << wxT('\\');
034be888 220#endif
23280650 221 }
d38ceae8 222 else
455fadaa 223 {
90a53a3a 224#if __WXGTK12__
223d09f6 225 if ( *pc == wxT('_') )
455fadaa
VZ
226 {
227 // underscores must be doubled to prevent them from being
228 // interpreted as accelerator character prefix by GTK
229 str << *pc;
230 }
90a53a3a 231#endif // GTK+ 1.2
455fadaa
VZ
232
233 str << *pc;
234 }
1e133b7d
RR
235 }
236
237 /* this doesn't have much effect right now */
238 menu->SetTitle( str );
23280650 239
1e133b7d
RR
240 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
241#if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
242
243 /* local buffer in multibyte form */
2b2edbed 244 wxString buf;
223d09f6 245 buf << wxT('/') << str.c_str();
c980c992 246
dc6c62a9 247 char *cbuf = new char[buf.Length()+1];
c980c992
GL
248 strcpy(cbuf, buf.mbc_str());
249
1e133b7d 250 GtkItemFactoryEntry entry;
c980c992 251 entry.path = (gchar *)cbuf; // const_cast
1e133b7d
RR
252 entry.accelerator = (gchar*) NULL;
253 entry.callback = (GtkItemFactoryCallback) NULL;
254 entry.callback_action = 0;
2b2edbed
KB
255 entry.item_type = "<Branch>";
256
1e133b7d 257 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
1e133b7d 258 /* in order to get the pointer to the item we need the item text _without_ underscores */
223d09f6
KB
259 wxString tmp = wxT("<main>/");
260 for ( pc = str; *pc != wxT('\0'); pc++ )
1e133b7d 261 {
455fadaa
VZ
262 // contrary to the common sense, we must throw out _all_ underscores,
263 // (i.e. "Hello__World" => "HelloWorld" and not "Hello_World" as we
974e8d94 264 // might naively think). IMHO it's a bug in GTK+ (VZ)
223d09f6 265 while (*pc == wxT('_'))
455fadaa 266 pc++;
2b2edbed 267 tmp << *pc;
034be888 268 }
1e133b7d 269 menu->m_owner = gtk_item_factory_get_item( m_factory, tmp.mb_str() );
1e133b7d 270 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
2b2edbed 271 delete [] cbuf;
1e133b7d 272#else
96fd301f 273
1e133b7d 274 menu->m_owner = gtk_menu_item_new_with_label( str.mb_str() );
2b1c162e
RR
275 gtk_widget_show( menu->m_owner );
276 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
96fd301f 277
2b1c162e 278 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar), menu->m_owner );
23280650 279
1e133b7d 280#endif
9c884972
RR
281
282 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
283 // adding menu later on.
284 if (m_invokingWindow)
285 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
3dfac970
VZ
286
287 return TRUE;
288}
289
290bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
291{
292 if ( !wxMenuBarBase::Insert(pos, menu, title) )
293 return FALSE;
294
295 wxFAIL_MSG(wxT("TODO"));
296
297 return FALSE;
298}
299
300wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
301{
302 if ( !wxMenuBarBase::Replace(pos, menu, title) )
303 return FALSE;
304
305 wxFAIL_MSG(wxT("TODO"));
306
307 return NULL;
308}
309
310wxMenu *wxMenuBar::Remove(size_t pos)
311{
312 if ( !wxMenuBarBase::Remove(pos) )
313 return FALSE;
314
315 wxFAIL_MSG(wxT("TODO"));
316
317 return NULL;
6de97a3b 318}
96fd301f 319
716b7364 320static int FindMenuItemRecursive( const wxMenu *menu, const wxString &menuString, const wxString &itemString )
c801d85f 321{
c626a8b7 322 if (menu->GetTitle() == menuString)
83624f79
RR
323 {
324 int res = menu->FindItem( itemString );
c626a8b7
VZ
325 if (res != wxNOT_FOUND)
326 return res;
83624f79 327 }
c626a8b7
VZ
328
329 wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
83624f79
RR
330 while (node)
331 {
332 wxMenuItem *item = (wxMenuItem*)node->Data();
333 if (item->IsSubMenu())
334 return FindMenuItemRecursive(item->GetSubMenu(), menuString, itemString);
2b1c162e 335
83624f79
RR
336 node = node->Next();
337 }
338
c626a8b7
VZ
339 return wxNOT_FOUND;
340}
341
c801d85f
KB
342int wxMenuBar::FindMenuItem( const wxString &menuString, const wxString &itemString ) const
343{
83624f79
RR
344 wxNode *node = m_menus.First();
345 while (node)
346 {
347 wxMenu *menu = (wxMenu*)node->Data();
348 int res = FindMenuItemRecursive( menu, menuString, itemString);
349 if (res != -1) return res;
350 node = node->Next();
351 }
352 return -1;
6de97a3b 353}
c801d85f 354
c626a8b7 355// Find a wxMenuItem using its id. Recurses down into sub-menus
96fd301f 356static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id)
716b7364 357{
83624f79 358 wxMenuItem* result = menu->FindItem(id);
716b7364 359
c626a8b7
VZ
360 wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
361 while ( node && result == NULL )
83624f79
RR
362 {
363 wxMenuItem *item = (wxMenuItem*)node->Data();
364 if (item->IsSubMenu())
c626a8b7 365 {
83624f79 366 result = FindMenuItemByIdRecursive( item->GetSubMenu(), id );
c626a8b7 367 }
83624f79
RR
368 node = node->Next();
369 }
96fd301f 370
83624f79 371 return result;
6de97a3b 372}
716b7364 373
3dfac970 374wxMenuItem* wxMenuBar::FindItem( int id, wxMenu **menuForItem ) const
716b7364 375{
83624f79
RR
376 wxMenuItem* result = 0;
377 wxNode *node = m_menus.First();
378 while (node && result == 0)
379 {
380 wxMenu *menu = (wxMenu*)node->Data();
381 result = FindMenuItemByIdRecursive( menu, id );
382 node = node->Next();
383 }
c626a8b7 384
3dfac970
VZ
385 if ( menuForItem )
386 {
387 *menuForItem = result ? result->GetMenu() : (wxMenu *)NULL;
388 }
c626a8b7 389
3dfac970 390 return result;
bbe0af5b
RR
391}
392
3dfac970 393void wxMenuBar::EnableTop( size_t pos, bool flag )
bbe0af5b 394{
3dfac970 395 wxMenuList::Node *node = m_menus.Item( pos );
c626a8b7 396
223d09f6 397 wxCHECK_RET( node, wxT("menu not found") );
c626a8b7 398
3dfac970 399 wxMenu* menu = node->GetData();
c626a8b7
VZ
400
401 if (menu->m_owner)
402 gtk_widget_set_sensitive( menu->m_owner, flag );
bbe0af5b
RR
403}
404
3dfac970 405wxString wxMenuBar::GetLabelTop( size_t pos ) const
bbe0af5b 406{
3dfac970 407 wxMenuList::Node *node = m_menus.Item( pos );
c626a8b7 408
223d09f6 409 wxCHECK_MSG( node, wxT("invalid"), wxT("menu not found") );
c626a8b7 410
3dfac970 411 wxMenu* menu = node->GetData();
c626a8b7 412
2b1c162e 413 return menu->GetTitle();
bbe0af5b
RR
414}
415
3dfac970 416void wxMenuBar::SetLabelTop( size_t pos, const wxString& label )
bbe0af5b 417{
3dfac970 418 wxMenuList::Node *node = m_menus.Item( pos );
c626a8b7 419
223d09f6 420 wxCHECK_RET( node, wxT("menu not found") );
c626a8b7 421
3dfac970 422 wxMenu* menu = node->GetData();
c626a8b7 423
2b1c162e 424 menu->SetTitle( label );
bbe0af5b
RR
425}
426
c801d85f 427//-----------------------------------------------------------------------------
cf7a7e13 428// "activate"
c801d85f
KB
429//-----------------------------------------------------------------------------
430
6de97a3b 431static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
c801d85f 432{
acfd422a
RR
433 if (g_isIdle) wxapp_install_idle_handler();
434
83624f79 435 int id = menu->FindMenuIdByMenuItem(widget);
96fd301f 436
83624f79 437 /* should find it for normal (not popup) menu */
c626a8b7 438 wxASSERT( (id != -1) || (menu->GetInvokingWindow() != NULL) );
96fd301f 439
c626a8b7
VZ
440 if (!menu->IsEnabled(id))
441 return;
96fd301f 442
2d17d68f 443 wxMenuItem* item = menu->FindItem( id );
223d09f6 444 wxCHECK_RET( item, wxT("error in menu item callback") );
c626a8b7
VZ
445
446 if (item->IsCheckable())
2d17d68f 447 {
974e8d94
VZ
448 bool isReallyChecked = item->IsChecked();
449 if ( item->wxMenuItemBase::IsChecked() == isReallyChecked )
2d17d68f 450 {
c626a8b7 451 /* the menu item has been checked by calling wxMenuItem->Check() */
2d17d68f 452 return;
c626a8b7
VZ
453 }
454 else
455 {
974e8d94
VZ
456 /* the user pressed on the menu item -> report and make consistent
457 * again */
458 item->wxMenuItemBase::Check(isReallyChecked);
c626a8b7 459 }
2d17d68f
RR
460 }
461
83624f79
RR
462 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, id );
463 event.SetEventObject( menu );
464 event.SetInt(id );
8bbe427f 465
c626a8b7 466 if (menu->GetCallback())
83624f79 467 {
c626a8b7 468 (void) (*(menu->GetCallback())) (*menu, event);
83624f79
RR
469 return;
470 }
cf7a7e13 471
c626a8b7
VZ
472 if (menu->GetEventHandler()->ProcessEvent(event))
473 return;
cf7a7e13 474
83624f79 475 wxWindow *win = menu->GetInvokingWindow();
c626a8b7
VZ
476 if (win)
477 win->GetEventHandler()->ProcessEvent( event );
cf7a7e13
RR
478}
479
480//-----------------------------------------------------------------------------
481// "select"
482//-----------------------------------------------------------------------------
483
484static void gtk_menu_hilight_callback( GtkWidget *widget, wxMenu *menu )
485{
acfd422a
RR
486 if (g_isIdle) wxapp_install_idle_handler();
487
83624f79
RR
488 int id = menu->FindMenuIdByMenuItem(widget);
489
490 wxASSERT( id != -1 ); // should find it!
cf7a7e13 491
c626a8b7
VZ
492 if (!menu->IsEnabled(id))
493 return;
cf7a7e13 494
342b6a2f 495 wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, id );
83624f79 496 event.SetEventObject( menu );
cf7a7e13 497
c626a8b7
VZ
498 if (menu->GetEventHandler()->ProcessEvent(event))
499 return;
6de97a3b 500
83624f79
RR
501 wxWindow *win = menu->GetInvokingWindow();
502 if (win) win->GetEventHandler()->ProcessEvent( event );
6de97a3b 503}
c801d85f 504
cd743a6f
RR
505//-----------------------------------------------------------------------------
506// "deselect"
507//-----------------------------------------------------------------------------
508
509static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu )
510{
acfd422a
RR
511 if (g_isIdle) wxapp_install_idle_handler();
512
cd743a6f
RR
513 int id = menu->FindMenuIdByMenuItem(widget);
514
515 wxASSERT( id != -1 ); // should find it!
516
c626a8b7
VZ
517 if (!menu->IsEnabled(id))
518 return;
cd743a6f
RR
519
520 wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, -1 );
521 event.SetEventObject( menu );
522
c626a8b7
VZ
523 if (menu->GetEventHandler()->ProcessEvent(event))
524 return;
cd743a6f
RR
525
526 wxWindow *win = menu->GetInvokingWindow();
c626a8b7
VZ
527 if (win)
528 win->GetEventHandler()->ProcessEvent( event );
cd743a6f
RR
529}
530
cf7a7e13 531//-----------------------------------------------------------------------------
db1b4961 532// wxMenuItem
cf7a7e13
RR
533//-----------------------------------------------------------------------------
534
974e8d94
VZ
535IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxMenuItemBase)
536
537wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
538 int id,
539 const wxString& name,
540 const wxString& help,
541 bool isCheckable,
542 wxMenu *subMenu)
543{
544 return new wxMenuItem(parentMenu, id, name, help, isCheckable, subMenu);
545}
96fd301f 546
974e8d94
VZ
547wxMenuItem::wxMenuItem(wxMenu *parentMenu,
548 int id,
549 const wxString& text,
550 const wxString& help,
551 bool isCheckable,
552 wxMenu *subMenu)
c801d85f 553{
974e8d94
VZ
554 m_id = id;
555 m_isCheckable = isCheckable;
83624f79
RR
556 m_isChecked = FALSE;
557 m_isEnabled = TRUE;
974e8d94
VZ
558 m_subMenu = subMenu;
559 m_parentMenu = parentMenu;
560 m_help = help;
561
83624f79 562 m_menuItem = (GtkWidget *) NULL;
974e8d94
VZ
563
564 // call it after initializing m_menuItem to NULL
565 DoSetText(text);
6de97a3b 566}
c801d85f 567
d1b15f03
RR
568wxMenuItem::~wxMenuItem()
569{
570 // don't delete menu items, the menus take care of that
571}
572
c626a8b7 573// it's valid for this function to be called even if m_menuItem == NULL
974e8d94 574void wxMenuItem::DoSetText( const wxString& str )
716b7364 575{
ab46dc18 576 /* '\t' is the deliminator indicating a hot key */
974e8d94 577 m_text.Empty();
ab46dc18 578 const wxChar *pc = str;
223d09f6 579 for (; (*pc != wxT('\0')) && (*pc != wxT('\t')); pc++ )
83624f79 580 {
223d09f6 581 if (*pc == wxT('&'))
23280650 582 {
034be888 583#if (GTK_MINOR_VERSION > 0)
223d09f6 584 m_text << wxT('_');
572d7461 585 }
223d09f6 586 else if ( *pc == wxT('_') ) // escape underscores
572d7461 587 {
223d09f6 588 m_text << wxT("__");
572d7461 589 }
223d09f6 590 else if (*pc == wxT('/')) /* we have to filter out slashes ... */
23280650 591 {
223d09f6 592 m_text << wxT('\\'); /* ... and replace them with back slashes */
034be888
RR
593#endif
594 }
d38ceae8
KB
595 else
596 m_text << *pc;
83624f79 597 }
23280650 598
837904f2 599 /* only GTK 1.2 knows about hot keys */
223d09f6 600 m_hotKey = wxT("");
ab46dc18 601#if (GTK_MINOR_VERSION > 0)
223d09f6 602 if(*pc == wxT('\t'))
d7dbc98a
KB
603 {
604 pc++;
605 m_hotKey = pc;
606 }
ab46dc18 607#endif
96fd301f 608
83624f79
RR
609 if (m_menuItem)
610 {
611 GtkLabel *label = GTK_LABEL( GTK_BIN(m_menuItem)->child );
1e133b7d 612 gtk_label_set( label, m_text.mb_str());
83624f79 613 }
716b7364
RR
614}
615
96fd301f 616void wxMenuItem::Check( bool check )
716b7364 617{
223d09f6 618 wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
db1b4961 619
223d09f6 620 wxCHECK_RET( IsCheckable(), wxT("Can't check uncheckable item!") )
96fd301f 621
974e8d94
VZ
622 if (check == m_isChecked)
623 return;
2d17d68f 624
974e8d94 625 wxMenuItemBase::Check( check );
83624f79 626 gtk_check_menu_item_set_state( (GtkCheckMenuItem*)m_menuItem, (gint)check );
716b7364
RR
627}
628
8bbe427f
VZ
629void wxMenuItem::Enable( bool enable )
630{
223d09f6 631 wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
db1b4961 632
83624f79 633 gtk_widget_set_sensitive( m_menuItem, enable );
974e8d94 634 wxMenuItemBase::Enable( enable );
a9c96bcc
RR
635}
636
96fd301f 637bool wxMenuItem::IsChecked() const
716b7364 638{
223d09f6 639 wxCHECK_MSG( m_menuItem, FALSE, wxT("invalid menu item") );
db1b4961 640
974e8d94
VZ
641 wxCHECK_MSG( IsCheckable(), FALSE,
642 wxT("can't get state of uncheckable item!") );
96fd301f 643
974e8d94 644 return ((GtkCheckMenuItem*)m_menuItem)->active != 0;
716b7364
RR
645}
646
db1b4961 647//-----------------------------------------------------------------------------
83624f79 648// wxMenu
db1b4961
RR
649//-----------------------------------------------------------------------------
650
c801d85f
KB
651IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler)
652
ae53c98c 653void
b908d224 654wxMenu::Init( const wxString& title,
33961d59 655 long style,
455fadaa
VZ
656 const wxFunction func
657 )
c801d85f 658{
83624f79
RR
659 m_title = title;
660 m_items.DeleteContents( TRUE );
661 m_invokingWindow = (wxWindow *) NULL;
ae53c98c 662 m_style = style;
23280650 663
034be888
RR
664#if (GTK_MINOR_VERSION > 0)
665 m_accel = gtk_accel_group_new();
666 m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "<main>", m_accel );
667 m_menu = gtk_item_factory_get_widget( m_factory, "<main>" );
23280650 668#else
83624f79 669 m_menu = gtk_menu_new(); // Do not show!
034be888 670#endif
8bbe427f 671
83624f79 672 m_callback = func;
b908d224 673
83624f79
RR
674 m_eventHandler = this;
675 m_clientData = (void*) NULL;
8bbe427f 676
223d09f6
KB
677 if (m_title.IsNull()) m_title = wxT("");
678 if (m_title != wxT(""))
83624f79
RR
679 {
680 Append(-2, m_title);
681 AppendSeparator();
682 }
c626a8b7 683
2b1c162e 684 m_owner = (GtkWidget*) NULL;
2b2edbed
KB
685
686#if (GTK_MINOR_VERSION > 0)
687 /* Tearoffs are entries, just like separators. So if we want this
688 menu to be a tear-off one, we just append a tearoff entry
689 immediately. */
690 if(m_style & wxMENU_TEAROFF)
691 {
692 GtkItemFactoryEntry entry;
693 entry.path = "/tearoff";
694 entry.callback = (GtkItemFactoryCallback) NULL;
695 entry.callback_action = 0;
696 entry.item_type = "<Tearoff>";
697 entry.accelerator = (gchar*) NULL;
698 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
23280650 699 //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
2b2edbed
KB
700 }
701#endif
6de97a3b 702}
c801d85f 703
034be888
RR
704wxMenu::~wxMenu()
705{
d1b15f03
RR
706 wxNode *node = m_items.First();
707 while (node)
708 {
709 wxMenuItem *item = (wxMenuItem*)node->Data();
974e8d94
VZ
710 wxMenu *submenu = item->GetSubMenu();
711 if (submenu)
712 delete submenu;
d1b15f03
RR
713 node = node->Next();
714 }
15a2076a 715
d1b15f03 716 gtk_widget_destroy( m_menu );
974e8d94 717
d1b15f03 718 gtk_object_unref( GTK_OBJECT(m_factory) );
034be888
RR
719}
720
c2dd8380
GL
721void wxMenu::SetTitle( const wxString& title )
722{
c626a8b7 723 // TODO Waiting for something better
83624f79 724 m_title = title;
c2dd8380
GL
725}
726
727const wxString wxMenu::GetTitle() const
728{
83624f79 729 return m_title;
c2dd8380
GL
730}
731
96fd301f 732void wxMenu::AppendSeparator()
c801d85f 733{
974e8d94 734 wxMenuItem *mitem = new wxMenuItem(this, wxID_SEPARATOR);
96fd301f 735
08fc1744
RR
736#if (GTK_MINOR_VERSION > 0)
737 GtkItemFactoryEntry entry;
738 entry.path = "/sep";
739 entry.callback = (GtkItemFactoryCallback) NULL;
740 entry.callback_action = 0;
741 entry.item_type = "<Separator>";
742 entry.accelerator = (gchar*) NULL;
23280650 743
08fc1744 744 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
23280650 745
08fc1744
RR
746 /* this will be wrong for more than one separator. do we care? */
747 GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/sep" );
748#else
83624f79
RR
749 GtkWidget *menuItem = gtk_menu_item_new();
750 gtk_menu_append( GTK_MENU(m_menu), menuItem );
751 gtk_widget_show( menuItem );
08fc1744 752#endif
23280650 753
83624f79
RR
754 mitem->SetMenuItem(menuItem);
755 m_items.Append( mitem );
6de97a3b 756}
c801d85f 757
974e8d94
VZ
758#if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL
759static wxString GetHotKey( const wxMenuItem& item )
837904f2 760{
974e8d94 761 wxString hotkey;
23280650 762
974e8d94
VZ
763 // as wxGetAccelFromString() looks for TAB, insert a dummy one here
764 wxString label;
765 label << wxT('\t') << item.GetHotKey();
50592885
VZ
766
767 // but if the hotkey is empty don't do anything
768 if ( label.length() > 1 )
837904f2 769 {
50592885
VZ
770 wxAcceleratorEntry *accel = wxGetAccelFromString(label);
771 if ( accel )
23280650 772 {
50592885
VZ
773 int flags = accel->GetFlags();
774 if ( flags & wxACCEL_ALT )
775 hotkey += wxT("<alt>");
776 if ( flags & wxACCEL_CTRL )
777 hotkey += wxT("<control>");
778 if ( flags & wxACCEL_SHIFT )
779 hotkey += wxT("<shift>");
780
781 int code = accel->GetKeyCode();
782 switch ( code )
783 {
784 case WXK_F1:
785 case WXK_F2:
786 case WXK_F3:
787 case WXK_F4:
788 case WXK_F5:
789 case WXK_F6:
790 case WXK_F7:
791 case WXK_F8:
792 case WXK_F9:
793 case WXK_F10:
794 case WXK_F11:
795 case WXK_F12:
3dfac970 796 hotkey << wxT('F') << code - WXK_F1 + 1;
974e8d94 797 break;
974e8d94 798
50592885
VZ
799 // if there are any other keys wxGetAccelFromString() may return,
800 // we should process them here
801
802 default:
803 if ( wxIsalnum(code) )
804 {
805 hotkey << (wxChar)code;
806
807 break;
808 }
809
810 wxFAIL_MSG( wxT("unknown keyboard accel") );
811 }
812
813 delete accel;
23280650 814 }
837904f2 815 }
974e8d94
VZ
816
817 return hotkey;
837904f2 818}
974e8d94 819#endif // wxUSE_ACCEL
837904f2 820
debe6624 821void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool checkable )
c801d85f 822{
974e8d94 823 wxMenuItem *mitem = new wxMenuItem(this, id, item, helpStr, checkable);
23280650 824
034be888 825#if (GTK_MINOR_VERSION > 0)
23280650 826 /* text has "_" instead of "&" after mitem->SetText() */
1e133b7d 827 wxString text( mitem->GetText() );
23280650 828
1e133b7d
RR
829 /* local buffer in multibyte form */
830 char buf[200];
831 strcpy( buf, "/" );
832 strcat( buf, text.mb_str() );
23280650 833
034be888 834 GtkItemFactoryEntry entry;
1e133b7d 835 entry.path = buf;
034be888
RR
836 entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
837 entry.callback_action = 0;
838 if (checkable)
839 entry.item_type = "<CheckItem>";
840 else
841 entry.item_type = "<Item>";
23280650 842
974e8d94
VZ
843#if wxUSE_ACCEL
844 // due to an apparent bug in GTK+, we have to use a static buffer here -
845 // otherwise GTK+ 1.2.2 manages to override the memory we pass to it
846 // somehow! (VZ)
847 static char s_accel[32]; // must be big enough for <control><alt><shift>F12
848 strncpy(s_accel, GetHotKey(*mitem).mb_str(), WXSIZEOF(s_accel));
849 entry.accelerator = s_accel;
850#else
851 entry.accelerator = NULL;
852#endif
23280650 853
034be888 854 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
23280650 855
034be888 856 /* in order to get the pointer to the item we need the item text _without_ underscores */
223d09f6
KB
857 wxString s = wxT("<main>/");
858 for ( const wxChar *pc = text; *pc != wxT('\0'); pc++ )
034be888 859 {
223d09f6 860 while (*pc == wxT('_')) pc++; /* skip it */
034be888
RR
861 s << *pc;
862 }
23280650 863
1e133b7d 864 GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, s.mb_str() );
23280650 865
034be888
RR
866#else
867
d38ceae8
KB
868 GtkWidget *menuItem = checkable ? gtk_check_menu_item_new_with_label( mitem->GetText().mb_str() )
869 : gtk_menu_item_new_with_label( mitem->GetText().mb_str() );
23280650 870
83624f79
RR
871 gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
872 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
034be888 873 (gpointer)this );
23280650 874
034be888
RR
875 gtk_menu_append( GTK_MENU(m_menu), menuItem );
876 gtk_widget_show( menuItem );
23280650 877
034be888 878#endif
96fd301f 879
83624f79
RR
880 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
881 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
034be888 882 (gpointer)this );
cf7a7e13 883
cd743a6f
RR
884 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
885 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
034be888
RR
886 (gpointer)this );
887
888 mitem->SetMenuItem(menuItem);
cd743a6f 889
83624f79 890 m_items.Append( mitem );
6de97a3b 891}
c801d85f 892
837904f2 893void wxMenu::Append( int id, const wxString &item, wxMenu *subMenu, const wxString &helpStr )
c801d85f 894{
974e8d94 895 wxMenuItem *mitem = new wxMenuItem(this, id, item, helpStr, FALSE, subMenu);
96fd301f 896
837904f2 897#if (GTK_MINOR_VERSION > 0)
23280650 898 /* text has "_" instead of "&" after mitem->SetText() */
837904f2 899 wxString text( mitem->GetText() );
23280650 900
837904f2
RR
901 /* local buffer in multibyte form */
902 char buf[200];
903 strcpy( buf, "/" );
904 strcat( buf, text.mb_str() );
23280650 905
837904f2
RR
906 GtkItemFactoryEntry entry;
907 entry.path = buf;
908 entry.callback = (GtkItemFactoryCallback) 0;
909 entry.callback_action = 0;
2b2edbed 910 entry.item_type = "<Branch>";
23280650 911
837904f2 912 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
23280650 913
837904f2 914 /* in order to get the pointer to the item we need the item text _without_ underscores */
223d09f6
KB
915 wxString s = wxT("<main>/");
916 for ( const wxChar *pc = text; *pc != wxT('\0'); pc++ )
837904f2 917 {
223d09f6 918 if (*pc == wxT('_')) pc++; /* skip it */
837904f2
RR
919 s << *pc;
920 }
23280650 921
837904f2 922 GtkWidget *menuItem = gtk_item_factory_get_item( m_factory, s.mb_str() );
23280650 923
837904f2
RR
924#else
925
b019151f 926 GtkWidget *menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str());
23280650 927
837904f2
RR
928 gtk_menu_append( GTK_MENU(m_menu), menuItem );
929 gtk_widget_show( menuItem );
23280650
VZ
930
931#endif
96fd301f 932
cd743a6f
RR
933 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
934 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
935 (gpointer*)this );
936
937 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
938 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
939 (gpointer*)this );
940
83624f79 941 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), subMenu->m_menu );
23280650 942
837904f2 943 mitem->SetMenuItem(menuItem);
837904f2 944
83624f79 945 m_items.Append( mitem );
6de97a3b 946}
c801d85f 947
828f655f
RR
948void wxMenu::Append( wxMenuItem *item )
949{
950 m_items.Append( item );
c626a8b7 951
828f655f
RR
952 GtkWidget *menuItem = (GtkWidget*) NULL;
953
c626a8b7 954 if (item->IsSeparator())
828f655f 955 menuItem = gtk_menu_item_new();
c626a8b7 956 else if (item->IsSubMenu())
b019151f 957 menuItem = gtk_menu_item_new_with_label(item->GetText().mbc_str());
c626a8b7 958 else
b019151f
OK
959 menuItem = item->IsCheckable() ? gtk_check_menu_item_new_with_label(item->GetText().mbc_str())
960 : gtk_menu_item_new_with_label(item->GetText().mbc_str());
828f655f
RR
961
962 if (!item->IsSeparator())
963 {
964 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
965 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
966 (gpointer*)this );
967
968 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
969 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
970 (gpointer*)this );
c626a8b7
VZ
971
972 if (!item->IsSubMenu())
973 {
828f655f
RR
974 gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
975 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
976 (gpointer*)this );
c626a8b7 977 }
828f655f 978 }
c626a8b7 979
828f655f
RR
980 gtk_menu_append( GTK_MENU(m_menu), menuItem );
981 gtk_widget_show( menuItem );
982 item->SetMenuItem(menuItem);
983}
984
d1b15f03
RR
985void wxMenu::Delete( int id )
986{
987 wxNode *node = m_items.First();
988 while (node)
989 {
990 wxMenuItem *item = (wxMenuItem*)node->Data();
991 if (item->GetId() == id)
992 {
974e8d94
VZ
993 gtk_widget_destroy( item->GetMenuItem() );
994 m_items.DeleteNode( node );
d1b15f03
RR
995 return;
996 }
997 node = node->Next();
998 }
999}
1000
c801d85f
KB
1001int wxMenu::FindItem( const wxString itemString ) const
1002{
223d09f6
KB
1003 wxString s = wxT("");
1004 for ( const wxChar *pc = itemString; *pc != wxT('\0'); pc++ )
83624f79 1005 {
223d09f6 1006 if (*pc == wxT('&'))
23280650
VZ
1007 {
1008 pc++; /* skip it */
034be888 1009#if (GTK_MINOR_VERSION > 0)
223d09f6 1010 s << wxT('_');
034be888
RR
1011#endif
1012 }
1013 s << *pc;
1014 }
96fd301f 1015
83624f79
RR
1016 wxNode *node = m_items.First();
1017 while (node)
1018 {
1019 wxMenuItem *item = (wxMenuItem*)node->Data();
1020 if (item->GetText() == s)
c626a8b7 1021 {
83624f79 1022 return item->GetId();
c626a8b7 1023 }
83624f79
RR
1024 node = node->Next();
1025 }
96fd301f 1026
c626a8b7 1027 return wxNOT_FOUND;
6de97a3b 1028}
c801d85f 1029
96fd301f 1030void wxMenu::Enable( int id, bool enable )
716b7364 1031{
83624f79 1032 wxMenuItem *item = FindItem(id);
c626a8b7 1033
223d09f6 1034 wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
c626a8b7
VZ
1035
1036 item->Enable(enable);
6de97a3b 1037}
716b7364 1038
96fd301f 1039bool wxMenu::IsEnabled( int id ) const
e2414cbe 1040{
83624f79 1041 wxMenuItem *item = FindItem(id);
c626a8b7 1042
223d09f6 1043 wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsEnabled: no such item") );
c626a8b7
VZ
1044
1045 return item->IsEnabled();
6de97a3b 1046}
e2414cbe 1047
96fd301f 1048void wxMenu::Check( int id, bool enable )
c801d85f 1049{
83624f79 1050 wxMenuItem *item = FindItem(id);
c626a8b7 1051
223d09f6 1052 wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
c626a8b7
VZ
1053
1054 item->Check(enable);
6de97a3b 1055}
c801d85f 1056
96fd301f 1057bool wxMenu::IsChecked( int id ) const
c801d85f 1058{
83624f79 1059 wxMenuItem *item = FindItem(id);
c626a8b7 1060
223d09f6 1061 wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsChecked: no such item") );
c626a8b7
VZ
1062
1063 return item->IsChecked();
6de97a3b 1064}
c801d85f 1065
debe6624 1066void wxMenu::SetLabel( int id, const wxString &label )
c801d85f 1067{
83624f79 1068 wxMenuItem *item = FindItem(id);
c626a8b7 1069
223d09f6 1070 wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
c626a8b7
VZ
1071
1072 item->SetText(label);
6de97a3b 1073}
96fd301f 1074
c33c4050
RR
1075wxString wxMenu::GetLabel( int id ) const
1076{
83624f79 1077 wxMenuItem *item = FindItem(id);
c626a8b7 1078
223d09f6 1079 wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetLabel: no such item") );
c626a8b7
VZ
1080
1081 return item->GetText();
c33c4050
RR
1082}
1083
1084void wxMenu::SetHelpString( int id, const wxString& helpString )
1085{
83624f79 1086 wxMenuItem *item = FindItem(id);
c626a8b7 1087
223d09f6 1088 wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
c626a8b7
VZ
1089
1090 item->SetHelp( helpString );
c33c4050
RR
1091}
1092
1093wxString wxMenu::GetHelpString( int id ) const
1094{
83624f79 1095 wxMenuItem *item = FindItem(id);
c626a8b7 1096
223d09f6 1097 wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetHelpString: no such item") );
c626a8b7
VZ
1098
1099 return item->GetHelp();
c33c4050
RR
1100}
1101
96fd301f
VZ
1102int wxMenu::FindMenuIdByMenuItem( GtkWidget *menuItem ) const
1103{
83624f79
RR
1104 wxNode *node = m_items.First();
1105 while (node)
1106 {
1107 wxMenuItem *item = (wxMenuItem*)node->Data();
1108 if (item->GetMenuItem() == menuItem)
1109 return item->GetId();
1110 node = node->Next();
1111 }
96fd301f 1112
c626a8b7 1113 return wxNOT_FOUND;
6de97a3b 1114}
c801d85f 1115
96fd301f 1116wxMenuItem *wxMenu::FindItem(int id) const
c801d85f 1117{
83624f79 1118 wxNode *node = m_items.First();
c626a8b7 1119 while (node)
83624f79
RR
1120 {
1121 wxMenuItem *item = (wxMenuItem*)node->Data();
1122 if (item->GetId() == id)
c626a8b7 1123 {
83624f79 1124 return item;
c626a8b7 1125 }
83624f79
RR
1126 node = node->Next();
1127 }
96fd301f 1128
83624f79
RR
1129 /* Not finding anything here can be correct
1130 * when search the entire menu system for
1131 * an entry -> no error message. */
8bbe427f 1132
83624f79 1133 return (wxMenuItem *) NULL;
96fd301f 1134}
c801d85f
KB
1135
1136void wxMenu::SetInvokingWindow( wxWindow *win )
1137{
83624f79 1138 m_invokingWindow = win;
6de97a3b 1139}
c801d85f 1140
96fd301f 1141wxWindow *wxMenu::GetInvokingWindow()
c801d85f 1142{
83624f79 1143 return m_invokingWindow;
6de97a3b 1144}
c801d85f 1145
c626a8b7
VZ
1146// Update a menu and all submenus recursively. source is the object that has
1147// the update event handlers defined for it. If NULL, the menu or associated
1148// window will be used.
631f1bfe
JS
1149void wxMenu::UpdateUI(wxEvtHandler* source)
1150{
1151 if (!source && GetInvokingWindow())
1152 source = GetInvokingWindow()->GetEventHandler();
1153 if (!source)
1154 source = GetEventHandler();
1155 if (!source)
1156 source = this;
1157
1158 wxNode* node = GetItems().First();
1159 while (node)
1160 {
1161 wxMenuItem* item = (wxMenuItem*) node->Data();
1162 if ( !item->IsSeparator() )
1163 {
1164 wxWindowID id = item->GetId();
1165 wxUpdateUIEvent event(id);
1166 event.SetEventObject( source );
1167
1168 if (source->ProcessEvent(event))
1169 {
1170 if (event.GetSetText())
1171 SetLabel(id, event.GetText());
1172 if (event.GetSetChecked())
1173 Check(id, event.GetChecked());
1174 if (event.GetSetEnabled())
1175 Enable(id, event.GetEnabled());
1176 }
1177
1178 if (item->GetSubMenu())
1179 item->GetSubMenu()->UpdateUI(source);
1180 }
1181 node = node->Next();
1182 }
1183}
1184