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() */
42 if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize
) ||
43 !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, _T("menubar") ))
45 wxFAIL_MSG( _T("wxMenuBar creation failed") );
49 m_menus
.DeleteContents( TRUE
);
51 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
52 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
53 m_accel
= gtk_accel_group_new();
54 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel
);
55 m_menubar
= gtk_item_factory_get_widget( m_factory
, "<main>" );
57 m_menubar
= gtk_menu_bar_new();
60 if (style
& wxMB_DOCKABLE
)
62 m_widget
= gtk_handle_box_new();
63 gtk_container_add( GTK_CONTAINER(m_widget
), GTK_WIDGET(m_menubar
) );
64 gtk_widget_show( GTK_WIDGET(m_menubar
) );
68 m_widget
= GTK_WIDGET(m_menubar
);
74 wxMenuBar::wxMenuBar()
76 /* the parent window is known after wxFrame::SetMenu() */
80 if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize
) ||
81 !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, 0, wxDefaultValidator
, _T("menubar") ))
83 wxFAIL_MSG( _T("wxMenuBar creation failed") );
87 m_menus
.DeleteContents( TRUE
);
89 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
90 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
91 m_accel
= gtk_accel_group_new();
92 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel
);
93 m_menubar
= gtk_item_factory_get_widget( m_factory
, "<main>" );
95 m_menubar
= gtk_menu_bar_new();
98 m_widget
= GTK_WIDGET(m_menubar
);
103 wxMenuBar::~wxMenuBar()
105 // how to destroy a GtkItemFactory ?
108 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
110 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
112 #if (GTK_MINOR_VERSION > 0)
113 wxWindow
*top_frame
= win
;
114 while (top_frame
->GetParent()) top_frame
= top_frame
->GetParent();
116 /* support for native hot keys */
117 gtk_accel_group_detach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
120 wxNode
*node
= menu
->GetItems().First();
123 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
124 if (menuitem
->IsSubMenu())
125 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu(), win
);
130 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
132 menu
->SetInvokingWindow( win
);
134 #if (GTK_MINOR_VERSION > 0)
135 wxWindow
*top_frame
= win
;
136 while (top_frame
->GetParent())
137 top_frame
= top_frame
->GetParent();
139 /* support for native hot keys */
140 gtk_accel_group_attach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
143 wxNode
*node
= menu
->GetItems().First();
146 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
147 if (menuitem
->IsSubMenu())
148 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu(), win
);
153 void wxMenuBar::SetInvokingWindow( wxWindow
*win
)
155 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
156 wxWindow
*top_frame
= win
;
157 while (top_frame
->GetParent())
158 top_frame
= top_frame
->GetParent();
160 /* support for native key accelerators indicated by underscroes */
161 gtk_accel_group_attach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
164 wxNode
*node
= m_menus
.First();
167 wxMenu
*menu
= (wxMenu
*)node
->Data();
168 wxMenubarSetInvokingWindow( menu
, win
);
173 void wxMenuBar::UnsetInvokingWindow( wxWindow
*win
)
175 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
176 wxWindow
*top_frame
= win
;
177 while (top_frame
->GetParent())
178 top_frame
= top_frame
->GetParent();
180 /* support for native key accelerators indicated by underscroes */
181 gtk_accel_group_detach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
184 wxNode
*node
= m_menus
.First();
187 wxMenu
*menu
= (wxMenu
*)node
->Data();
188 wxMenubarUnsetInvokingWindow( menu
, win
);
193 void wxMenuBar::Append( wxMenu
*menu
, const wxString
&title
)
195 m_menus
.Append( menu
);
199 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
201 for ( pc
= title
; *pc
!= _T('\0'); pc
++ )
205 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
217 /* this doesn't have much effect right now */
218 menu
->SetTitle( str
);
220 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
221 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
223 /* local buffer in multibyte form */
225 buf
<< _T('/') << str
.c_str();
227 char *cbuf
= new char[buf
.Length()+1];
228 strcpy(cbuf
, buf
.mbc_str());
230 GtkItemFactoryEntry entry
;
231 entry
.path
= (gchar
*)cbuf
; // const_cast
232 entry
.accelerator
= (gchar
*) NULL
;
233 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
234 entry
.callback_action
= 0;
235 entry
.item_type
= "<Branch>";
237 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
238 /* in order to get the pointer to the item we need the item text _without_ underscores */
239 wxString tmp
= _T("<main>/");
240 for ( pc
= str
; *pc
!= _T('\0'); pc
++ )
242 if (*pc
== _T('_')) pc
++; /* skip it */
245 menu
->m_owner
= gtk_item_factory_get_item( m_factory
, tmp
.mb_str() );
246 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
250 menu
->m_owner
= gtk_menu_item_new_with_label( str
.mb_str() );
251 gtk_widget_show( menu
->m_owner
);
252 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
254 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), menu
->m_owner
);
259 static int FindMenuItemRecursive( const wxMenu
*menu
, const wxString
&menuString
, const wxString
&itemString
)
261 if (menu
->GetTitle() == menuString
)
263 int res
= menu
->FindItem( itemString
);
264 if (res
!= wxNOT_FOUND
)
268 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
271 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
272 if (item
->IsSubMenu())
273 return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
);
281 wxMenuItem
*wxMenuBar::FindItemForId(int itemId
, wxMenu
**menuForItem
) const
285 // TODO return the pointer to the menu
290 return FindItem(itemId
);
293 int wxMenuBar::FindMenuItem( const wxString
&menuString
, const wxString
&itemString
) const
295 wxNode
*node
= m_menus
.First();
298 wxMenu
*menu
= (wxMenu
*)node
->Data();
299 int res
= FindMenuItemRecursive( menu
, menuString
, itemString
);
300 if (res
!= -1) return res
;
306 // Find a wxMenuItem using its id. Recurses down into sub-menus
307 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
)
309 wxMenuItem
* result
= menu
->FindItem(id
);
311 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
312 while ( node
&& result
== NULL
)
314 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
315 if (item
->IsSubMenu())
317 result
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id
);
325 wxMenuItem
* wxMenuBar::FindItem( int id
) const
327 wxMenuItem
* result
= 0;
328 wxNode
*node
= m_menus
.First();
329 while (node
&& result
== 0)
331 wxMenu
*menu
= (wxMenu
*)node
->Data();
332 result
= FindMenuItemByIdRecursive( menu
, id
);
339 void wxMenuBar::Check( int id
, bool check
)
341 wxMenuItem
* item
= FindMenuItemById( id
);
343 wxCHECK_RET( item
, _T("wxMenuBar::Check: no such item") );
348 bool wxMenuBar::IsChecked( int id
) const
350 wxMenuItem
* item
= FindMenuItemById( id
);
352 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsChecked: no such item") );
354 return item
->IsChecked();
357 void wxMenuBar::Enable( int id
, bool enable
)
359 wxMenuItem
* item
= FindMenuItemById( id
);
361 wxCHECK_RET( item
, _T("wxMenuBar::Enable: no such item") );
363 item
->Enable(enable
);
366 bool wxMenuBar::IsEnabled( int id
) const
368 wxMenuItem
* item
= FindMenuItemById( id
);
370 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsEnabled: no such item") );
372 return item
->IsEnabled();
375 wxString
wxMenuBar::GetLabel( int id
) const
377 wxMenuItem
* item
= FindMenuItemById( id
);
379 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetLabel: no such item") );
381 return item
->GetText();
384 void wxMenuBar::SetLabel( int id
, const wxString
&label
)
386 wxMenuItem
* item
= FindMenuItemById( id
);
388 wxCHECK_RET( item
, _T("wxMenuBar::SetLabel: no such item") );
390 item
->SetText( label
);
393 void wxMenuBar::EnableTop( int pos
, bool flag
)
395 wxNode
*node
= m_menus
.Nth( pos
);
397 wxCHECK_RET( node
, _T("menu not found") );
399 wxMenu
* menu
= (wxMenu
*)node
->Data();
402 gtk_widget_set_sensitive( menu
->m_owner
, flag
);
405 wxString
wxMenuBar::GetLabelTop( int pos
) const
407 wxNode
*node
= m_menus
.Nth( pos
);
409 wxCHECK_MSG( node
, _T("invalid"), _T("menu not found") );
411 wxMenu
* menu
= (wxMenu
*)node
->Data();
413 return menu
->GetTitle();
416 void wxMenuBar::SetLabelTop( int pos
, const wxString
& label
)
418 wxNode
*node
= m_menus
.Nth( pos
);
420 wxCHECK_RET( node
, _T("menu not found") );
422 wxMenu
* menu
= (wxMenu
*)node
->Data();
424 menu
->SetTitle( label
);
427 void wxMenuBar::SetHelpString( int id
, const wxString
& helpString
)
429 wxMenuItem
* item
= FindMenuItemById( id
);
431 wxCHECK_RET( item
, _T("wxMenuBar::SetHelpString: no such item") );
433 item
->SetHelp( helpString
);
436 wxString
wxMenuBar::GetHelpString( int id
) const
438 wxMenuItem
* item
= FindMenuItemById( id
);
440 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetHelpString: no such item") );
442 return item
->GetHelp();
445 //-----------------------------------------------------------------------------
447 //-----------------------------------------------------------------------------
449 static void gtk_menu_clicked_callback( GtkWidget
*widget
, wxMenu
*menu
)
451 if (g_isIdle
) wxapp_install_idle_handler();
453 int id
= menu
->FindMenuIdByMenuItem(widget
);
455 /* should find it for normal (not popup) menu */
456 wxASSERT( (id
!= -1) || (menu
->GetInvokingWindow() != NULL
) );
458 if (!menu
->IsEnabled(id
))
461 wxMenuItem
* item
= menu
->FindItem( id
);
462 wxCHECK_RET( item
, _T("error in menu item callback") );
464 if (item
->IsCheckable())
466 if (item
->GetCheckedFlag() == item
->IsChecked())
468 /* the menu item has been checked by calling wxMenuItem->Check() */
473 /* the user pressed on the menu item -> report */
474 item
->SetCheckedFlag(item
->IsChecked()); /* make consistent again */
478 wxCommandEvent
event( wxEVT_COMMAND_MENU_SELECTED
, id
);
479 event
.SetEventObject( menu
);
482 if (menu
->GetCallback())
484 (void) (*(menu
->GetCallback())) (*menu
, event
);
488 if (menu
->GetEventHandler()->ProcessEvent(event
))
491 wxWindow
*win
= menu
->GetInvokingWindow();
493 win
->GetEventHandler()->ProcessEvent( event
);
496 //-----------------------------------------------------------------------------
498 //-----------------------------------------------------------------------------
500 static void gtk_menu_hilight_callback( GtkWidget
*widget
, wxMenu
*menu
)
502 if (g_isIdle
) wxapp_install_idle_handler();
504 int id
= menu
->FindMenuIdByMenuItem(widget
);
506 wxASSERT( id
!= -1 ); // should find it!
508 if (!menu
->IsEnabled(id
))
511 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, id
);
512 event
.SetEventObject( menu
);
514 if (menu
->GetEventHandler()->ProcessEvent(event
))
517 wxWindow
*win
= menu
->GetInvokingWindow();
518 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
521 //-----------------------------------------------------------------------------
523 //-----------------------------------------------------------------------------
525 static void gtk_menu_nolight_callback( GtkWidget
*widget
, wxMenu
*menu
)
527 if (g_isIdle
) wxapp_install_idle_handler();
529 int id
= menu
->FindMenuIdByMenuItem(widget
);
531 wxASSERT( id
!= -1 ); // should find it!
533 if (!menu
->IsEnabled(id
))
536 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, -1 );
537 event
.SetEventObject( menu
);
539 if (menu
->GetEventHandler()->ProcessEvent(event
))
542 wxWindow
*win
= menu
->GetInvokingWindow();
544 win
->GetEventHandler()->ProcessEvent( event
);
547 //-----------------------------------------------------------------------------
549 //-----------------------------------------------------------------------------
551 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
,wxObject
)
553 wxMenuItem::wxMenuItem()
556 m_isCheckMenu
= FALSE
;
559 m_subMenu
= (wxMenu
*) NULL
;
560 m_menuItem
= (GtkWidget
*) NULL
;
563 // it's valid for this function to be called even if m_menuItem == NULL
564 void wxMenuItem::SetName( const wxString
& str
)
566 /* '\t' is the deliminator indicating a hot key */
568 const wxChar
*pc
= str
;
569 for (; (*pc
!= _T('\0')) && (*pc
!= _T('\t')); pc
++ )
573 #if (GTK_MINOR_VERSION > 0)
576 if (*pc
== _T('/')) /* we have to filter out slashes ... */
578 m_text
<< _T('\\'); /* ... and replace them with back slashes */
585 /* only GTK 1.2 knows about hot keys */
587 #if (GTK_MINOR_VERSION > 0)
597 GtkLabel
*label
= GTK_LABEL( GTK_BIN(m_menuItem
)->child
);
598 gtk_label_set( label
, m_text
.mb_str());
602 void wxMenuItem::Check( bool check
)
604 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
606 wxCHECK_RET( IsCheckable(), _T("Can't check uncheckable item!") )
608 if (check
== m_isChecked
) return;
611 gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check
);
614 void wxMenuItem::Enable( bool enable
)
616 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
618 gtk_widget_set_sensitive( m_menuItem
, enable
);
619 m_isEnabled
= enable
;
622 bool wxMenuItem::IsChecked() const
624 wxCHECK_MSG( m_menuItem
, FALSE
, _T("invalid menu item") );
626 wxCHECK( IsCheckable(), FALSE
); // can't get state of uncheckable item!
628 bool bIsChecked
= ((GtkCheckMenuItem
*)m_menuItem
)->active
!= 0;
633 //-----------------------------------------------------------------------------
635 //-----------------------------------------------------------------------------
637 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
)
640 wxMenu::Init( const wxString
& title
,
642 const wxFunction func
646 m_items
.DeleteContents( TRUE
);
647 m_invokingWindow
= (wxWindow
*) NULL
;
650 #if (GTK_MINOR_VERSION > 0)
651 m_accel
= gtk_accel_group_new();
652 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU
, "<main>", m_accel
);
653 m_menu
= gtk_item_factory_get_widget( m_factory
, "<main>" );
655 m_menu
= gtk_menu_new(); // Do not show!
660 m_eventHandler
= this;
661 m_clientData
= (void*) NULL
;
663 if (m_title
.IsNull()) m_title
= _T("");
664 if (m_title
!= _T(""))
670 m_owner
= (GtkWidget
*) NULL
;
672 #if (GTK_MINOR_VERSION > 0)
673 /* Tearoffs are entries, just like separators. So if we want this
674 menu to be a tear-off one, we just append a tearoff entry
676 if(m_style
& wxMENU_TEAROFF
)
678 GtkItemFactoryEntry entry
;
679 entry
.path
= "/tearoff";
680 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
681 entry
.callback_action
= 0;
682 entry
.item_type
= "<Tearoff>";
683 entry
.accelerator
= (gchar
*) NULL
;
684 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
685 //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
692 /* how do we delete an item-factory ? */
693 gtk_widget_destroy( m_menu
);
697 void wxMenu::SetTitle( const wxString
& title
)
699 // TODO Waiting for something better
703 const wxString
wxMenu::GetTitle() const
708 void wxMenu::AppendSeparator()
710 wxMenuItem
*mitem
= new wxMenuItem();
711 mitem
->SetId(ID_SEPARATOR
);
713 #if (GTK_MINOR_VERSION > 0)
714 GtkItemFactoryEntry entry
;
716 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
717 entry
.callback_action
= 0;
718 entry
.item_type
= "<Separator>";
719 entry
.accelerator
= (gchar
*) NULL
;
721 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
723 /* this will be wrong for more than one separator. do we care? */
724 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, "<main>/sep" );
726 GtkWidget
*menuItem
= gtk_menu_item_new();
727 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
728 gtk_widget_show( menuItem
);
731 mitem
->SetMenuItem(menuItem
);
732 m_items
.Append( mitem
);
735 #if (GTK_MINOR_VERSION > 0)
736 static char* GetHotKey( const wxString
&hotkey
, char *hotbuf
)
738 if (hotkey
.IsEmpty()) return (char*) NULL
;
742 case _T('a'): /* Alt */
744 case _T('m'): /* Meta */
747 strcpy( hotbuf
, "<alt>" );
748 wxString last
= hotkey
.Right(1);
749 strcat( hotbuf
, last
.mb_str() );
752 case _T('c'): /* Ctrl */
754 case _T('s'): /* Strg, yeah man, I'm German */
757 strcpy( hotbuf
, "<control>" );
758 wxString last
= hotkey
.Right(1);
759 strcat( hotbuf
, last
.mb_str() );
762 case _T('F'): /* function keys */
764 strcpy( hotbuf
, hotkey
.mb_str() );
775 void wxMenu::Append( int id
, const wxString
&item
, const wxString
&helpStr
, bool checkable
)
777 wxMenuItem
*mitem
= new wxMenuItem();
779 mitem
->SetText(item
);
780 mitem
->SetHelp(helpStr
);
781 mitem
->SetCheckable(checkable
);
783 #if (GTK_MINOR_VERSION > 0)
784 /* text has "_" instead of "&" after mitem->SetText() */
785 wxString
text( mitem
->GetText() );
787 /* local buffer in multibyte form */
790 strcat( buf
, text
.mb_str() );
792 GtkItemFactoryEntry entry
;
794 entry
.callback
= (GtkItemFactoryCallback
) gtk_menu_clicked_callback
;
795 entry
.callback_action
= 0;
797 entry
.item_type
= "<CheckItem>";
799 entry
.item_type
= "<Item>";
802 entry
.accelerator
= GetHotKey( mitem
->GetHotKey(), hotbuf
);
804 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
806 /* in order to get the pointer to the item we need the item text _without_ underscores */
807 wxString s
= _T("<main>/");
808 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
810 if (*pc
== _T('_')) pc
++; /* skip it */
814 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, s
.mb_str() );
818 GtkWidget
*menuItem
= checkable
? gtk_check_menu_item_new_with_label( mitem
->GetText().mb_str() )
819 : gtk_menu_item_new_with_label( mitem
->GetText().mb_str() );
821 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
822 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
825 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
826 gtk_widget_show( menuItem
);
830 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
831 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
834 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
835 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
838 mitem
->SetMenuItem(menuItem
);
840 m_items
.Append( mitem
);
843 void wxMenu::Append( int id
, const wxString
&item
, wxMenu
*subMenu
, const wxString
&helpStr
)
845 wxMenuItem
*mitem
= new wxMenuItem();
847 mitem
->SetText(item
);
848 mitem
->SetHelp(helpStr
);
850 #if (GTK_MINOR_VERSION > 0)
851 /* text has "_" instead of "&" after mitem->SetText() */
852 wxString
text( mitem
->GetText() );
854 /* local buffer in multibyte form */
857 strcat( buf
, text
.mb_str() );
859 GtkItemFactoryEntry entry
;
861 entry
.callback
= (GtkItemFactoryCallback
) 0;
862 entry
.callback_action
= 0;
863 entry
.item_type
= "<Branch>";
865 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
867 /* in order to get the pointer to the item we need the item text _without_ underscores */
868 wxString s
= _T("<main>/");
869 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
871 if (*pc
== _T('_')) pc
++; /* skip it */
875 GtkWidget
*menuItem
= gtk_item_factory_get_item( m_factory
, s
.mb_str() );
879 GtkWidget
*menuItem
= gtk_menu_item_new_with_label(mitem
->GetText().mbc_str());
881 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
882 gtk_widget_show( menuItem
);
886 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
887 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
890 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
891 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
894 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), subMenu
->m_menu
);
896 mitem
->SetMenuItem(menuItem
);
897 mitem
->SetSubMenu(subMenu
);
899 m_items
.Append( mitem
);
902 void wxMenu::Append( wxMenuItem
*item
)
904 m_items
.Append( item
);
906 GtkWidget
*menuItem
= (GtkWidget
*) NULL
;
908 if (item
->IsSeparator())
909 menuItem
= gtk_menu_item_new();
910 else if (item
->IsSubMenu())
911 menuItem
= gtk_menu_item_new_with_label(item
->GetText().mbc_str());
913 menuItem
= item
->IsCheckable() ? gtk_check_menu_item_new_with_label(item
->GetText().mbc_str())
914 : gtk_menu_item_new_with_label(item
->GetText().mbc_str());
916 if (!item
->IsSeparator())
918 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
919 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
922 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
923 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
926 if (!item
->IsSubMenu())
928 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
929 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
934 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
935 gtk_widget_show( menuItem
);
936 item
->SetMenuItem(menuItem
);
939 int wxMenu::FindItem( const wxString itemString
) const
942 for ( const wxChar
*pc
= itemString
; *pc
!= _T('\0'); pc
++ )
947 #if (GTK_MINOR_VERSION > 0)
954 wxNode
*node
= m_items
.First();
957 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
958 if (item
->GetText() == s
)
960 return item
->GetId();
968 void wxMenu::Enable( int id
, bool enable
)
970 wxMenuItem
*item
= FindItem(id
);
972 wxCHECK_RET( item
, _T("wxMenu::Enable: no such item") );
974 item
->Enable(enable
);
977 bool wxMenu::IsEnabled( int id
) const
979 wxMenuItem
*item
= FindItem(id
);
981 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsEnabled: no such item") );
983 return item
->IsEnabled();
986 void wxMenu::Check( int id
, bool enable
)
988 wxMenuItem
*item
= FindItem(id
);
990 wxCHECK_RET( item
, _T("wxMenu::Check: no such item") );
995 bool wxMenu::IsChecked( int id
) const
997 wxMenuItem
*item
= FindItem(id
);
999 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsChecked: no such item") );
1001 return item
->IsChecked();
1004 void wxMenu::SetLabel( int id
, const wxString
&label
)
1006 wxMenuItem
*item
= FindItem(id
);
1008 wxCHECK_RET( item
, _T("wxMenu::SetLabel: no such item") );
1010 item
->SetText(label
);
1013 wxString
wxMenu::GetLabel( int id
) const
1015 wxMenuItem
*item
= FindItem(id
);
1017 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetLabel: no such item") );
1019 return item
->GetText();
1022 void wxMenu::SetHelpString( int id
, const wxString
& helpString
)
1024 wxMenuItem
*item
= FindItem(id
);
1026 wxCHECK_RET( item
, _T("wxMenu::SetHelpString: no such item") );
1028 item
->SetHelp( helpString
);
1031 wxString
wxMenu::GetHelpString( int id
) const
1033 wxMenuItem
*item
= FindItem(id
);
1035 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetHelpString: no such item") );
1037 return item
->GetHelp();
1040 int wxMenu::FindMenuIdByMenuItem( GtkWidget
*menuItem
) const
1042 wxNode
*node
= m_items
.First();
1045 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1046 if (item
->GetMenuItem() == menuItem
)
1047 return item
->GetId();
1048 node
= node
->Next();
1054 wxMenuItem
*wxMenu::FindItem(int id
) const
1056 wxNode
*node
= m_items
.First();
1059 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1060 if (item
->GetId() == id
)
1064 node
= node
->Next();
1067 /* Not finding anything here can be correct
1068 * when search the entire menu system for
1069 * an entry -> no error message. */
1071 return (wxMenuItem
*) NULL
;
1074 void wxMenu::SetInvokingWindow( wxWindow
*win
)
1076 m_invokingWindow
= win
;
1079 wxWindow
*wxMenu::GetInvokingWindow()
1081 return m_invokingWindow
;
1084 // Update a menu and all submenus recursively. source is the object that has
1085 // the update event handlers defined for it. If NULL, the menu or associated
1086 // window will be used.
1087 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1089 if (!source
&& GetInvokingWindow())
1090 source
= GetInvokingWindow()->GetEventHandler();
1092 source
= GetEventHandler();
1096 wxNode
* node
= GetItems().First();
1099 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1100 if ( !item
->IsSeparator() )
1102 wxWindowID id
= item
->GetId();
1103 wxUpdateUIEvent
event(id
);
1104 event
.SetEventObject( source
);
1106 if (source
->ProcessEvent(event
))
1108 if (event
.GetSetText())
1109 SetLabel(id
, event
.GetText());
1110 if (event
.GetSetChecked())
1111 Check(id
, event
.GetChecked());
1112 if (event
.GetSetEnabled())
1113 Enable(id
, event
.GetEnabled());
1116 if (item
->GetSubMenu())
1117 item
->GetSubMenu()->UpdateUI(source
);
1119 node
= node
->Next();