]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/menu.cpp
Fixed gtk 1.0.6 corruped menu entry names.
[wxWidgets.git] / src / gtk / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: menu.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "menu.h"
12 #pragma implementation "menuitem.h"
13 #endif
14
15 #include "wx/menu.h"
16 #include "wx/log.h"
17 #include "wx/intl.h"
18 #include "wx/app.h"
19
20 #include "gdk/gdk.h"
21 #include "gtk/gtk.h"
22
23 //-----------------------------------------------------------------------------
24 // idle system
25 //-----------------------------------------------------------------------------
26
27 extern void wxapp_install_idle_handler();
28 extern bool g_isIdle;
29
30 //-----------------------------------------------------------------------------
31 // wxMenuBar
32 //-----------------------------------------------------------------------------
33
34 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar,wxWindow)
35
36 wxMenuBar::wxMenuBar( long style )
37 {
38 /* the parent window is known after wxFrame::SetMenu() */
39 m_needParent = FALSE;
40
41 PreCreation( (wxWindow *) NULL, -1, wxDefaultPosition, wxDefaultSize, style, "menu" );
42
43 m_menus.DeleteContents( TRUE );
44
45 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
46 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
47 m_accel = gtk_accel_group_new();
48 m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
49 m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
50 #else
51 m_menubar = gtk_menu_bar_new();
52 #endif
53
54 if (style & wxMB_DOCKABLE)
55 {
56 m_widget = gtk_handle_box_new();
57 gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_menubar) );
58 gtk_widget_show( GTK_WIDGET(m_menubar) );
59 }
60 else
61 {
62 m_widget = GTK_WIDGET(m_menubar);
63 }
64
65 PostCreation();
66
67 Show( TRUE );
68 }
69
70 wxMenuBar::wxMenuBar()
71 {
72 /* the parent window is known after wxFrame::SetMenu() */
73 m_needParent = FALSE;
74
75 PreCreation( (wxWindow *) NULL, -1, wxDefaultPosition, wxDefaultSize, 0, "menu" );
76
77 m_menus.DeleteContents( TRUE );
78
79 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
80 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
81 m_accel = gtk_accel_group_new();
82 m_factory = gtk_item_factory_new( GTK_TYPE_MENU_BAR, "<main>", m_accel );
83 m_menubar = gtk_item_factory_get_widget( m_factory, "<main>" );
84 #else
85 m_menubar = gtk_menu_bar_new();
86 #endif
87
88 m_widget = GTK_WIDGET(m_menubar);
89
90 PostCreation();
91
92 Show( TRUE );
93 }
94
95 wxMenuBar::~wxMenuBar()
96 {
97 // how to destroy a GtkItemFactory ?
98 }
99
100 void wxMenuBar::Append( wxMenu *menu, const wxString &title )
101 {
102 m_menus.Append( menu );
103
104 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
105 wxString str;
106 for ( const wxChar *pc = title; *pc != _T('\0'); pc++ )
107 {
108 if (*pc == _T('&'))
109 {
110 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
111 str << _T('_');
112 #endif
113 }
114 else
115 str << *pc;
116 }
117
118 /* this doesn't have much effect right now */
119 menu->SetTitle( str );
120
121 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
122 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
123
124 /* local buffer in multibyte form */
125 char buf[200];
126 strcpy( buf, "/" );
127 strcat( buf, str.mb_str() );
128
129 GtkItemFactoryEntry entry;
130 entry.path = buf;
131 entry.accelerator = (gchar*) NULL;
132 entry.callback = (GtkItemFactoryCallback) NULL;
133 entry.callback_action = 0;
134 entry.item_type = "<Branch>";
135
136 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
137
138 /* in order to get the pointer to the item we need the item text _without_ underscores */
139 wxString tmp = _T("<main>/");
140 for ( const wxChar *pc = str; *pc != _T('\0'); pc++ )
141 {
142 if (*pc == _T('_')) pc++; /* skip it */
143 tmp << *pc;
144 }
145
146 menu->m_owner = gtk_item_factory_get_item( m_factory, tmp.mb_str() );
147
148 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
149
150 #else
151
152 menu->m_owner = gtk_menu_item_new_with_label( str.mb_str() );
153 gtk_widget_show( menu->m_owner );
154 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu );
155
156 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar), menu->m_owner );
157
158 #endif
159 }
160
161 static int FindMenuItemRecursive( const wxMenu *menu, const wxString &menuString, const wxString &itemString )
162 {
163 if (menu->GetTitle() == menuString)
164 {
165 int res = menu->FindItem( itemString );
166 if (res != wxNOT_FOUND)
167 return res;
168 }
169
170 wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
171 while (node)
172 {
173 wxMenuItem *item = (wxMenuItem*)node->Data();
174 if (item->IsSubMenu())
175 return FindMenuItemRecursive(item->GetSubMenu(), menuString, itemString);
176
177 node = node->Next();
178 }
179
180 return wxNOT_FOUND;
181 }
182
183 wxMenuItem *wxMenuBar::FindItemForId(int itemId, wxMenu **menuForItem = NULL) const
184 {
185 if ( menuForItem )
186 {
187 // TODO return the pointer to the menu
188
189 *menuForItem = NULL;
190 }
191
192 return FindItem(itemId);
193 }
194
195 int wxMenuBar::FindMenuItem( const wxString &menuString, const wxString &itemString ) const
196 {
197 wxNode *node = m_menus.First();
198 while (node)
199 {
200 wxMenu *menu = (wxMenu*)node->Data();
201 int res = FindMenuItemRecursive( menu, menuString, itemString);
202 if (res != -1) return res;
203 node = node->Next();
204 }
205 return -1;
206 }
207
208 // Find a wxMenuItem using its id. Recurses down into sub-menus
209 static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id)
210 {
211 wxMenuItem* result = menu->FindItem(id);
212
213 wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
214 while ( node && result == NULL )
215 {
216 wxMenuItem *item = (wxMenuItem*)node->Data();
217 if (item->IsSubMenu())
218 {
219 result = FindMenuItemByIdRecursive( item->GetSubMenu(), id );
220 }
221 node = node->Next();
222 }
223
224 return result;
225 }
226
227 wxMenuItem* wxMenuBar::FindItem( int id ) const
228 {
229 wxMenuItem* result = 0;
230 wxNode *node = m_menus.First();
231 while (node && result == 0)
232 {
233 wxMenu *menu = (wxMenu*)node->Data();
234 result = FindMenuItemByIdRecursive( menu, id );
235 node = node->Next();
236 }
237
238 return result;
239 }
240
241 void wxMenuBar::Check( int id, bool check )
242 {
243 wxMenuItem* item = FindMenuItemById( id );
244
245 wxCHECK_RET( item, _T("wxMenuBar::Check: no such item") );
246
247 item->Check(check);
248 }
249
250 bool wxMenuBar::IsChecked( int id ) const
251 {
252 wxMenuItem* item = FindMenuItemById( id );
253
254 wxCHECK_MSG( item, FALSE, _T("wxMenuBar::IsChecked: no such item") );
255
256 return item->IsChecked();
257 }
258
259 void wxMenuBar::Enable( int id, bool enable )
260 {
261 wxMenuItem* item = FindMenuItemById( id );
262
263 wxCHECK_RET( item, _T("wxMenuBar::Enable: no such item") );
264
265 item->Enable(enable);
266 }
267
268 bool wxMenuBar::IsEnabled( int id ) const
269 {
270 wxMenuItem* item = FindMenuItemById( id );
271
272 wxCHECK_MSG( item, FALSE, _T("wxMenuBar::IsEnabled: no such item") );
273
274 return item->IsEnabled();
275 }
276
277 wxString wxMenuBar::GetLabel( int id ) const
278 {
279 wxMenuItem* item = FindMenuItemById( id );
280
281 wxCHECK_MSG( item, _T(""), _T("wxMenuBar::GetLabel: no such item") );
282
283 return item->GetText();
284 }
285
286 void wxMenuBar::SetLabel( int id, const wxString &label )
287 {
288 wxMenuItem* item = FindMenuItemById( id );
289
290 wxCHECK_RET( item, _T("wxMenuBar::SetLabel: no such item") );
291
292 item->SetText( label );
293 }
294
295 void wxMenuBar::EnableTop( int pos, bool flag )
296 {
297 wxNode *node = m_menus.Nth( pos );
298
299 wxCHECK_RET( node, _T("menu not found") );
300
301 wxMenu* menu = (wxMenu*)node->Data();
302
303 if (menu->m_owner)
304 gtk_widget_set_sensitive( menu->m_owner, flag );
305 }
306
307 wxString wxMenuBar::GetLabelTop( int pos ) const
308 {
309 wxNode *node = m_menus.Nth( pos );
310
311 wxCHECK_MSG( node, _T("invalid"), _T("menu not found") );
312
313 wxMenu* menu = (wxMenu*)node->Data();
314
315 return menu->GetTitle();
316 }
317
318 void wxMenuBar::SetLabelTop( int pos, const wxString& label )
319 {
320 wxNode *node = m_menus.Nth( pos );
321
322 wxCHECK_RET( node, _T("menu not found") );
323
324 wxMenu* menu = (wxMenu*)node->Data();
325
326 menu->SetTitle( label );
327 }
328
329 void wxMenuBar::SetHelpString( int id, const wxString& helpString )
330 {
331 wxMenuItem* item = FindMenuItemById( id );
332
333 wxCHECK_RET( item, _T("wxMenuBar::SetHelpString: no such item") );
334
335 item->SetHelp( helpString );
336 }
337
338 wxString wxMenuBar::GetHelpString( int id ) const
339 {
340 wxMenuItem* item = FindMenuItemById( id );
341
342 wxCHECK_MSG( item, _T(""), _T("wxMenuBar::GetHelpString: no such item") );
343
344 return item->GetHelp();
345 }
346
347 //-----------------------------------------------------------------------------
348 // "activate"
349 //-----------------------------------------------------------------------------
350
351 static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
352 {
353 if (g_isIdle) wxapp_install_idle_handler();
354
355 int id = menu->FindMenuIdByMenuItem(widget);
356
357 /* should find it for normal (not popup) menu */
358 wxASSERT( (id != -1) || (menu->GetInvokingWindow() != NULL) );
359
360 if (!menu->IsEnabled(id))
361 return;
362
363 wxMenuItem* item = menu->FindItem( id );
364 wxCHECK_RET( item, _T("error in menu item callback") );
365
366 if (item->IsCheckable())
367 {
368 if (item->GetCheckedFlag() == item->IsChecked())
369 {
370 /* the menu item has been checked by calling wxMenuItem->Check() */
371 return;
372 }
373 else
374 {
375 /* the user pressed on the menu item -> report */
376 item->SetCheckedFlag(item->IsChecked()); /* make consistent again */
377 }
378 }
379
380 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, id );
381 event.SetEventObject( menu );
382 event.SetInt(id );
383
384 if (menu->GetCallback())
385 {
386 (void) (*(menu->GetCallback())) (*menu, event);
387 return;
388 }
389
390 if (menu->GetEventHandler()->ProcessEvent(event))
391 return;
392
393 wxWindow *win = menu->GetInvokingWindow();
394 if (win)
395 win->GetEventHandler()->ProcessEvent( event );
396 }
397
398 //-----------------------------------------------------------------------------
399 // "select"
400 //-----------------------------------------------------------------------------
401
402 static void gtk_menu_hilight_callback( GtkWidget *widget, wxMenu *menu )
403 {
404 if (g_isIdle) wxapp_install_idle_handler();
405
406 int id = menu->FindMenuIdByMenuItem(widget);
407
408 wxASSERT( id != -1 ); // should find it!
409
410 if (!menu->IsEnabled(id))
411 return;
412
413 wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, id );
414 event.SetEventObject( menu );
415
416 /* wxMSW doesn't call callback here either
417
418 if (menu->m_callback)
419 {
420 (void) (*(menu->m_callback)) (*menu, event);
421 return;
422 }
423 */
424
425 if (menu->GetEventHandler()->ProcessEvent(event))
426 return;
427
428 wxWindow *win = menu->GetInvokingWindow();
429 if (win) win->GetEventHandler()->ProcessEvent( event );
430 }
431
432 //-----------------------------------------------------------------------------
433 // "deselect"
434 //-----------------------------------------------------------------------------
435
436 static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu )
437 {
438 if (g_isIdle) wxapp_install_idle_handler();
439
440 int id = menu->FindMenuIdByMenuItem(widget);
441
442 wxASSERT( id != -1 ); // should find it!
443
444 if (!menu->IsEnabled(id))
445 return;
446
447 wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, -1 );
448 event.SetEventObject( menu );
449
450 if (menu->GetEventHandler()->ProcessEvent(event))
451 return;
452
453 wxWindow *win = menu->GetInvokingWindow();
454 if (win)
455 win->GetEventHandler()->ProcessEvent( event );
456 }
457
458 //-----------------------------------------------------------------------------
459 // wxMenuItem
460 //-----------------------------------------------------------------------------
461
462 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem,wxObject)
463
464 wxMenuItem::wxMenuItem()
465 {
466 m_id = ID_SEPARATOR;
467 m_isCheckMenu = FALSE;
468 m_isChecked = FALSE;
469 m_isEnabled = TRUE;
470 m_subMenu = (wxMenu *) NULL;
471 m_menuItem = (GtkWidget *) NULL;
472 }
473
474 // it's valid for this function to be called even if m_menuItem == NULL
475 void wxMenuItem::SetName( const wxString& str )
476 {
477 m_text = _T("");
478 for ( const wxChar *pc = str; *pc != _T('\0'); pc++ )
479 {
480 if (*pc == _T('&'))
481 {
482 #if (GTK_MINOR_VERSION > 0)
483 m_text << _T('_');
484 #endif
485 }
486 else
487 m_text << *pc;
488 }
489
490 if (m_menuItem)
491 {
492 GtkLabel *label = GTK_LABEL( GTK_BIN(m_menuItem)->child );
493 gtk_label_set( label, m_text.mb_str());
494 }
495 }
496
497 void wxMenuItem::Check( bool check )
498 {
499 wxCHECK_RET( m_menuItem, _T("invalid menu item") );
500
501 wxCHECK_RET( IsCheckable(), _T("Can't check uncheckable item!") )
502
503 if (check == m_isChecked) return;
504
505 m_isChecked = check;
506 gtk_check_menu_item_set_state( (GtkCheckMenuItem*)m_menuItem, (gint)check );
507 }
508
509 void wxMenuItem::Enable( bool enable )
510 {
511 wxCHECK_RET( m_menuItem, _T("invalid menu item") );
512
513 gtk_widget_set_sensitive( m_menuItem, enable );
514 m_isEnabled = enable;
515 }
516
517 bool wxMenuItem::IsChecked() const
518 {
519 wxCHECK_MSG( m_menuItem, FALSE, _T("invalid menu item") );
520
521 wxCHECK( IsCheckable(), FALSE ); // can't get state of uncheckable item!
522
523 bool bIsChecked = ((GtkCheckMenuItem*)m_menuItem)->active != 0;
524
525 return bIsChecked;
526 }
527
528 //-----------------------------------------------------------------------------
529 // wxMenu
530 //-----------------------------------------------------------------------------
531
532 IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler)
533
534 wxMenu::wxMenu( const wxString& title, const wxFunction func )
535 {
536 m_title = title;
537 m_items.DeleteContents( TRUE );
538 m_invokingWindow = (wxWindow *) NULL;
539
540 #if (GTK_MINOR_VERSION > 0)
541 m_accel = gtk_accel_group_new();
542 m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "<main>", m_accel );
543 m_menu = gtk_item_factory_get_widget( m_factory, "<main>" );
544 #else
545 m_menu = gtk_menu_new(); // Do not show!
546 #endif
547
548 m_callback = func;
549 m_eventHandler = this;
550 m_clientData = (void*) NULL;
551
552 if (m_title.IsNull()) m_title = _T("");
553 if (m_title != _T(""))
554 {
555 Append(-2, m_title);
556 AppendSeparator();
557 }
558
559 m_owner = (GtkWidget*) NULL;
560 }
561
562 wxMenu::~wxMenu()
563 {
564 /* how do we delete an item-factory ? */
565 }
566
567 void wxMenu::SetTitle( const wxString& title )
568 {
569 // TODO Waiting for something better
570 m_title = title;
571 }
572
573 const wxString wxMenu::GetTitle() const
574 {
575 return m_title;
576 }
577
578 void wxMenu::AppendSeparator()
579 {
580 wxMenuItem *mitem = new wxMenuItem();
581 mitem->SetId(ID_SEPARATOR);
582
583 GtkWidget *menuItem = gtk_menu_item_new();
584 gtk_menu_append( GTK_MENU(m_menu), menuItem );
585 gtk_widget_show( menuItem );
586
587 mitem->SetMenuItem(menuItem);
588 m_items.Append( mitem );
589 }
590
591 void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool checkable )
592 {
593 wxMenuItem *mitem = new wxMenuItem();
594 mitem->SetId(id);
595 mitem->SetText(item);
596 mitem->SetHelp(helpStr);
597 mitem->SetCheckable(checkable);
598
599 #if (GTK_MINOR_VERSION > 0)
600 /* text has "_" instead of "&" after mitem->SetText() */
601 wxString text( mitem->GetText() );
602
603 /* local buffer in multibyte form */
604 char buf[200];
605 strcpy( buf, "/" );
606 strcat( buf, text.mb_str() );
607
608 GtkItemFactoryEntry entry;
609 entry.path = buf;
610 entry.accelerator = (gchar*) NULL;
611 entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
612 entry.callback_action = 0;
613 if (checkable)
614 entry.item_type = "<CheckItem>";
615 else
616 entry.item_type = "<Item>";
617
618 gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
619
620 /* in order to get the pointer to the item we need the item text _without_ underscores */
621 wxString s = _T("<main>/");
622 for ( const wxChar *pc = text; *pc != _T('\0'); pc++ )
623 {
624 if (*pc == _T('_')) pc++; /* skip it */
625 s << *pc;
626 }
627
628 GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, s.mb_str() );
629
630 #else
631
632 GtkWidget *menuItem = checkable ? gtk_check_menu_item_new_with_label( mitem->GetText().mb_str() )
633 : gtk_menu_item_new_with_label( mitem->GetText().mb_str() );
634
635 gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
636 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
637 (gpointer)this );
638
639 gtk_menu_append( GTK_MENU(m_menu), menuItem );
640 gtk_widget_show( menuItem );
641
642 #endif
643
644 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
645 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
646 (gpointer)this );
647
648 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
649 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
650 (gpointer)this );
651
652 mitem->SetMenuItem(menuItem);
653
654 m_items.Append( mitem );
655 }
656
657 void wxMenu::Append( int id, const wxString &text, wxMenu *subMenu, const wxString &helpStr )
658 {
659 wxMenuItem *mitem = new wxMenuItem();
660 mitem->SetId(id);
661 mitem->SetText(text);
662 mitem->SetHelp(helpStr);
663
664 GtkWidget *menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str());
665 mitem->SetMenuItem(menuItem);
666 mitem->SetSubMenu(subMenu);
667
668 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
669 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
670 (gpointer*)this );
671
672 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
673 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
674 (gpointer*)this );
675
676 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), subMenu->m_menu );
677 gtk_menu_append( GTK_MENU(m_menu), menuItem );
678 gtk_widget_show( menuItem );
679 m_items.Append( mitem );
680 }
681
682 void wxMenu::Append( wxMenuItem *item )
683 {
684 m_items.Append( item );
685
686 GtkWidget *menuItem = (GtkWidget*) NULL;
687
688 if (item->IsSeparator())
689 menuItem = gtk_menu_item_new();
690 else if (item->IsSubMenu())
691 menuItem = gtk_menu_item_new_with_label(item->GetText().mbc_str());
692 else
693 menuItem = item->IsCheckable() ? gtk_check_menu_item_new_with_label(item->GetText().mbc_str())
694 : gtk_menu_item_new_with_label(item->GetText().mbc_str());
695
696 if (!item->IsSeparator())
697 {
698 gtk_signal_connect( GTK_OBJECT(menuItem), "select",
699 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
700 (gpointer*)this );
701
702 gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
703 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
704 (gpointer*)this );
705
706 if (!item->IsSubMenu())
707 {
708 gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
709 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
710 (gpointer*)this );
711 }
712 }
713
714 gtk_menu_append( GTK_MENU(m_menu), menuItem );
715 gtk_widget_show( menuItem );
716 item->SetMenuItem(menuItem);
717 }
718
719 int wxMenu::FindItem( const wxString itemString ) const
720 {
721 wxString s = _T("");
722 for ( const wxChar *pc = itemString; *pc != _T('\0'); pc++ )
723 {
724 if (*pc == _T('&'))
725 {
726 pc++; /* skip it */
727 #if (GTK_MINOR_VERSION > 0)
728 s << _T('_');
729 #endif
730 }
731 s << *pc;
732 }
733
734 wxNode *node = m_items.First();
735 while (node)
736 {
737 wxMenuItem *item = (wxMenuItem*)node->Data();
738 if (item->GetText() == s)
739 {
740 return item->GetId();
741 }
742 node = node->Next();
743 }
744
745 return wxNOT_FOUND;
746 }
747
748 void wxMenu::Enable( int id, bool enable )
749 {
750 wxMenuItem *item = FindItem(id);
751
752 wxCHECK_RET( item, _T("wxMenu::Enable: no such item") );
753
754 item->Enable(enable);
755 }
756
757 bool wxMenu::IsEnabled( int id ) const
758 {
759 wxMenuItem *item = FindItem(id);
760
761 wxCHECK_MSG( item, FALSE, _T("wxMenu::IsEnabled: no such item") );
762
763 return item->IsEnabled();
764 }
765
766 void wxMenu::Check( int id, bool enable )
767 {
768 wxMenuItem *item = FindItem(id);
769
770 wxCHECK_RET( item, _T("wxMenu::Check: no such item") );
771
772 item->Check(enable);
773 }
774
775 bool wxMenu::IsChecked( int id ) const
776 {
777 wxMenuItem *item = FindItem(id);
778
779 wxCHECK_MSG( item, FALSE, _T("wxMenu::IsChecked: no such item") );
780
781 return item->IsChecked();
782 }
783
784 void wxMenu::SetLabel( int id, const wxString &label )
785 {
786 wxMenuItem *item = FindItem(id);
787
788 wxCHECK_RET( item, _T("wxMenu::SetLabel: no such item") );
789
790 item->SetText(label);
791 }
792
793 wxString wxMenu::GetLabel( int id ) const
794 {
795 wxMenuItem *item = FindItem(id);
796
797 wxCHECK_MSG( item, _T(""), _T("wxMenu::GetLabel: no such item") );
798
799 return item->GetText();
800 }
801
802 void wxMenu::SetHelpString( int id, const wxString& helpString )
803 {
804 wxMenuItem *item = FindItem(id);
805
806 wxCHECK_RET( item, _T("wxMenu::SetHelpString: no such item") );
807
808 item->SetHelp( helpString );
809 }
810
811 wxString wxMenu::GetHelpString( int id ) const
812 {
813 wxMenuItem *item = FindItem(id);
814
815 wxCHECK_MSG( item, _T(""), _T("wxMenu::GetHelpString: no such item") );
816
817 return item->GetHelp();
818 }
819
820 int wxMenu::FindMenuIdByMenuItem( GtkWidget *menuItem ) const
821 {
822 wxNode *node = m_items.First();
823 while (node)
824 {
825 wxMenuItem *item = (wxMenuItem*)node->Data();
826 if (item->GetMenuItem() == menuItem)
827 return item->GetId();
828 node = node->Next();
829 }
830
831 return wxNOT_FOUND;
832 }
833
834 wxMenuItem *wxMenu::FindItem(int id) const
835 {
836 wxNode *node = m_items.First();
837 while (node)
838 {
839 wxMenuItem *item = (wxMenuItem*)node->Data();
840 if (item->GetId() == id)
841 {
842 return item;
843 }
844 node = node->Next();
845 }
846
847 /* Not finding anything here can be correct
848 * when search the entire menu system for
849 * an entry -> no error message. */
850
851 return (wxMenuItem *) NULL;
852 }
853
854 void wxMenu::SetInvokingWindow( wxWindow *win )
855 {
856 m_invokingWindow = win;
857 }
858
859 wxWindow *wxMenu::GetInvokingWindow()
860 {
861 return m_invokingWindow;
862 }
863
864 // Update a menu and all submenus recursively. source is the object that has
865 // the update event handlers defined for it. If NULL, the menu or associated
866 // window will be used.
867 void wxMenu::UpdateUI(wxEvtHandler* source)
868 {
869 if (!source && GetInvokingWindow())
870 source = GetInvokingWindow()->GetEventHandler();
871 if (!source)
872 source = GetEventHandler();
873 if (!source)
874 source = this;
875
876 wxNode* node = GetItems().First();
877 while (node)
878 {
879 wxMenuItem* item = (wxMenuItem*) node->Data();
880 if ( !item->IsSeparator() )
881 {
882 wxWindowID id = item->GetId();
883 wxUpdateUIEvent event(id);
884 event.SetEventObject( source );
885
886 if (source->ProcessEvent(event))
887 {
888 if (event.GetSetText())
889 SetLabel(id, event.GetText());
890 if (event.GetSetChecked())
891 Check(id, event.GetChecked());
892 if (event.GetSetEnabled())
893 Enable(id, event.GetEnabled());
894 }
895
896 if (item->GetSubMenu())
897 item->GetSubMenu()->UpdateUI(source);
898 }
899 node = node->Next();
900 }
901 }
902