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