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