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 PreCreation( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, style
, "menu" );
44 m_menus
.DeleteContents( TRUE
);
46 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
47 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
48 m_accel
= gtk_accel_group_new();
49 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel
);
50 m_menubar
= gtk_item_factory_get_widget( m_factory
, "<main>" );
52 m_menubar
= gtk_menu_bar_new();
55 if (style
& wxMB_DOCKABLE
)
57 m_widget
= gtk_handle_box_new();
58 gtk_container_add( GTK_CONTAINER(m_widget
), GTK_WIDGET(m_menubar
) );
59 gtk_widget_show( GTK_WIDGET(m_menubar
) );
63 m_widget
= GTK_WIDGET(m_menubar
);
69 wxMenuBar::wxMenuBar()
71 /* the parent window is known after wxFrame::SetMenu() */
75 PreCreation( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, 0, "menu" );
77 m_menus
.DeleteContents( TRUE
);
79 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
80 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
81 m_accel
= gtk_accel_group_new();
82 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel
);
83 m_menubar
= gtk_item_factory_get_widget( m_factory
, "<main>" );
85 m_menubar
= gtk_menu_bar_new();
88 m_widget
= GTK_WIDGET(m_menubar
);
93 wxMenuBar::~wxMenuBar()
95 // how to destroy a GtkItemFactory ?
98 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
100 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
102 #if (GTK_MINOR_VERSION > 0)
103 wxWindow
*top_frame
= win
;
104 while (top_frame
->GetParent()) top_frame
= top_frame
->GetParent();
106 /* support for native hot keys */
107 gtk_accel_group_detach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
110 wxNode
*node
= menu
->GetItems().First();
113 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
114 if (menuitem
->IsSubMenu())
115 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu(), win
);
120 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
122 menu
->SetInvokingWindow( win
);
124 #if (GTK_MINOR_VERSION > 0)
125 wxWindow
*top_frame
= win
;
126 while (top_frame
->GetParent())
127 top_frame
= top_frame
->GetParent();
129 /* support for native hot keys */
130 gtk_accel_group_attach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
133 wxNode
*node
= menu
->GetItems().First();
136 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
137 if (menuitem
->IsSubMenu())
138 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu(), win
);
143 void wxMenuBar::SetInvokingWindow( wxWindow
*win
)
145 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
146 wxWindow
*top_frame
= win
;
147 while (top_frame
->GetParent())
148 top_frame
= top_frame
->GetParent();
150 /* support for native key accelerators indicated by underscroes */
151 gtk_accel_group_attach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
154 wxNode
*node
= m_menus
.First();
157 wxMenu
*menu
= (wxMenu
*)node
->Data();
158 wxMenubarSetInvokingWindow( menu
, win
);
163 void wxMenuBar::UnsetInvokingWindow( wxWindow
*win
)
165 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
166 wxWindow
*top_frame
= win
;
167 while (top_frame
->GetParent())
168 top_frame
= top_frame
->GetParent();
170 /* support for native key accelerators indicated by underscroes */
171 gtk_accel_group_detach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
174 wxNode
*node
= m_menus
.First();
177 wxMenu
*menu
= (wxMenu
*)node
->Data();
178 wxMenubarUnsetInvokingWindow( menu
, win
);
183 void wxMenuBar::Append( wxMenu
*menu
, const wxString
&title
)
185 m_menus
.Append( menu
);
189 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
191 for ( pc
= title
; *pc
!= _T('\0'); pc
++ )
195 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
207 /* this doesn't have much effect right now */
208 menu
->SetTitle( str
);
210 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
211 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
213 /* local buffer in multibyte form */
215 buf
<< _T('/') << str
.c_str();
217 char *cbuf
= new char[buf
.Length()];
218 strcpy(cbuf
, buf
.mbc_str());
220 GtkItemFactoryEntry entry
;
221 entry
.path
= (gchar
*)cbuf
; // const_cast
222 entry
.accelerator
= (gchar
*) NULL
;
223 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
224 entry
.callback_action
= 0;
225 entry
.item_type
= "<Branch>";
227 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
228 /* in order to get the pointer to the item we need the item text _without_ underscores */
229 wxString tmp
= _T("<main>/");
230 for ( pc
= str
; *pc
!= _T('\0'); pc
++ )
232 if (*pc
== _T('_')) pc
++; /* skip it */
235 menu
->m_owner
= gtk_item_factory_get_item( m_factory
, tmp
.mb_str() );
236 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
240 menu
->m_owner
= gtk_menu_item_new_with_label( str
.mb_str() );
241 gtk_widget_show( menu
->m_owner
);
242 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
244 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), menu
->m_owner
);
249 static int FindMenuItemRecursive( const wxMenu
*menu
, const wxString
&menuString
, const wxString
&itemString
)
251 if (menu
->GetTitle() == menuString
)
253 int res
= menu
->FindItem( itemString
);
254 if (res
!= wxNOT_FOUND
)
258 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
261 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
262 if (item
->IsSubMenu())
263 return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
);
271 wxMenuItem
*wxMenuBar::FindItemForId(int itemId
, wxMenu
**menuForItem
) const
275 // TODO return the pointer to the menu
280 return FindItem(itemId
);
283 int wxMenuBar::FindMenuItem( const wxString
&menuString
, const wxString
&itemString
) const
285 wxNode
*node
= m_menus
.First();
288 wxMenu
*menu
= (wxMenu
*)node
->Data();
289 int res
= FindMenuItemRecursive( menu
, menuString
, itemString
);
290 if (res
!= -1) return res
;
296 // Find a wxMenuItem using its id. Recurses down into sub-menus
297 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
)
299 wxMenuItem
* result
= menu
->FindItem(id
);
301 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
302 while ( node
&& result
== NULL
)
304 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
305 if (item
->IsSubMenu())
307 result
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id
);
315 wxMenuItem
* wxMenuBar::FindItem( int id
) const
317 wxMenuItem
* result
= 0;
318 wxNode
*node
= m_menus
.First();
319 while (node
&& result
== 0)
321 wxMenu
*menu
= (wxMenu
*)node
->Data();
322 result
= FindMenuItemByIdRecursive( menu
, id
);
329 void wxMenuBar::Check( int id
, bool check
)
331 wxMenuItem
* item
= FindMenuItemById( id
);
333 wxCHECK_RET( item
, _T("wxMenuBar::Check: no such item") );
338 bool wxMenuBar::IsChecked( int id
) const
340 wxMenuItem
* item
= FindMenuItemById( id
);
342 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsChecked: no such item") );
344 return item
->IsChecked();
347 void wxMenuBar::Enable( int id
, bool enable
)
349 wxMenuItem
* item
= FindMenuItemById( id
);
351 wxCHECK_RET( item
, _T("wxMenuBar::Enable: no such item") );
353 item
->Enable(enable
);
356 bool wxMenuBar::IsEnabled( int id
) const
358 wxMenuItem
* item
= FindMenuItemById( id
);
360 wxCHECK_MSG( item
, FALSE
, _T("wxMenuBar::IsEnabled: no such item") );
362 return item
->IsEnabled();
365 wxString
wxMenuBar::GetLabel( int id
) const
367 wxMenuItem
* item
= FindMenuItemById( id
);
369 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetLabel: no such item") );
371 return item
->GetText();
374 void wxMenuBar::SetLabel( int id
, const wxString
&label
)
376 wxMenuItem
* item
= FindMenuItemById( id
);
378 wxCHECK_RET( item
, _T("wxMenuBar::SetLabel: no such item") );
380 item
->SetText( label
);
383 void wxMenuBar::EnableTop( int pos
, bool flag
)
385 wxNode
*node
= m_menus
.Nth( pos
);
387 wxCHECK_RET( node
, _T("menu not found") );
389 wxMenu
* menu
= (wxMenu
*)node
->Data();
392 gtk_widget_set_sensitive( menu
->m_owner
, flag
);
395 wxString
wxMenuBar::GetLabelTop( int pos
) const
397 wxNode
*node
= m_menus
.Nth( pos
);
399 wxCHECK_MSG( node
, _T("invalid"), _T("menu not found") );
401 wxMenu
* menu
= (wxMenu
*)node
->Data();
403 return menu
->GetTitle();
406 void wxMenuBar::SetLabelTop( int pos
, const wxString
& label
)
408 wxNode
*node
= m_menus
.Nth( pos
);
410 wxCHECK_RET( node
, _T("menu not found") );
412 wxMenu
* menu
= (wxMenu
*)node
->Data();
414 menu
->SetTitle( label
);
417 void wxMenuBar::SetHelpString( int id
, const wxString
& helpString
)
419 wxMenuItem
* item
= FindMenuItemById( id
);
421 wxCHECK_RET( item
, _T("wxMenuBar::SetHelpString: no such item") );
423 item
->SetHelp( helpString
);
426 wxString
wxMenuBar::GetHelpString( int id
) const
428 wxMenuItem
* item
= FindMenuItemById( id
);
430 wxCHECK_MSG( item
, _T(""), _T("wxMenuBar::GetHelpString: no such item") );
432 return item
->GetHelp();
435 //-----------------------------------------------------------------------------
437 //-----------------------------------------------------------------------------
439 static void gtk_menu_clicked_callback( GtkWidget
*widget
, wxMenu
*menu
)
441 if (g_isIdle
) wxapp_install_idle_handler();
443 int id
= menu
->FindMenuIdByMenuItem(widget
);
445 /* should find it for normal (not popup) menu */
446 wxASSERT( (id
!= -1) || (menu
->GetInvokingWindow() != NULL
) );
448 if (!menu
->IsEnabled(id
))
451 wxMenuItem
* item
= menu
->FindItem( id
);
452 wxCHECK_RET( item
, _T("error in menu item callback") );
454 if (item
->IsCheckable())
456 if (item
->GetCheckedFlag() == item
->IsChecked())
458 /* the menu item has been checked by calling wxMenuItem->Check() */
463 /* the user pressed on the menu item -> report */
464 item
->SetCheckedFlag(item
->IsChecked()); /* make consistent again */
468 wxCommandEvent
event( wxEVT_COMMAND_MENU_SELECTED
, id
);
469 event
.SetEventObject( menu
);
472 if (menu
->GetCallback())
474 (void) (*(menu
->GetCallback())) (*menu
, event
);
478 if (menu
->GetEventHandler()->ProcessEvent(event
))
481 wxWindow
*win
= menu
->GetInvokingWindow();
483 win
->GetEventHandler()->ProcessEvent( event
);
486 //-----------------------------------------------------------------------------
488 //-----------------------------------------------------------------------------
490 static void gtk_menu_hilight_callback( GtkWidget
*widget
, wxMenu
*menu
)
492 if (g_isIdle
) wxapp_install_idle_handler();
494 int id
= menu
->FindMenuIdByMenuItem(widget
);
496 wxASSERT( id
!= -1 ); // should find it!
498 if (!menu
->IsEnabled(id
))
501 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, id
);
502 event
.SetEventObject( menu
);
504 /* wxMSW doesn't call callback here either
506 if (menu->m_callback)
508 (void) (*(menu->m_callback)) (*menu, event);
513 if (menu
->GetEventHandler()->ProcessEvent(event
))
516 wxWindow
*win
= menu
->GetInvokingWindow();
517 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
520 //-----------------------------------------------------------------------------
522 //-----------------------------------------------------------------------------
524 static void gtk_menu_nolight_callback( GtkWidget
*widget
, wxMenu
*menu
)
526 if (g_isIdle
) wxapp_install_idle_handler();
528 int id
= menu
->FindMenuIdByMenuItem(widget
);
530 wxASSERT( id
!= -1 ); // should find it!
532 if (!menu
->IsEnabled(id
))
535 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, -1 );
536 event
.SetEventObject( menu
);
538 if (menu
->GetEventHandler()->ProcessEvent(event
))
541 wxWindow
*win
= menu
->GetInvokingWindow();
543 win
->GetEventHandler()->ProcessEvent( event
);
546 //-----------------------------------------------------------------------------
548 //-----------------------------------------------------------------------------
550 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
,wxObject
)
552 wxMenuItem::wxMenuItem()
555 m_isCheckMenu
= FALSE
;
558 m_subMenu
= (wxMenu
*) NULL
;
559 m_menuItem
= (GtkWidget
*) NULL
;
562 // it's valid for this function to be called even if m_menuItem == NULL
563 void wxMenuItem::SetName( const wxString
& str
)
565 /* '\t' is the deliminator indicating a hot key */
567 const wxChar
*pc
= str
;
568 for (; (*pc
!= _T('\0')) && (*pc
!= _T('\t')); pc
++ )
572 #if (GTK_MINOR_VERSION > 0)
575 if (*pc
== _T('/')) /* we have to filter out slashes ... */
577 m_text
<< _T('\\'); /* ... and replace them with back slashes */
584 /* only GTK 1.2 knows about hot keys */
586 #if (GTK_MINOR_VERSION > 0)
596 GtkLabel
*label
= GTK_LABEL( GTK_BIN(m_menuItem
)->child
);
597 gtk_label_set( label
, m_text
.mb_str());
601 void wxMenuItem::Check( bool check
)
603 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
605 wxCHECK_RET( IsCheckable(), _T("Can't check uncheckable item!") )
607 if (check
== m_isChecked
) return;
610 gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check
);
613 void wxMenuItem::Enable( bool enable
)
615 wxCHECK_RET( m_menuItem
, _T("invalid menu item") );
617 gtk_widget_set_sensitive( m_menuItem
, enable
);
618 m_isEnabled
= enable
;
621 bool wxMenuItem::IsChecked() const
623 wxCHECK_MSG( m_menuItem
, FALSE
, _T("invalid menu item") );
625 wxCHECK( IsCheckable(), FALSE
); // can't get state of uncheckable item!
627 bool bIsChecked
= ((GtkCheckMenuItem
*)m_menuItem
)->active
!= 0;
632 //-----------------------------------------------------------------------------
634 //-----------------------------------------------------------------------------
636 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
)
638 wxMenu::wxMenu( const wxString
& title
, const wxFunction func
, long style
)
640 Init(title
, func
, style
);
643 wxMenu::wxMenu(long style
)
645 Init(wxEmptyString
, (wxFunction
) NULL
, style
);
649 wxMenu::Init( const wxString
& title
, const wxFunction func
, long style
)
652 m_items
.DeleteContents( TRUE
);
653 m_invokingWindow
= (wxWindow
*) NULL
;
656 #if (GTK_MINOR_VERSION > 0)
657 m_accel
= gtk_accel_group_new();
658 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU
, "<main>", m_accel
);
659 m_menu
= gtk_item_factory_get_widget( m_factory
, "<main>" );
661 m_menu
= gtk_menu_new(); // Do not show!
665 m_eventHandler
= this;
666 m_clientData
= (void*) NULL
;
668 if (m_title
.IsNull()) m_title
= _T("");
669 if (m_title
!= _T(""))
675 m_owner
= (GtkWidget
*) NULL
;
677 #if (GTK_MINOR_VERSION > 0)
678 /* Tearoffs are entries, just like separators. So if we want this
679 menu to be a tear-off one, we just append a tearoff entry
681 if(m_style
& wxMENU_TEAROFF
)
683 GtkItemFactoryEntry entry
;
684 entry
.path
= "/tearoff";
685 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
686 entry
.callback_action
= 0;
687 entry
.item_type
= "<Tearoff>";
688 entry
.accelerator
= (gchar
*) NULL
;
689 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
690 //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
697 /* how do we delete an item-factory ? */
700 void wxMenu::SetTitle( const wxString
& title
)
702 // TODO Waiting for something better
706 const wxString
wxMenu::GetTitle() const
711 void wxMenu::AppendSeparator()
713 wxMenuItem
*mitem
= new wxMenuItem();
714 mitem
->SetId(ID_SEPARATOR
);
716 #if (GTK_MINOR_VERSION > 0)
717 GtkItemFactoryEntry entry
;
719 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
720 entry
.callback_action
= 0;
721 entry
.item_type
= "<Separator>";
722 entry
.accelerator
= (gchar
*) NULL
;
724 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
726 /* this will be wrong for more than one separator. do we care? */
727 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, "<main>/sep" );
729 GtkWidget
*menuItem
= gtk_menu_item_new();
730 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
731 gtk_widget_show( menuItem
);
734 mitem
->SetMenuItem(menuItem
);
735 m_items
.Append( mitem
);
738 static char* GetHotKey( const wxString
&hotkey
, char *hotbuf
)
740 if (hotkey
.IsEmpty()) return (char*) NULL
;
744 case _T('a'): /* Alt */
746 case _T('m'): /* Meta */
749 strcpy( hotbuf
, "<alt>" );
750 wxString last
= hotkey
.Right(1);
751 strcat( hotbuf
, last
.mb_str() );
754 case _T('c'): /* Ctrl */
756 case _T('s'): /* Strg, yeah man, I'm German */
759 strcpy( hotbuf
, "<control>" );
760 wxString last
= hotkey
.Right(1);
761 strcat( hotbuf
, last
.mb_str() );
764 case _T('F'): /* function keys */
766 strcpy( hotbuf
, hotkey
.mb_str() );
776 void wxMenu::Append( int id
, const wxString
&item
, const wxString
&helpStr
, bool checkable
)
778 wxMenuItem
*mitem
= new wxMenuItem();
780 mitem
->SetText(item
);
781 mitem
->SetHelp(helpStr
);
782 mitem
->SetCheckable(checkable
);
784 #if (GTK_MINOR_VERSION > 0)
785 /* text has "_" instead of "&" after mitem->SetText() */
786 wxString
text( mitem
->GetText() );
788 /* local buffer in multibyte form */
791 strcat( buf
, text
.mb_str() );
793 GtkItemFactoryEntry entry
;
795 entry
.callback
= (GtkItemFactoryCallback
) gtk_menu_clicked_callback
;
796 entry
.callback_action
= 0;
798 entry
.item_type
= "<CheckItem>";
800 entry
.item_type
= "<Item>";
803 entry
.accelerator
= GetHotKey( mitem
->GetHotKey(), hotbuf
);
805 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
807 /* in order to get the pointer to the item we need the item text _without_ underscores */
808 wxString s
= _T("<main>/");
809 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
811 if (*pc
== _T('_')) pc
++; /* skip it */
815 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, s
.mb_str() );
819 GtkWidget
*menuItem
= checkable
? gtk_check_menu_item_new_with_label( mitem
->GetText().mb_str() )
820 : gtk_menu_item_new_with_label( mitem
->GetText().mb_str() );
822 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
823 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
826 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
827 gtk_widget_show( menuItem
);
831 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
832 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
835 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
836 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
839 mitem
->SetMenuItem(menuItem
);
841 m_items
.Append( mitem
);
844 void wxMenu::Append( int id
, const wxString
&item
, wxMenu
*subMenu
, const wxString
&helpStr
)
846 wxMenuItem
*mitem
= new wxMenuItem();
848 mitem
->SetText(item
);
849 mitem
->SetHelp(helpStr
);
851 #if (GTK_MINOR_VERSION > 0)
852 /* text has "_" instead of "&" after mitem->SetText() */
853 wxString
text( mitem
->GetText() );
855 /* local buffer in multibyte form */
858 strcat( buf
, text
.mb_str() );
860 GtkItemFactoryEntry entry
;
862 entry
.callback
= (GtkItemFactoryCallback
) 0;
863 entry
.callback_action
= 0;
864 entry
.item_type
= "<Branch>";
866 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
868 /* in order to get the pointer to the item we need the item text _without_ underscores */
869 wxString s
= _T("<main>/");
870 for ( const wxChar
*pc
= text
; *pc
!= _T('\0'); pc
++ )
872 if (*pc
== _T('_')) pc
++; /* skip it */
876 GtkWidget
*menuItem
= gtk_item_factory_get_item( m_factory
, s
.mb_str() );
880 GtkWidget
*menuItem
= gtk_menu_item_new_with_label(mitem
->GetText().mbc_str());
882 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
883 gtk_widget_show( menuItem
);
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 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), subMenu
->m_menu
);
897 mitem
->SetMenuItem(menuItem
);
898 mitem
->SetSubMenu(subMenu
);
900 m_items
.Append( mitem
);
903 void wxMenu::Append( wxMenuItem
*item
)
905 m_items
.Append( item
);
907 GtkWidget
*menuItem
= (GtkWidget
*) NULL
;
909 if (item
->IsSeparator())
910 menuItem
= gtk_menu_item_new();
911 else if (item
->IsSubMenu())
912 menuItem
= gtk_menu_item_new_with_label(item
->GetText().mbc_str());
914 menuItem
= item
->IsCheckable() ? gtk_check_menu_item_new_with_label(item
->GetText().mbc_str())
915 : gtk_menu_item_new_with_label(item
->GetText().mbc_str());
917 if (!item
->IsSeparator())
919 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
920 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
923 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
924 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
927 if (!item
->IsSubMenu())
929 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
930 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
935 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
936 gtk_widget_show( menuItem
);
937 item
->SetMenuItem(menuItem
);
940 int wxMenu::FindItem( const wxString itemString
) const
943 for ( const wxChar
*pc
= itemString
; *pc
!= _T('\0'); pc
++ )
948 #if (GTK_MINOR_VERSION > 0)
955 wxNode
*node
= m_items
.First();
958 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
959 if (item
->GetText() == s
)
961 return item
->GetId();
969 void wxMenu::Enable( int id
, bool enable
)
971 wxMenuItem
*item
= FindItem(id
);
973 wxCHECK_RET( item
, _T("wxMenu::Enable: no such item") );
975 item
->Enable(enable
);
978 bool wxMenu::IsEnabled( int id
) const
980 wxMenuItem
*item
= FindItem(id
);
982 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsEnabled: no such item") );
984 return item
->IsEnabled();
987 void wxMenu::Check( int id
, bool enable
)
989 wxMenuItem
*item
= FindItem(id
);
991 wxCHECK_RET( item
, _T("wxMenu::Check: no such item") );
996 bool wxMenu::IsChecked( int id
) const
998 wxMenuItem
*item
= FindItem(id
);
1000 wxCHECK_MSG( item
, FALSE
, _T("wxMenu::IsChecked: no such item") );
1002 return item
->IsChecked();
1005 void wxMenu::SetLabel( int id
, const wxString
&label
)
1007 wxMenuItem
*item
= FindItem(id
);
1009 wxCHECK_RET( item
, _T("wxMenu::SetLabel: no such item") );
1011 item
->SetText(label
);
1014 wxString
wxMenu::GetLabel( int id
) const
1016 wxMenuItem
*item
= FindItem(id
);
1018 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetLabel: no such item") );
1020 return item
->GetText();
1023 void wxMenu::SetHelpString( int id
, const wxString
& helpString
)
1025 wxMenuItem
*item
= FindItem(id
);
1027 wxCHECK_RET( item
, _T("wxMenu::SetHelpString: no such item") );
1029 item
->SetHelp( helpString
);
1032 wxString
wxMenu::GetHelpString( int id
) const
1034 wxMenuItem
*item
= FindItem(id
);
1036 wxCHECK_MSG( item
, _T(""), _T("wxMenu::GetHelpString: no such item") );
1038 return item
->GetHelp();
1041 int wxMenu::FindMenuIdByMenuItem( GtkWidget
*menuItem
) const
1043 wxNode
*node
= m_items
.First();
1046 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1047 if (item
->GetMenuItem() == menuItem
)
1048 return item
->GetId();
1049 node
= node
->Next();
1055 wxMenuItem
*wxMenu::FindItem(int id
) const
1057 wxNode
*node
= m_items
.First();
1060 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1061 if (item
->GetId() == id
)
1065 node
= node
->Next();
1068 /* Not finding anything here can be correct
1069 * when search the entire menu system for
1070 * an entry -> no error message. */
1072 return (wxMenuItem
*) NULL
;
1075 void wxMenu::SetInvokingWindow( wxWindow
*win
)
1077 m_invokingWindow
= win
;
1080 wxWindow
*wxMenu::GetInvokingWindow()
1082 return m_invokingWindow
;
1085 // Update a menu and all submenus recursively. source is the object that has
1086 // the update event handlers defined for it. If NULL, the menu or associated
1087 // window will be used.
1088 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1090 if (!source
&& GetInvokingWindow())
1091 source
= GetInvokingWindow()->GetEventHandler();
1093 source
= GetEventHandler();
1097 wxNode
* node
= GetItems().First();
1100 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1101 if ( !item
->IsSeparator() )
1103 wxWindowID id
= item
->GetId();
1104 wxUpdateUIEvent
event(id
);
1105 event
.SetEventObject( source
);
1107 if (source
->ProcessEvent(event
))
1109 if (event
.GetSetText())
1110 SetLabel(id
, event
.GetText());
1111 if (event
.GetSetChecked())
1112 Check(id
, event
.GetChecked());
1113 if (event
.GetSetEnabled())
1114 Enable(id
, event
.GetEnabled());
1117 if (item
->GetSubMenu())
1118 item
->GetSubMenu()->UpdateUI(source
);
1120 node
= node
->Next();