1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "menu.h"
12 #pragma implementation "menuitem.h"
23 //-----------------------------------------------------------------------------
25 //-----------------------------------------------------------------------------
27 extern void wxapp_install_idle_handler();
30 //-----------------------------------------------------------------------------
32 //-----------------------------------------------------------------------------
34 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
,wxWindow
)
36 wxMenuBar::wxMenuBar( long style
)
38 /* the parent window is known after wxFrame::SetMenu() */
41 PreCreation( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, style
, "menu" );
43 m_menus
.DeleteContents( TRUE
);
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>" );
51 m_menubar
= gtk_menu_bar_new();
54 if (style
& wxMB_DOCKABLE
)
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
) );
62 m_widget
= GTK_WIDGET(m_menubar
);
68 wxMenuBar::wxMenuBar()
70 /* the parent window is known after wxFrame::SetMenu() */
73 PreCreation( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, 0, "menu" );
75 m_menus
.DeleteContents( TRUE
);
77 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
78 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
79 m_accel
= gtk_accel_group_new();
80 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel
);
81 m_menubar
= gtk_item_factory_get_widget( m_factory
, "<main>" );
83 m_menubar
= gtk_menu_bar_new();
86 m_widget
= GTK_WIDGET(m_menubar
);
91 wxMenuBar::~wxMenuBar()
93 // how to destroy a GtkItemFactory ?
96 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
98 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
100 #if (GTK_MINOR_VERSION > 0)
101 wxWindow
*top_frame
= win
;
102 while (top_frame
->GetParent()) top_frame
= top_frame
->GetParent();
104 /* support for native hot keys */
105 gtk_accel_group_detach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
108 wxNode
*node
= menu
->GetItems().First();
111 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
112 if (menuitem
->IsSubMenu())
113 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu(), win
);
118 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
120 menu
->SetInvokingWindow( win
);
122 #if (GTK_MINOR_VERSION > 0)
123 wxWindow
*top_frame
= win
;
124 while (top_frame
->GetParent())
125 top_frame
= top_frame
->GetParent();
127 /* support for native hot keys */
128 gtk_accel_group_attach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
131 wxNode
*node
= menu
->GetItems().First();
134 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
135 if (menuitem
->IsSubMenu())
136 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu(), win
);
141 void wxMenuBar::SetInvokingWindow( wxWindow
*win
)
143 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
144 wxWindow
*top_frame
= win
;
145 while (top_frame
->GetParent())
146 top_frame
= top_frame
->GetParent();
148 /* support for native key accelerators indicated by underscroes */
149 gtk_accel_group_attach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
152 wxNode
*node
= m_menus
.First();
155 wxMenu
*menu
= (wxMenu
*)node
->Data();
156 wxMenubarSetInvokingWindow( menu
, win
);
161 void wxMenuBar::UnsetInvokingWindow( wxWindow
*win
)
163 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
164 wxWindow
*top_frame
= win
;
165 while (top_frame
->GetParent())
166 top_frame
= top_frame
->GetParent();
168 /* support for native key accelerators indicated by underscroes */
169 gtk_accel_group_detach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
172 wxNode
*node
= m_menus
.First();
175 wxMenu
*menu
= (wxMenu
*)node
->Data();
176 wxMenubarUnsetInvokingWindow( menu
, win
);
181 void wxMenuBar::Append( wxMenu
*menu
, const wxString
&title
)
183 m_menus
.Append( menu
);
185 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
187 for ( const wxChar
*pc
= title
; *pc
!= _T('\0'); pc
++ )
191 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
203 /* this doesn't have much effect right now */
204 menu
->SetTitle( str
);
206 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
207 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
209 /* local buffer in multibyte form */
212 strcat( buf
, str
.mb_str() );
214 GtkItemFactoryEntry entry
;
216 entry
.accelerator
= (gchar
*) NULL
;
217 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
218 entry
.callback_action
= 0;
219 entry
.item_type
= "<Branch>";
221 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
223 /* in order to get the pointer to the item we need the item text _without_ underscores */
224 wxString tmp
= _T("<main>/");
225 for ( const wxChar
*pc
= str
; *pc
!= _T('\0'); pc
++ )
227 if (*pc
== _T('_')) pc
++; /* skip it */
231 menu
->m_owner
= gtk_item_factory_get_item( m_factory
, tmp
.mb_str() );
233 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
237 menu
->m_owner
= gtk_menu_item_new_with_label( str
.mb_str() );
238 gtk_widget_show( menu
->m_owner
);
239 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
241 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), menu
->m_owner
);
246 static int FindMenuItemRecursive( const wxMenu
*menu
, const wxString
&menuString
, const wxString
&itemString
)
248 if (menu
->GetTitle() == menuString
)
250 int res
= menu
->FindItem( itemString
);
251 if (res
!= wxNOT_FOUND
)
255 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
258 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
259 if (item
->IsSubMenu())
260 return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
);
268 wxMenuItem
*wxMenuBar::FindItemForId(int itemId
, wxMenu
**menuForItem
) const
272 // TODO return the pointer to the menu
277 return FindItem(itemId
);
280 int wxMenuBar::FindMenuItem( const wxString
&menuString
, const wxString
&itemString
) const
282 wxNode
*node
= m_menus
.First();
285 wxMenu
*menu
= (wxMenu
*)node
->Data();
286 int res
= FindMenuItemRecursive( menu
, menuString
, itemString
);
287 if (res
!= -1) return res
;
293 // Find a wxMenuItem using its id. Recurses down into sub-menus
294 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
)
296 wxMenuItem
* result
= menu
->FindItem(id
);
298 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
299 while ( node
&& result
== NULL
)
301 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
302 if (item
->IsSubMenu())
304 result
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id
);
312 wxMenuItem
* wxMenuBar::FindItem( int id
) const
314 wxMenuItem
* result
= 0;
315 wxNode
*node
= m_menus
.First();
316 while (node
&& result
== 0)
318 wxMenu
*menu
= (wxMenu
*)node
->Data();
319 result
= FindMenuItemByIdRecursive( menu
, id
);
326 void wxMenuBar::Check( int id
, bool check
)
328 wxMenuItem
* item
= FindMenuItemById( id
);
330 wxCHECK_RET( item
, _T("wxMenuBar::Check: no such item") );
335 bool wxMenuBar::IsChecked( int id
) const
337 wxMenuItem
* item
= FindMenuItemById( id
);
339 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsChecked: no such item") );
341 return item
->IsChecked();
344 void wxMenuBar::Enable( int id
, bool enable
)
346 wxMenuItem
* item
= FindMenuItemById( id
);
348 wxCHECK_RET( item
, _T("wxMenuBar::Enable: no such item") );
350 item
->Enable(enable
);
353 bool wxMenuBar::IsEnabled( int id
) const
355 wxMenuItem
* item
= FindMenuItemById( id
);
357 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsEnabled: no such item") );
359 return item
->IsEnabled();
362 wxString
wxMenuBar::GetLabel( int id
) const
364 wxMenuItem
* item
= FindMenuItemById( id
);
366 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetLabel: no such item") );
368 return item
->GetText();
371 void wxMenuBar::SetLabel( int id
, const wxString
&label
)
373 wxMenuItem
* item
= FindMenuItemById( id
);
375 wxCHECK_RET( item
, _T("wxMenuBar::SetLabel: no such item") );
377 item
->SetText( label
);
380 void wxMenuBar::EnableTop( int pos
, bool flag
)
382 wxNode
*node
= m_menus
.Nth( pos
);
384 wxCHECK_RET( node
, _T("menu not found") );
386 wxMenu
* menu
= (wxMenu
*)node
->Data();
389 gtk_widget_set_sensitive( menu
->m_owner
, flag
);
392 wxString
wxMenuBar::GetLabelTop( int pos
) const
394 wxNode
*node
= m_menus
.Nth( pos
);
396 wxCHECK_MSG( node
, _T("invalid"), _T("menu not found") );
398 wxMenu
* menu
= (wxMenu
*)node
->Data();
400 return menu
->GetTitle();
403 void wxMenuBar::SetLabelTop( int pos
, const wxString
& label
)
405 wxNode
*node
= m_menus
.Nth( pos
);
407 wxCHECK_RET( node
, _T("menu not found") );
409 wxMenu
* menu
= (wxMenu
*)node
->Data();
411 menu
->SetTitle( label
);
414 void wxMenuBar::SetHelpString( int id
, const wxString
& helpString
)
416 wxMenuItem
* item
= FindMenuItemById( id
);
418 wxCHECK_RET( item
, _T("wxMenuBar::SetHelpString: no such item") );
420 item
->SetHelp( helpString
);
423 wxString
wxMenuBar::GetHelpString( int id
) const
425 wxMenuItem
* item
= FindMenuItemById( id
);
427 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetHelpString: no such item") );
429 return item
->GetHelp();
432 //-----------------------------------------------------------------------------
434 //-----------------------------------------------------------------------------
436 static void gtk_menu_clicked_callback( GtkWidget
*widget
, wxMenu
*menu
)
438 if (g_isIdle
) wxapp_install_idle_handler();
440 int id
= menu
->FindMenuIdByMenuItem(widget
);
442 /* should find it for normal (not popup) menu */
443 wxASSERT( (id
!= -1) || (menu
->GetInvokingWindow() != NULL
) );
445 if (!menu
->IsEnabled(id
))
448 wxMenuItem
* item
= menu
->FindItem( id
);
449 wxCHECK_RET( item
, _T("error in menu item callback") );
451 if (item
->IsCheckable())
453 if (item
->GetCheckedFlag() == item
->IsChecked())
455 /* the menu item has been checked by calling wxMenuItem->Check() */
460 /* the user pressed on the menu item -> report */
461 item
->SetCheckedFlag(item
->IsChecked()); /* make consistent again */
465 wxCommandEvent
event( wxEVT_COMMAND_MENU_SELECTED
, id
);
466 event
.SetEventObject( menu
);
469 if (menu
->GetCallback())
471 (void) (*(menu
->GetCallback())) (*menu
, event
);
475 if (menu
->GetEventHandler()->ProcessEvent(event
))
478 wxWindow
*win
= menu
->GetInvokingWindow();
480 win
->GetEventHandler()->ProcessEvent( event
);
483 //-----------------------------------------------------------------------------
485 //-----------------------------------------------------------------------------
487 static void gtk_menu_hilight_callback( GtkWidget
*widget
, wxMenu
*menu
)
489 if (g_isIdle
) wxapp_install_idle_handler();
491 int id
= menu
->FindMenuIdByMenuItem(widget
);
493 wxASSERT( id
!= -1 ); // should find it!
495 if (!menu
->IsEnabled(id
))
498 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, id
);
499 event
.SetEventObject( menu
);
501 /* wxMSW doesn't call callback here either
503 if (menu->m_callback)
505 (void) (*(menu->m_callback)) (*menu, event);
510 if (menu
->GetEventHandler()->ProcessEvent(event
))
513 wxWindow
*win
= menu
->GetInvokingWindow();
514 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
517 //-----------------------------------------------------------------------------
519 //-----------------------------------------------------------------------------
521 static void gtk_menu_nolight_callback( GtkWidget
*widget
, wxMenu
*menu
)
523 if (g_isIdle
) wxapp_install_idle_handler();
525 int id
= menu
->FindMenuIdByMenuItem(widget
);
527 wxASSERT( id
!= -1 ); // should find it!
529 if (!menu
->IsEnabled(id
))
532 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, -1 );
533 event
.SetEventObject( menu
);
535 if (menu
->GetEventHandler()->ProcessEvent(event
))
538 wxWindow
*win
= menu
->GetInvokingWindow();
540 win
->GetEventHandler()->ProcessEvent( event
);
543 //-----------------------------------------------------------------------------
545 //-----------------------------------------------------------------------------
547 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
,wxObject
)
549 wxMenuItem::wxMenuItem()
552 m_isCheckMenu
= FALSE
;
555 m_subMenu
= (wxMenu
*) NULL
;
556 m_menuItem
= (GtkWidget
*) NULL
;
559 // it's valid for this function to be called even if m_menuItem == NULL
560 void wxMenuItem::SetName( const wxString
& str
)
562 /* '\t' is the deliminator indicating a hot key */
564 const wxChar
*pc
= str
;
565 for (; (*pc
!= _T('\0')) && (*pc
!= _T('\t')); pc
++ )
569 #if (GTK_MINOR_VERSION > 0)
572 if (*pc
== _T('/')) /* we have to filter out slashes ... */
574 m_text
<< _T('\\'); /* ... and replace them with back slashes */
581 /* only GTK 1.2 knows about hot keys */
583 #if (GTK_MINOR_VERSION > 0)
593 GtkLabel
*label
= GTK_LABEL( GTK_BIN(m_menuItem
)->child
);
594 gtk_label_set( label
, m_text
.mb_str());
598 void wxMenuItem::Check( bool check
)
600 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
602 wxCHECK_RET( IsCheckable(), _T("Can't check uncheckable item!") )
604 if (check
== m_isChecked
) return;
607 gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check
);
610 void wxMenuItem::Enable( bool enable
)
612 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
614 gtk_widget_set_sensitive( m_menuItem
, enable
);
615 m_isEnabled
= enable
;
618 bool wxMenuItem::IsChecked() const
620 wxCHECK_MSG( m_menuItem
, FALSE
, _T("invalid menu item") );
622 wxCHECK( IsCheckable(), FALSE
); // can't get state of uncheckable item!
624 bool bIsChecked
= ((GtkCheckMenuItem
*)m_menuItem
)->active
!= 0;
629 //-----------------------------------------------------------------------------
631 //-----------------------------------------------------------------------------
633 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
)
635 wxMenu::wxMenu( const wxString
& title
, const wxFunction func
)
638 m_items
.DeleteContents( TRUE
);
639 m_invokingWindow
= (wxWindow
*) NULL
;
641 #if (GTK_MINOR_VERSION > 0)
642 m_accel
= gtk_accel_group_new();
643 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU
, "<main>", m_accel
);
644 m_menu
= gtk_item_factory_get_widget( m_factory
, "<main>" );
646 m_menu
= gtk_menu_new(); // Do not show!
650 m_eventHandler
= this;
651 m_clientData
= (void*) NULL
;
653 if (m_title
.IsNull()) m_title
= _T("");
654 if (m_title
!= _T(""))
660 m_owner
= (GtkWidget
*) NULL
;
665 /* how do we delete an item-factory ? */
668 void wxMenu::SetTitle( const wxString
& title
)
670 // TODO Waiting for something better
674 const wxString
wxMenu::GetTitle() const
679 void wxMenu::AppendSeparator()
681 wxMenuItem
*mitem
= new wxMenuItem();
682 mitem
->SetId(ID_SEPARATOR
);
684 #if (GTK_MINOR_VERSION > 0)
685 GtkItemFactoryEntry entry
;
687 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
688 entry
.callback_action
= 0;
689 entry
.item_type
= "<Separator>";
690 entry
.accelerator
= (gchar
*) NULL
;
692 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
694 /* this will be wrong for more than one separator. do we care? */
695 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, "<main>/sep" );
697 GtkWidget
*menuItem
= gtk_menu_item_new();
698 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
699 gtk_widget_show( menuItem
);
702 mitem
->SetMenuItem(menuItem
);
703 m_items
.Append( mitem
);
706 static char* GetHotKey( const wxString
&hotkey
, char *hotbuf
)
708 if (hotkey
.IsEmpty()) return (char*) NULL
;
712 case _T('a'): /* Alt */
714 case _T('m'): /* Meta */
717 strcpy( hotbuf
, "<alt>" );
718 wxString last
= hotkey
.Right(1);
719 strcat( hotbuf
, last
.mb_str() );
722 case _T('c'): /* Ctrl */
724 case _T('s'): /* Strg, yeah man, I'm German */
727 strcpy( hotbuf
, "<control>" );
728 wxString last
= hotkey
.Right(1);
729 strcat( hotbuf
, last
.mb_str() );
732 case _T('F'): /* function keys */
734 strcpy( hotbuf
, hotkey
.mb_str() );
744 void wxMenu::Append( int id
, const wxString
&item
, const wxString
&helpStr
, bool checkable
)
746 wxMenuItem
*mitem
= new wxMenuItem();
748 mitem
->SetText(item
);
749 mitem
->SetHelp(helpStr
);
750 mitem
->SetCheckable(checkable
);
752 #if (GTK_MINOR_VERSION > 0)
753 /* text has "_" instead of "&" after mitem->SetText() */
754 wxString
text( mitem
->GetText() );
756 /* local buffer in multibyte form */
759 strcat( buf
, text
.mb_str() );
761 GtkItemFactoryEntry entry
;
763 entry
.callback
= (GtkItemFactoryCallback
) gtk_menu_clicked_callback
;
764 entry
.callback_action
= 0;
766 entry
.item_type
= "<CheckItem>";
768 entry
.item_type
= "<Item>";
771 entry
.accelerator
= GetHotKey( mitem
->GetHotKey(), hotbuf
);
773 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
775 /* in order to get the pointer to the item we need the item text _without_ underscores */
776 wxString s
= _T("<main>/");
777 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
779 if (*pc
== _T('_')) pc
++; /* skip it */
783 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, s
.mb_str() );
787 GtkWidget
*menuItem
= checkable
? gtk_check_menu_item_new_with_label( mitem
->GetText().mb_str() )
788 : gtk_menu_item_new_with_label( mitem
->GetText().mb_str() );
790 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
791 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
794 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
795 gtk_widget_show( menuItem
);
799 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
800 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
803 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
804 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
807 mitem
->SetMenuItem(menuItem
);
809 m_items
.Append( mitem
);
812 void wxMenu::Append( int id
, const wxString
&item
, wxMenu
*subMenu
, const wxString
&helpStr
)
814 wxMenuItem
*mitem
= new wxMenuItem();
816 mitem
->SetText(item
);
817 mitem
->SetHelp(helpStr
);
819 #if (GTK_MINOR_VERSION > 0)
820 /* text has "_" instead of "&" after mitem->SetText() */
821 wxString
text( mitem
->GetText() );
823 /* local buffer in multibyte form */
826 strcat( buf
, text
.mb_str() );
828 GtkItemFactoryEntry entry
;
830 entry
.callback
= (GtkItemFactoryCallback
) 0;
831 entry
.callback_action
= 0;
832 entry
.item_type
= "<Branch>";
834 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
836 /* in order to get the pointer to the item we need the item text _without_ underscores */
837 wxString s
= _T("<main>/");
838 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
840 if (*pc
== _T('_')) pc
++; /* skip it */
844 GtkWidget
*menuItem
= gtk_item_factory_get_item( m_factory
, s
.mb_str() );
848 GtkWidget
*menuItem
= gtk_menu_item_new_with_label(mitem
->GetText().mbc_str());
850 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
851 gtk_widget_show( menuItem
);
855 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
856 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
859 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
860 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
863 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), subMenu
->m_menu
);
865 mitem
->SetMenuItem(menuItem
);
866 mitem
->SetSubMenu(subMenu
);
868 m_items
.Append( mitem
);
871 void wxMenu::Append( wxMenuItem
*item
)
873 m_items
.Append( item
);
875 GtkWidget
*menuItem
= (GtkWidget
*) NULL
;
877 if (item
->IsSeparator())
878 menuItem
= gtk_menu_item_new();
879 else if (item
->IsSubMenu())
880 menuItem
= gtk_menu_item_new_with_label(item
->GetText().mbc_str());
882 menuItem
= item
->IsCheckable() ? gtk_check_menu_item_new_with_label(item
->GetText().mbc_str())
883 : gtk_menu_item_new_with_label(item
->GetText().mbc_str());
885 if (!item
->IsSeparator())
887 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
888 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
891 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
892 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
895 if (!item
->IsSubMenu())
897 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
898 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
903 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
904 gtk_widget_show( menuItem
);
905 item
->SetMenuItem(menuItem
);
908 int wxMenu::FindItem( const wxString itemString
) const
911 for ( const wxChar
*pc
= itemString
; *pc
!= _T('\0'); pc
++ )
916 #if (GTK_MINOR_VERSION > 0)
923 wxNode
*node
= m_items
.First();
926 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
927 if (item
->GetText() == s
)
929 return item
->GetId();
937 void wxMenu::Enable( int id
, bool enable
)
939 wxMenuItem
*item
= FindItem(id
);
941 wxCHECK_RET( item
, _T("wxMenu::Enable: no such item") );
943 item
->Enable(enable
);
946 bool wxMenu::IsEnabled( int id
) const
948 wxMenuItem
*item
= FindItem(id
);
950 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsEnabled: no such item") );
952 return item
->IsEnabled();
955 void wxMenu::Check( int id
, bool enable
)
957 wxMenuItem
*item
= FindItem(id
);
959 wxCHECK_RET( item
, _T("wxMenu::Check: no such item") );
964 bool wxMenu::IsChecked( int id
) const
966 wxMenuItem
*item
= FindItem(id
);
968 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsChecked: no such item") );
970 return item
->IsChecked();
973 void wxMenu::SetLabel( int id
, const wxString
&label
)
975 wxMenuItem
*item
= FindItem(id
);
977 wxCHECK_RET( item
, _T("wxMenu::SetLabel: no such item") );
979 item
->SetText(label
);
982 wxString
wxMenu::GetLabel( int id
) const
984 wxMenuItem
*item
= FindItem(id
);
986 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetLabel: no such item") );
988 return item
->GetText();
991 void wxMenu::SetHelpString( int id
, const wxString
& helpString
)
993 wxMenuItem
*item
= FindItem(id
);
995 wxCHECK_RET( item
, _T("wxMenu::SetHelpString: no such item") );
997 item
->SetHelp( helpString
);
1000 wxString
wxMenu::GetHelpString( int id
) const
1002 wxMenuItem
*item
= FindItem(id
);
1004 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetHelpString: no such item") );
1006 return item
->GetHelp();
1009 int wxMenu::FindMenuIdByMenuItem( GtkWidget
*menuItem
) const
1011 wxNode
*node
= m_items
.First();
1014 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1015 if (item
->GetMenuItem() == menuItem
)
1016 return item
->GetId();
1017 node
= node
->Next();
1023 wxMenuItem
*wxMenu::FindItem(int id
) const
1025 wxNode
*node
= m_items
.First();
1028 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1029 if (item
->GetId() == id
)
1033 node
= node
->Next();
1036 /* Not finding anything here can be correct
1037 * when search the entire menu system for
1038 * an entry -> no error message. */
1040 return (wxMenuItem
*) NULL
;
1043 void wxMenu::SetInvokingWindow( wxWindow
*win
)
1045 m_invokingWindow
= win
;
1048 wxWindow
*wxMenu::GetInvokingWindow()
1050 return m_invokingWindow
;
1053 // Update a menu and all submenus recursively. source is the object that has
1054 // the update event handlers defined for it. If NULL, the menu or associated
1055 // window will be used.
1056 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1058 if (!source
&& GetInvokingWindow())
1059 source
= GetInvokingWindow()->GetEventHandler();
1061 source
= GetEventHandler();
1065 wxNode
* node
= GetItems().First();
1068 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1069 if ( !item
->IsSeparator() )
1071 wxWindowID id
= item
->GetId();
1072 wxUpdateUIEvent
event(id
);
1073 event
.SetEventObject( source
);
1075 if (source
->ProcessEvent(event
))
1077 if (event
.GetSetText())
1078 SetLabel(id
, event
.GetText());
1079 if (event
.GetSetChecked())
1080 Check(id
, event
.GetChecked());
1081 if (event
.GetSetEnabled())
1082 Enable(id
, event
.GetEnabled());
1085 if (item
->GetSubMenu())
1086 item
->GetSubMenu()->UpdateUI(source
);
1088 node
= node
->Next();