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 m_invokingWindow
= (wxWindow
*) NULL
;
43 if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize
) ||
44 !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, _T("menubar") ))
46 wxFAIL_MSG( _T("wxMenuBar creation failed") );
50 m_menus
.DeleteContents( TRUE
);
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>" );
58 m_menubar
= gtk_menu_bar_new();
61 if (style
& wxMB_DOCKABLE
)
63 m_widget
= gtk_handle_box_new();
64 gtk_container_add( GTK_CONTAINER(m_widget
), GTK_WIDGET(m_menubar
) );
65 gtk_widget_show( GTK_WIDGET(m_menubar
) );
69 m_widget
= GTK_WIDGET(m_menubar
);
75 wxMenuBar::wxMenuBar()
77 /* the parent window is known after wxFrame::SetMenu() */
80 m_invokingWindow
= (wxWindow
*) NULL
;
82 if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize
) ||
83 !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, 0, wxDefaultValidator
, _T("menubar") ))
85 wxFAIL_MSG( _T("wxMenuBar creation failed") );
89 m_menus
.DeleteContents( TRUE
);
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>" );
97 m_menubar
= gtk_menu_bar_new();
100 m_widget
= GTK_WIDGET(m_menubar
);
105 wxMenuBar::~wxMenuBar()
107 // how to destroy a GtkItemFactory ?
110 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
112 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
114 #if (GTK_MINOR_VERSION > 0)
115 wxWindow
*top_frame
= win
;
116 while (top_frame
->GetParent()) top_frame
= top_frame
->GetParent();
118 /* support for native hot keys */
119 gtk_accel_group_detach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
122 wxNode
*node
= menu
->GetItems().First();
125 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
126 if (menuitem
->IsSubMenu())
127 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu(), win
);
132 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
134 menu
->SetInvokingWindow( win
);
136 #if (GTK_MINOR_VERSION > 0)
137 wxWindow
*top_frame
= win
;
138 while (top_frame
->GetParent())
139 top_frame
= top_frame
->GetParent();
141 /* support for native hot keys */
142 gtk_accel_group_attach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
145 wxNode
*node
= menu
->GetItems().First();
148 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
149 if (menuitem
->IsSubMenu())
150 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu(), win
);
155 void wxMenuBar::SetInvokingWindow( wxWindow
*win
)
157 m_invokingWindow
= win
;
158 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
159 wxWindow
*top_frame
= win
;
160 while (top_frame
->GetParent())
161 top_frame
= top_frame
->GetParent();
163 /* support for native key accelerators indicated by underscroes */
164 gtk_accel_group_attach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
167 wxNode
*node
= m_menus
.First();
170 wxMenu
*menu
= (wxMenu
*)node
->Data();
171 wxMenubarSetInvokingWindow( menu
, win
);
176 void wxMenuBar::UnsetInvokingWindow( wxWindow
*win
)
178 m_invokingWindow
= (wxWindow
*) NULL
;
179 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
180 wxWindow
*top_frame
= win
;
181 while (top_frame
->GetParent())
182 top_frame
= top_frame
->GetParent();
184 /* support for native key accelerators indicated by underscroes */
185 gtk_accel_group_detach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
188 wxNode
*node
= m_menus
.First();
191 wxMenu
*menu
= (wxMenu
*)node
->Data();
192 wxMenubarUnsetInvokingWindow( menu
, win
);
197 void wxMenuBar::Append( wxMenu
*menu
, const wxString
&title
)
199 m_menus
.Append( menu
);
203 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
205 for ( pc
= title
; *pc
!= _T('\0'); pc
++ )
209 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
221 /* this doesn't have much effect right now */
222 menu
->SetTitle( str
);
224 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
225 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
227 /* local buffer in multibyte form */
229 buf
<< _T('/') << str
.c_str();
231 char *cbuf
= new char[buf
.Length()+1];
232 strcpy(cbuf
, buf
.mbc_str());
234 GtkItemFactoryEntry entry
;
235 entry
.path
= (gchar
*)cbuf
; // const_cast
236 entry
.accelerator
= (gchar
*) NULL
;
237 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
238 entry
.callback_action
= 0;
239 entry
.item_type
= "<Branch>";
241 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
242 /* in order to get the pointer to the item we need the item text _without_ underscores */
243 wxString tmp
= _T("<main>/");
244 for ( pc
= str
; *pc
!= _T('\0'); pc
++ )
246 if (*pc
== _T('_')) pc
++; /* skip it */
249 menu
->m_owner
= gtk_item_factory_get_item( m_factory
, tmp
.mb_str() );
250 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
254 menu
->m_owner
= gtk_menu_item_new_with_label( str
.mb_str() );
255 gtk_widget_show( menu
->m_owner
);
256 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
258 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), menu
->m_owner
);
262 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
263 // adding menu later on.
264 if (m_invokingWindow
)
265 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
268 static int FindMenuItemRecursive( const wxMenu
*menu
, const wxString
&menuString
, const wxString
&itemString
)
270 if (menu
->GetTitle() == menuString
)
272 int res
= menu
->FindItem( itemString
);
273 if (res
!= wxNOT_FOUND
)
277 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
280 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
281 if (item
->IsSubMenu())
282 return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
);
290 wxMenuItem
*wxMenuBar::FindItemForId(int itemId
, wxMenu
**menuForItem
) const
294 // TODO return the pointer to the menu
299 return FindItem(itemId
);
302 int wxMenuBar::FindMenuItem( const wxString
&menuString
, const wxString
&itemString
) const
304 wxNode
*node
= m_menus
.First();
307 wxMenu
*menu
= (wxMenu
*)node
->Data();
308 int res
= FindMenuItemRecursive( menu
, menuString
, itemString
);
309 if (res
!= -1) return res
;
315 // Find a wxMenuItem using its id. Recurses down into sub-menus
316 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
)
318 wxMenuItem
* result
= menu
->FindItem(id
);
320 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
321 while ( node
&& result
== NULL
)
323 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
324 if (item
->IsSubMenu())
326 result
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id
);
334 wxMenuItem
* wxMenuBar::FindItem( int id
) const
336 wxMenuItem
* result
= 0;
337 wxNode
*node
= m_menus
.First();
338 while (node
&& result
== 0)
340 wxMenu
*menu
= (wxMenu
*)node
->Data();
341 result
= FindMenuItemByIdRecursive( menu
, id
);
348 void wxMenuBar::Check( int id
, bool check
)
350 wxMenuItem
* item
= FindMenuItemById( id
);
352 wxCHECK_RET( item
, _T("wxMenuBar::Check: no such item") );
357 bool wxMenuBar::IsChecked( int id
) const
359 wxMenuItem
* item
= FindMenuItemById( id
);
361 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsChecked: no such item") );
363 return item
->IsChecked();
366 void wxMenuBar::Enable( int id
, bool enable
)
368 wxMenuItem
* item
= FindMenuItemById( id
);
370 wxCHECK_RET( item
, _T("wxMenuBar::Enable: no such item") );
372 item
->Enable(enable
);
375 bool wxMenuBar::IsEnabled( int id
) const
377 wxMenuItem
* item
= FindMenuItemById( id
);
379 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsEnabled: no such item") );
381 return item
->IsEnabled();
384 wxString
wxMenuBar::GetLabel( int id
) const
386 wxMenuItem
* item
= FindMenuItemById( id
);
388 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetLabel: no such item") );
390 return item
->GetText();
393 void wxMenuBar::SetLabel( int id
, const wxString
&label
)
395 wxMenuItem
* item
= FindMenuItemById( id
);
397 wxCHECK_RET( item
, _T("wxMenuBar::SetLabel: no such item") );
399 item
->SetText( label
);
402 void wxMenuBar::EnableTop( int pos
, bool flag
)
404 wxNode
*node
= m_menus
.Nth( pos
);
406 wxCHECK_RET( node
, _T("menu not found") );
408 wxMenu
* menu
= (wxMenu
*)node
->Data();
411 gtk_widget_set_sensitive( menu
->m_owner
, flag
);
414 wxString
wxMenuBar::GetLabelTop( int pos
) const
416 wxNode
*node
= m_menus
.Nth( pos
);
418 wxCHECK_MSG( node
, _T("invalid"), _T("menu not found") );
420 wxMenu
* menu
= (wxMenu
*)node
->Data();
422 return menu
->GetTitle();
425 void wxMenuBar::SetLabelTop( int pos
, const wxString
& label
)
427 wxNode
*node
= m_menus
.Nth( pos
);
429 wxCHECK_RET( node
, _T("menu not found") );
431 wxMenu
* menu
= (wxMenu
*)node
->Data();
433 menu
->SetTitle( label
);
436 void wxMenuBar::SetHelpString( int id
, const wxString
& helpString
)
438 wxMenuItem
* item
= FindMenuItemById( id
);
440 wxCHECK_RET( item
, _T("wxMenuBar::SetHelpString: no such item") );
442 item
->SetHelp( helpString
);
445 wxString
wxMenuBar::GetHelpString( int id
) const
447 wxMenuItem
* item
= FindMenuItemById( id
);
449 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetHelpString: no such item") );
451 return item
->GetHelp();
454 //-----------------------------------------------------------------------------
456 //-----------------------------------------------------------------------------
458 static void gtk_menu_clicked_callback( GtkWidget
*widget
, wxMenu
*menu
)
460 if (g_isIdle
) wxapp_install_idle_handler();
462 int id
= menu
->FindMenuIdByMenuItem(widget
);
464 /* should find it for normal (not popup) menu */
465 wxASSERT( (id
!= -1) || (menu
->GetInvokingWindow() != NULL
) );
467 if (!menu
->IsEnabled(id
))
470 wxMenuItem
* item
= menu
->FindItem( id
);
471 wxCHECK_RET( item
, _T("error in menu item callback") );
473 if (item
->IsCheckable())
475 if (item
->GetCheckedFlag() == item
->IsChecked())
477 /* the menu item has been checked by calling wxMenuItem->Check() */
482 /* the user pressed on the menu item -> report */
483 item
->SetCheckedFlag(item
->IsChecked()); /* make consistent again */
487 wxCommandEvent
event( wxEVT_COMMAND_MENU_SELECTED
, id
);
488 event
.SetEventObject( menu
);
491 if (menu
->GetCallback())
493 (void) (*(menu
->GetCallback())) (*menu
, event
);
497 if (menu
->GetEventHandler()->ProcessEvent(event
))
500 wxWindow
*win
= menu
->GetInvokingWindow();
502 win
->GetEventHandler()->ProcessEvent( event
);
505 //-----------------------------------------------------------------------------
507 //-----------------------------------------------------------------------------
509 static void gtk_menu_hilight_callback( GtkWidget
*widget
, wxMenu
*menu
)
511 if (g_isIdle
) wxapp_install_idle_handler();
513 int id
= menu
->FindMenuIdByMenuItem(widget
);
515 wxASSERT( id
!= -1 ); // should find it!
517 if (!menu
->IsEnabled(id
))
520 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, id
);
521 event
.SetEventObject( menu
);
523 if (menu
->GetEventHandler()->ProcessEvent(event
))
526 wxWindow
*win
= menu
->GetInvokingWindow();
527 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
530 //-----------------------------------------------------------------------------
532 //-----------------------------------------------------------------------------
534 static void gtk_menu_nolight_callback( GtkWidget
*widget
, wxMenu
*menu
)
536 if (g_isIdle
) wxapp_install_idle_handler();
538 int id
= menu
->FindMenuIdByMenuItem(widget
);
540 wxASSERT( id
!= -1 ); // should find it!
542 if (!menu
->IsEnabled(id
))
545 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, -1 );
546 event
.SetEventObject( menu
);
548 if (menu
->GetEventHandler()->ProcessEvent(event
))
551 wxWindow
*win
= menu
->GetInvokingWindow();
553 win
->GetEventHandler()->ProcessEvent( event
);
556 //-----------------------------------------------------------------------------
558 //-----------------------------------------------------------------------------
560 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
,wxObject
)
562 wxMenuItem::wxMenuItem()
565 m_isCheckMenu
= FALSE
;
568 m_subMenu
= (wxMenu
*) NULL
;
569 m_menuItem
= (GtkWidget
*) NULL
;
572 // it's valid for this function to be called even if m_menuItem == NULL
573 void wxMenuItem::SetName( const wxString
& str
)
575 /* '\t' is the deliminator indicating a hot key */
577 const wxChar
*pc
= str
;
578 for (; (*pc
!= _T('\0')) && (*pc
!= _T('\t')); pc
++ )
582 #if (GTK_MINOR_VERSION > 0)
585 if (*pc
== _T('/')) /* we have to filter out slashes ... */
587 m_text
<< _T('\\'); /* ... and replace them with back slashes */
594 /* only GTK 1.2 knows about hot keys */
596 #if (GTK_MINOR_VERSION > 0)
606 GtkLabel
*label
= GTK_LABEL( GTK_BIN(m_menuItem
)->child
);
607 gtk_label_set( label
, m_text
.mb_str());
611 void wxMenuItem::Check( bool check
)
613 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
615 wxCHECK_RET( IsCheckable(), _T("Can't check uncheckable item!") )
617 if (check
== m_isChecked
) return;
620 gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check
);
623 void wxMenuItem::Enable( bool enable
)
625 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
627 gtk_widget_set_sensitive( m_menuItem
, enable
);
628 m_isEnabled
= enable
;
631 bool wxMenuItem::IsChecked() const
633 wxCHECK_MSG( m_menuItem
, FALSE
, _T("invalid menu item") );
635 wxCHECK( IsCheckable(), FALSE
); // can't get state of uncheckable item!
637 bool bIsChecked
= ((GtkCheckMenuItem
*)m_menuItem
)->active
!= 0;
642 //-----------------------------------------------------------------------------
644 //-----------------------------------------------------------------------------
646 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
)
649 wxMenu::Init( const wxString
& title
,
651 const wxFunction func
655 m_items
.DeleteContents( TRUE
);
656 m_invokingWindow
= (wxWindow
*) NULL
;
659 #if (GTK_MINOR_VERSION > 0)
660 m_accel
= gtk_accel_group_new();
661 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU
, "<main>", m_accel
);
662 m_menu
= gtk_item_factory_get_widget( m_factory
, "<main>" );
664 m_menu
= gtk_menu_new(); // Do not show!
669 m_eventHandler
= this;
670 m_clientData
= (void*) NULL
;
672 if (m_title
.IsNull()) m_title
= _T("");
673 if (m_title
!= _T(""))
679 m_owner
= (GtkWidget
*) NULL
;
681 #if (GTK_MINOR_VERSION > 0)
682 /* Tearoffs are entries, just like separators. So if we want this
683 menu to be a tear-off one, we just append a tearoff entry
685 if(m_style
& wxMENU_TEAROFF
)
687 GtkItemFactoryEntry entry
;
688 entry
.path
= "/tearoff";
689 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
690 entry
.callback_action
= 0;
691 entry
.item_type
= "<Tearoff>";
692 entry
.accelerator
= (gchar
*) NULL
;
693 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
694 //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
701 /* how do we delete an item-factory ? */
702 gtk_widget_destroy( m_menu
);
706 void wxMenu::SetTitle( const wxString
& title
)
708 // TODO Waiting for something better
712 const wxString
wxMenu::GetTitle() const
717 void wxMenu::AppendSeparator()
719 wxMenuItem
*mitem
= new wxMenuItem();
720 mitem
->SetId(ID_SEPARATOR
);
722 #if (GTK_MINOR_VERSION > 0)
723 GtkItemFactoryEntry entry
;
725 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
726 entry
.callback_action
= 0;
727 entry
.item_type
= "<Separator>";
728 entry
.accelerator
= (gchar
*) NULL
;
730 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
732 /* this will be wrong for more than one separator. do we care? */
733 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, "<main>/sep" );
735 GtkWidget
*menuItem
= gtk_menu_item_new();
736 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
737 gtk_widget_show( menuItem
);
740 mitem
->SetMenuItem(menuItem
);
741 m_items
.Append( mitem
);
744 #if (GTK_MINOR_VERSION > 0)
745 static char* GetHotKey( const wxString
&hotkey
, char *hotbuf
)
747 if (hotkey
.IsEmpty()) return (char*) NULL
;
751 case _T('a'): /* Alt */
753 case _T('m'): /* Meta */
756 strcpy( hotbuf
, "<alt>" );
757 wxString last
= hotkey
.Right(1);
758 strcat( hotbuf
, last
.mb_str() );
761 case _T('c'): /* Ctrl */
763 case _T('s'): /* Strg, yeah man, I'm German */
766 strcpy( hotbuf
, "<control>" );
767 wxString last
= hotkey
.Right(1);
768 strcat( hotbuf
, last
.mb_str() );
771 case _T('F'): /* function keys */
773 strcpy( hotbuf
, hotkey
.mb_str() );
784 void wxMenu::Append( int id
, const wxString
&item
, const wxString
&helpStr
, bool checkable
)
786 wxMenuItem
*mitem
= new wxMenuItem();
788 mitem
->SetText(item
);
789 mitem
->SetHelp(helpStr
);
790 mitem
->SetCheckable(checkable
);
792 #if (GTK_MINOR_VERSION > 0)
793 /* text has "_" instead of "&" after mitem->SetText() */
794 wxString
text( mitem
->GetText() );
796 /* local buffer in multibyte form */
799 strcat( buf
, text
.mb_str() );
801 GtkItemFactoryEntry entry
;
803 entry
.callback
= (GtkItemFactoryCallback
) gtk_menu_clicked_callback
;
804 entry
.callback_action
= 0;
806 entry
.item_type
= "<CheckItem>";
808 entry
.item_type
= "<Item>";
811 entry
.accelerator
= GetHotKey( mitem
->GetHotKey(), hotbuf
);
813 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
815 /* in order to get the pointer to the item we need the item text _without_ underscores */
816 wxString s
= _T("<main>/");
817 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
819 if (*pc
== _T('_')) pc
++; /* skip it */
823 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, s
.mb_str() );
827 GtkWidget
*menuItem
= checkable
? gtk_check_menu_item_new_with_label( mitem
->GetText().mb_str() )
828 : gtk_menu_item_new_with_label( mitem
->GetText().mb_str() );
830 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
831 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
834 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
835 gtk_widget_show( menuItem
);
839 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
840 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
843 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
844 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
847 mitem
->SetMenuItem(menuItem
);
849 m_items
.Append( mitem
);
852 void wxMenu::Append( int id
, const wxString
&item
, wxMenu
*subMenu
, const wxString
&helpStr
)
854 wxMenuItem
*mitem
= new wxMenuItem();
856 mitem
->SetText(item
);
857 mitem
->SetHelp(helpStr
);
859 #if (GTK_MINOR_VERSION > 0)
860 /* text has "_" instead of "&" after mitem->SetText() */
861 wxString
text( mitem
->GetText() );
863 /* local buffer in multibyte form */
866 strcat( buf
, text
.mb_str() );
868 GtkItemFactoryEntry entry
;
870 entry
.callback
= (GtkItemFactoryCallback
) 0;
871 entry
.callback_action
= 0;
872 entry
.item_type
= "<Branch>";
874 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
876 /* in order to get the pointer to the item we need the item text _without_ underscores */
877 wxString s
= _T("<main>/");
878 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
880 if (*pc
== _T('_')) pc
++; /* skip it */
884 GtkWidget
*menuItem
= gtk_item_factory_get_item( m_factory
, s
.mb_str() );
888 GtkWidget
*menuItem
= gtk_menu_item_new_with_label(mitem
->GetText().mbc_str());
890 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
891 gtk_widget_show( menuItem
);
895 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
896 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
899 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
900 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
903 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), subMenu
->m_menu
);
905 mitem
->SetMenuItem(menuItem
);
906 mitem
->SetSubMenu(subMenu
);
908 m_items
.Append( mitem
);
911 void wxMenu::Append( wxMenuItem
*item
)
913 m_items
.Append( item
);
915 GtkWidget
*menuItem
= (GtkWidget
*) NULL
;
917 if (item
->IsSeparator())
918 menuItem
= gtk_menu_item_new();
919 else if (item
->IsSubMenu())
920 menuItem
= gtk_menu_item_new_with_label(item
->GetText().mbc_str());
922 menuItem
= item
->IsCheckable() ? gtk_check_menu_item_new_with_label(item
->GetText().mbc_str())
923 : gtk_menu_item_new_with_label(item
->GetText().mbc_str());
925 if (!item
->IsSeparator())
927 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
928 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
931 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
932 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
935 if (!item
->IsSubMenu())
937 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
938 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
943 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
944 gtk_widget_show( menuItem
);
945 item
->SetMenuItem(menuItem
);
948 int wxMenu::FindItem( const wxString itemString
) const
951 for ( const wxChar
*pc
= itemString
; *pc
!= _T('\0'); pc
++ )
956 #if (GTK_MINOR_VERSION > 0)
963 wxNode
*node
= m_items
.First();
966 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
967 if (item
->GetText() == s
)
969 return item
->GetId();
977 void wxMenu::Enable( int id
, bool enable
)
979 wxMenuItem
*item
= FindItem(id
);
981 wxCHECK_RET( item
, _T("wxMenu::Enable: no such item") );
983 item
->Enable(enable
);
986 bool wxMenu::IsEnabled( int id
) const
988 wxMenuItem
*item
= FindItem(id
);
990 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsEnabled: no such item") );
992 return item
->IsEnabled();
995 void wxMenu::Check( int id
, bool enable
)
997 wxMenuItem
*item
= FindItem(id
);
999 wxCHECK_RET( item
, _T("wxMenu::Check: no such item") );
1001 item
->Check(enable
);
1004 bool wxMenu::IsChecked( int id
) const
1006 wxMenuItem
*item
= FindItem(id
);
1008 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsChecked: no such item") );
1010 return item
->IsChecked();
1013 void wxMenu::SetLabel( int id
, const wxString
&label
)
1015 wxMenuItem
*item
= FindItem(id
);
1017 wxCHECK_RET( item
, _T("wxMenu::SetLabel: no such item") );
1019 item
->SetText(label
);
1022 wxString
wxMenu::GetLabel( int id
) const
1024 wxMenuItem
*item
= FindItem(id
);
1026 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetLabel: no such item") );
1028 return item
->GetText();
1031 void wxMenu::SetHelpString( int id
, const wxString
& helpString
)
1033 wxMenuItem
*item
= FindItem(id
);
1035 wxCHECK_RET( item
, _T("wxMenu::SetHelpString: no such item") );
1037 item
->SetHelp( helpString
);
1040 wxString
wxMenu::GetHelpString( int id
) const
1042 wxMenuItem
*item
= FindItem(id
);
1044 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetHelpString: no such item") );
1046 return item
->GetHelp();
1049 int wxMenu::FindMenuIdByMenuItem( GtkWidget
*menuItem
) const
1051 wxNode
*node
= m_items
.First();
1054 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1055 if (item
->GetMenuItem() == menuItem
)
1056 return item
->GetId();
1057 node
= node
->Next();
1063 wxMenuItem
*wxMenu::FindItem(int id
) const
1065 wxNode
*node
= m_items
.First();
1068 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1069 if (item
->GetId() == id
)
1073 node
= node
->Next();
1076 /* Not finding anything here can be correct
1077 * when search the entire menu system for
1078 * an entry -> no error message. */
1080 return (wxMenuItem
*) NULL
;
1083 void wxMenu::SetInvokingWindow( wxWindow
*win
)
1085 m_invokingWindow
= win
;
1088 wxWindow
*wxMenu::GetInvokingWindow()
1090 return m_invokingWindow
;
1093 // Update a menu and all submenus recursively. source is the object that has
1094 // the update event handlers defined for it. If NULL, the menu or associated
1095 // window will be used.
1096 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1098 if (!source
&& GetInvokingWindow())
1099 source
= GetInvokingWindow()->GetEventHandler();
1101 source
= GetEventHandler();
1105 wxNode
* node
= GetItems().First();
1108 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1109 if ( !item
->IsSeparator() )
1111 wxWindowID id
= item
->GetId();
1112 wxUpdateUIEvent
event(id
);
1113 event
.SetEventObject( source
);
1115 if (source
->ProcessEvent(event
))
1117 if (event
.GetSetText())
1118 SetLabel(id
, event
.GetText());
1119 if (event
.GetSetChecked())
1120 Check(id
, event
.GetChecked());
1121 if (event
.GetSetEnabled())
1122 Enable(id
, event
.GetEnabled());
1125 if (item
->GetSubMenu())
1126 item
->GetSubMenu()->UpdateUI(source
);
1128 node
= node
->Next();