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
, wxT("menubar") ))
46 wxFAIL_MSG( wxT("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
, wxT("menubar") ))
85 wxFAIL_MSG( wxT("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 // gtk_object_unref( GTK_OBJECT(m_factory) ); why not ?
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
->GetParent()->m_isFrame
))
117 top_frame
= top_frame
->GetParent();
119 /* support for native hot keys */
120 gtk_accel_group_detach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
123 wxNode
*node
= menu
->GetItems().First();
126 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
127 if (menuitem
->IsSubMenu())
128 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu(), win
);
133 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
135 menu
->SetInvokingWindow( win
);
137 #if (GTK_MINOR_VERSION > 0)
138 wxWindow
*top_frame
= win
;
139 while (top_frame
->GetParent() && !(top_frame
->GetParent()->m_isFrame
))
140 top_frame
= top_frame
->GetParent();
142 /* support for native hot keys */
143 gtk_accel_group_attach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
146 wxNode
*node
= menu
->GetItems().First();
149 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
150 if (menuitem
->IsSubMenu())
151 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu(), win
);
156 void wxMenuBar::SetInvokingWindow( wxWindow
*win
)
158 m_invokingWindow
= win
;
159 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
160 wxWindow
*top_frame
= win
;
161 while (top_frame
->GetParent() && !(top_frame
->GetParent()->m_isFrame
))
162 top_frame
= top_frame
->GetParent();
164 /* support for native key accelerators indicated by underscroes */
165 gtk_accel_group_attach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
168 wxNode
*node
= m_menus
.First();
171 wxMenu
*menu
= (wxMenu
*)node
->Data();
172 wxMenubarSetInvokingWindow( menu
, win
);
177 void wxMenuBar::UnsetInvokingWindow( wxWindow
*win
)
179 m_invokingWindow
= (wxWindow
*) NULL
;
180 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
181 wxWindow
*top_frame
= win
;
182 while (top_frame
->GetParent() && !(top_frame
->GetParent()->m_isFrame
))
183 top_frame
= top_frame
->GetParent();
185 /* support for native key accelerators indicated by underscroes */
186 gtk_accel_group_detach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
189 wxNode
*node
= m_menus
.First();
192 wxMenu
*menu
= (wxMenu
*)node
->Data();
193 wxMenubarUnsetInvokingWindow( menu
, win
);
198 void wxMenuBar::Append( wxMenu
*menu
, const wxString
&title
)
200 m_menus
.Append( menu
);
204 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
206 for ( pc
= title
; *pc
!= wxT('\0'); pc
++ )
210 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
213 else if (*pc
== wxT('/'))
221 if ( *pc
== wxT('_') )
223 // underscores must be doubled to prevent them from being
224 // interpreted as accelerator character prefix by GTK
233 /* this doesn't have much effect right now */
234 menu
->SetTitle( str
);
236 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
237 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
239 /* local buffer in multibyte form */
241 buf
<< wxT('/') << str
.c_str();
243 char *cbuf
= new char[buf
.Length()+1];
244 strcpy(cbuf
, buf
.mbc_str());
246 GtkItemFactoryEntry entry
;
247 entry
.path
= (gchar
*)cbuf
; // const_cast
248 entry
.accelerator
= (gchar
*) NULL
;
249 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
250 entry
.callback_action
= 0;
251 entry
.item_type
= "<Branch>";
253 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
254 /* in order to get the pointer to the item we need the item text _without_ underscores */
255 wxString tmp
= wxT("<main>/");
256 for ( pc
= str
; *pc
!= wxT('\0'); pc
++ )
258 // contrary to the common sense, we must throw out _all_ underscores,
259 // (i.e. "Hello__World" => "HelloWorld" and not "Hello_World" as we
260 // might naively think). IMHO it's a bug in GTK+ (VZ)
261 while (*pc
== wxT('_'))
265 menu
->m_owner
= gtk_item_factory_get_item( m_factory
, tmp
.mb_str() );
266 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
270 menu
->m_owner
= gtk_menu_item_new_with_label( str
.mb_str() );
271 gtk_widget_show( menu
->m_owner
);
272 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
274 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), menu
->m_owner
);
278 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
279 // adding menu later on.
280 if (m_invokingWindow
)
281 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
284 static int FindMenuItemRecursive( const wxMenu
*menu
, const wxString
&menuString
, const wxString
&itemString
)
286 if (menu
->GetTitle() == menuString
)
288 int res
= menu
->FindItem( itemString
);
289 if (res
!= wxNOT_FOUND
)
293 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
296 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
297 if (item
->IsSubMenu())
298 return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
);
306 wxMenuItem
*wxMenuBar::FindItemForId(int itemId
, wxMenu
**menuForItem
) const
310 // TODO return the pointer to the menu
315 return FindItem(itemId
);
318 int wxMenuBar::FindMenuItem( const wxString
&menuString
, const wxString
&itemString
) const
320 wxNode
*node
= m_menus
.First();
323 wxMenu
*menu
= (wxMenu
*)node
->Data();
324 int res
= FindMenuItemRecursive( menu
, menuString
, itemString
);
325 if (res
!= -1) return res
;
331 // Find a wxMenuItem using its id. Recurses down into sub-menus
332 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
)
334 wxMenuItem
* result
= menu
->FindItem(id
);
336 wxNode
*node
= ((wxMenu
*)menu
)->GetItems().First(); // const_cast
337 while ( node
&& result
== NULL
)
339 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
340 if (item
->IsSubMenu())
342 result
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id
);
350 wxMenuItem
* wxMenuBar::FindItem( int id
) const
352 wxMenuItem
* result
= 0;
353 wxNode
*node
= m_menus
.First();
354 while (node
&& result
== 0)
356 wxMenu
*menu
= (wxMenu
*)node
->Data();
357 result
= FindMenuItemByIdRecursive( menu
, id
);
364 void wxMenuBar::Check( int id
, bool check
)
366 wxMenuItem
* item
= FindMenuItemById( id
);
368 wxCHECK_RET( item
, wxT("wxMenuBar::Check: no such item") );
373 bool wxMenuBar::IsChecked( int id
) const
375 wxMenuItem
* item
= FindMenuItemById( id
);
377 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsChecked: no such item") );
379 return item
->IsChecked();
382 void wxMenuBar::Enable( int id
, bool enable
)
384 wxMenuItem
* item
= FindMenuItemById( id
);
386 wxCHECK_RET( item
, wxT("wxMenuBar::Enable: no such item") );
388 item
->Enable(enable
);
391 bool wxMenuBar::IsEnabled( int id
) const
393 wxMenuItem
* item
= FindMenuItemById( id
);
395 wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsEnabled: no such item") );
397 return item
->IsEnabled();
400 wxString
wxMenuBar::GetLabel( int id
) const
402 wxMenuItem
* item
= FindMenuItemById( id
);
404 wxCHECK_MSG( item
, wxT(""), wxT("wxMenuBar::GetLabel: no such item") );
406 return item
->GetText();
409 void wxMenuBar::SetLabel( int id
, const wxString
&label
)
411 wxMenuItem
* item
= FindMenuItemById( id
);
413 wxCHECK_RET( item
, wxT("wxMenuBar::SetLabel: no such item") );
415 item
->SetText( label
);
418 void wxMenuBar::EnableTop( int pos
, bool flag
)
420 wxNode
*node
= m_menus
.Nth( pos
);
422 wxCHECK_RET( node
, wxT("menu not found") );
424 wxMenu
* menu
= (wxMenu
*)node
->Data();
427 gtk_widget_set_sensitive( menu
->m_owner
, flag
);
430 wxString
wxMenuBar::GetLabelTop( int pos
) const
432 wxNode
*node
= m_menus
.Nth( pos
);
434 wxCHECK_MSG( node
, wxT("invalid"), wxT("menu not found") );
436 wxMenu
* menu
= (wxMenu
*)node
->Data();
438 return menu
->GetTitle();
441 void wxMenuBar::SetLabelTop( int pos
, const wxString
& label
)
443 wxNode
*node
= m_menus
.Nth( pos
);
445 wxCHECK_RET( node
, wxT("menu not found") );
447 wxMenu
* menu
= (wxMenu
*)node
->Data();
449 menu
->SetTitle( label
);
452 void wxMenuBar::SetHelpString( int id
, const wxString
& helpString
)
454 wxMenuItem
* item
= FindMenuItemById( id
);
456 wxCHECK_RET( item
, wxT("wxMenuBar::SetHelpString: no such item") );
458 item
->SetHelp( helpString
);
461 wxString
wxMenuBar::GetHelpString( int id
) const
463 wxMenuItem
* item
= FindMenuItemById( id
);
465 wxCHECK_MSG( item
, wxT(""), wxT("wxMenuBar::GetHelpString: no such item") );
467 return item
->GetHelp();
470 //-----------------------------------------------------------------------------
472 //-----------------------------------------------------------------------------
474 static void gtk_menu_clicked_callback( GtkWidget
*widget
, wxMenu
*menu
)
476 if (g_isIdle
) wxapp_install_idle_handler();
478 int id
= menu
->FindMenuIdByMenuItem(widget
);
480 /* should find it for normal (not popup) menu */
481 wxASSERT( (id
!= -1) || (menu
->GetInvokingWindow() != NULL
) );
483 if (!menu
->IsEnabled(id
))
486 wxMenuItem
* item
= menu
->FindItem( id
);
487 wxCHECK_RET( item
, wxT("error in menu item callback") );
489 if (item
->IsCheckable())
491 if (item
->GetCheckedFlag() == item
->IsChecked())
493 /* the menu item has been checked by calling wxMenuItem->Check() */
498 /* the user pressed on the menu item -> report */
499 item
->SetCheckedFlag(item
->IsChecked()); /* make consistent again */
503 wxCommandEvent
event( wxEVT_COMMAND_MENU_SELECTED
, id
);
504 event
.SetEventObject( menu
);
507 if (menu
->GetCallback())
509 (void) (*(menu
->GetCallback())) (*menu
, event
);
513 if (menu
->GetEventHandler()->ProcessEvent(event
))
516 wxWindow
*win
= menu
->GetInvokingWindow();
518 win
->GetEventHandler()->ProcessEvent( event
);
521 //-----------------------------------------------------------------------------
523 //-----------------------------------------------------------------------------
525 static void gtk_menu_hilight_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
, id
);
537 event
.SetEventObject( menu
);
539 if (menu
->GetEventHandler()->ProcessEvent(event
))
542 wxWindow
*win
= menu
->GetInvokingWindow();
543 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
546 //-----------------------------------------------------------------------------
548 //-----------------------------------------------------------------------------
550 static void gtk_menu_nolight_callback( GtkWidget
*widget
, wxMenu
*menu
)
552 if (g_isIdle
) wxapp_install_idle_handler();
554 int id
= menu
->FindMenuIdByMenuItem(widget
);
556 wxASSERT( id
!= -1 ); // should find it!
558 if (!menu
->IsEnabled(id
))
561 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, -1 );
562 event
.SetEventObject( menu
);
564 if (menu
->GetEventHandler()->ProcessEvent(event
))
567 wxWindow
*win
= menu
->GetInvokingWindow();
569 win
->GetEventHandler()->ProcessEvent( event
);
572 //-----------------------------------------------------------------------------
574 //-----------------------------------------------------------------------------
576 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
,wxObject
)
578 wxMenuItem::wxMenuItem()
581 m_isCheckMenu
= FALSE
;
584 m_subMenu
= (wxMenu
*) NULL
;
585 m_menuItem
= (GtkWidget
*) NULL
;
588 wxMenuItem::~wxMenuItem()
590 // don't delete menu items, the menus take care of that
593 // it's valid for this function to be called even if m_menuItem == NULL
594 void wxMenuItem::SetName( const wxString
& str
)
596 /* '\t' is the deliminator indicating a hot key */
598 const wxChar
*pc
= str
;
599 for (; (*pc
!= wxT('\0')) && (*pc
!= wxT('\t')); pc
++ )
603 #if (GTK_MINOR_VERSION > 0)
606 else if ( *pc
== wxT('_') ) // escape underscores
610 else if (*pc
== wxT('/')) /* we have to filter out slashes ... */
612 m_text
<< wxT('\\'); /* ... and replace them with back slashes */
619 /* only GTK 1.2 knows about hot keys */
621 #if (GTK_MINOR_VERSION > 0)
631 GtkLabel
*label
= GTK_LABEL( GTK_BIN(m_menuItem
)->child
);
632 gtk_label_set( label
, m_text
.mb_str());
636 void wxMenuItem::Check( bool check
)
638 wxCHECK_RET( m_menuItem
, wxT("invalid menu item") );
640 wxCHECK_RET( IsCheckable(), wxT("Can't check uncheckable item!") )
642 if (check
== m_isChecked
) return;
645 gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check
);
648 void wxMenuItem::Enable( bool enable
)
650 wxCHECK_RET( m_menuItem
, wxT("invalid menu item") );
652 gtk_widget_set_sensitive( m_menuItem
, enable
);
653 m_isEnabled
= enable
;
656 bool wxMenuItem::IsChecked() const
658 wxCHECK_MSG( m_menuItem
, FALSE
, wxT("invalid menu item") );
660 wxCHECK( IsCheckable(), FALSE
); // can't get state of uncheckable item!
662 bool bIsChecked
= ((GtkCheckMenuItem
*)m_menuItem
)->active
!= 0;
667 //-----------------------------------------------------------------------------
669 //-----------------------------------------------------------------------------
671 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
)
674 wxMenu::Init( const wxString
& title
,
676 const wxFunction func
680 m_items
.DeleteContents( TRUE
);
681 m_invokingWindow
= (wxWindow
*) NULL
;
684 #if (GTK_MINOR_VERSION > 0)
685 m_accel
= gtk_accel_group_new();
686 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU
, "<main>", m_accel
);
687 m_menu
= gtk_item_factory_get_widget( m_factory
, "<main>" );
689 m_menu
= gtk_menu_new(); // Do not show!
694 m_eventHandler
= this;
695 m_clientData
= (void*) NULL
;
697 if (m_title
.IsNull()) m_title
= wxT("");
698 if (m_title
!= wxT(""))
704 m_owner
= (GtkWidget
*) NULL
;
706 #if (GTK_MINOR_VERSION > 0)
707 /* Tearoffs are entries, just like separators. So if we want this
708 menu to be a tear-off one, we just append a tearoff entry
710 if(m_style
& wxMENU_TEAROFF
)
712 GtkItemFactoryEntry entry
;
713 entry
.path
= "/tearoff";
714 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
715 entry
.callback_action
= 0;
716 entry
.item_type
= "<Tearoff>";
717 entry
.accelerator
= (gchar
*) NULL
;
718 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
719 //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
726 wxNode
*node
= m_items
.First();
729 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
730 wxMenu
*submenu
= item
->GetSubMenu();
736 gtk_widget_destroy( m_menu
);
738 gtk_object_unref( GTK_OBJECT(m_factory
) );
741 void wxMenu::SetTitle( const wxString
& title
)
743 // TODO Waiting for something better
747 const wxString
wxMenu::GetTitle() const
752 void wxMenu::AppendSeparator()
754 wxMenuItem
*mitem
= new wxMenuItem();
755 mitem
->SetId(ID_SEPARATOR
);
757 #if (GTK_MINOR_VERSION > 0)
758 GtkItemFactoryEntry entry
;
760 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
761 entry
.callback_action
= 0;
762 entry
.item_type
= "<Separator>";
763 entry
.accelerator
= (gchar
*) NULL
;
765 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
767 /* this will be wrong for more than one separator. do we care? */
768 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, "<main>/sep" );
770 GtkWidget
*menuItem
= gtk_menu_item_new();
771 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
772 gtk_widget_show( menuItem
);
775 mitem
->SetMenuItem(menuItem
);
776 m_items
.Append( mitem
);
779 #if (GTK_MINOR_VERSION > 0)
780 static char* GetHotKey( const wxString
&hotkey
, char *hotbuf
)
782 if (hotkey
.IsEmpty()) return (char*) NULL
;
786 case wxT('a'): /* Alt */
788 case wxT('m'): /* Meta */
791 strcpy( hotbuf
, "<alt>" );
792 wxString last
= hotkey
.Right(1);
793 strcat( hotbuf
, last
.mb_str() );
796 case wxT('c'): /* Ctrl */
798 case wxT('s'): /* Strg, yeah man, I'm German */
801 strcpy( hotbuf
, "<control>" );
802 wxString last
= hotkey
.Right(1);
803 strcat( hotbuf
, last
.mb_str() );
806 case wxT('F'): /* function keys */
808 strcpy( hotbuf
, hotkey
.mb_str() );
819 void wxMenu::Append( int id
, const wxString
&item
, const wxString
&helpStr
, bool checkable
)
821 wxMenuItem
*mitem
= new wxMenuItem();
823 mitem
->SetText(item
);
824 mitem
->SetHelp(helpStr
);
825 mitem
->SetCheckable(checkable
);
827 #if (GTK_MINOR_VERSION > 0)
828 /* text has "_" instead of "&" after mitem->SetText() */
829 wxString
text( mitem
->GetText() );
831 /* local buffer in multibyte form */
834 strcat( buf
, text
.mb_str() );
836 GtkItemFactoryEntry entry
;
838 entry
.callback
= (GtkItemFactoryCallback
) gtk_menu_clicked_callback
;
839 entry
.callback_action
= 0;
841 entry
.item_type
= "<CheckItem>";
843 entry
.item_type
= "<Item>";
846 entry
.accelerator
= GetHotKey( mitem
->GetHotKey(), hotbuf
);
848 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
850 /* in order to get the pointer to the item we need the item text _without_ underscores */
851 wxString s
= wxT("<main>/");
852 for ( const wxChar
*pc
= text
; *pc
!= wxT('\0'); pc
++ )
854 while (*pc
== wxT('_')) pc
++; /* skip it */
858 GtkWidget
*menuItem
= gtk_item_factory_get_widget( m_factory
, s
.mb_str() );
862 GtkWidget
*menuItem
= checkable
? gtk_check_menu_item_new_with_label( mitem
->GetText().mb_str() )
863 : gtk_menu_item_new_with_label( mitem
->GetText().mb_str() );
865 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
866 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
869 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
870 gtk_widget_show( menuItem
);
874 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
875 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
878 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
879 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
882 mitem
->SetMenuItem(menuItem
);
884 m_items
.Append( mitem
);
887 void wxMenu::Append( int id
, const wxString
&item
, wxMenu
*subMenu
, const wxString
&helpStr
)
889 wxMenuItem
*mitem
= new wxMenuItem();
891 mitem
->SetText(item
);
892 mitem
->SetHelp(helpStr
);
894 #if (GTK_MINOR_VERSION > 0)
895 /* text has "_" instead of "&" after mitem->SetText() */
896 wxString
text( mitem
->GetText() );
898 /* local buffer in multibyte form */
901 strcat( buf
, text
.mb_str() );
903 GtkItemFactoryEntry entry
;
905 entry
.callback
= (GtkItemFactoryCallback
) 0;
906 entry
.callback_action
= 0;
907 entry
.item_type
= "<Branch>";
909 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
911 /* in order to get the pointer to the item we need the item text _without_ underscores */
912 wxString s
= wxT("<main>/");
913 for ( const wxChar
*pc
= text
; *pc
!= wxT('\0'); pc
++ )
915 if (*pc
== wxT('_')) pc
++; /* skip it */
919 GtkWidget
*menuItem
= gtk_item_factory_get_item( m_factory
, s
.mb_str() );
923 GtkWidget
*menuItem
= gtk_menu_item_new_with_label(mitem
->GetText().mbc_str());
925 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
926 gtk_widget_show( menuItem
);
930 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
931 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
934 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
935 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
938 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), subMenu
->m_menu
);
940 mitem
->SetMenuItem(menuItem
);
941 mitem
->SetSubMenu(subMenu
);
943 m_items
.Append( mitem
);
946 void wxMenu::Append( wxMenuItem
*item
)
948 m_items
.Append( item
);
950 GtkWidget
*menuItem
= (GtkWidget
*) NULL
;
952 if (item
->IsSeparator())
953 menuItem
= gtk_menu_item_new();
954 else if (item
->IsSubMenu())
955 menuItem
= gtk_menu_item_new_with_label(item
->GetText().mbc_str());
957 menuItem
= item
->IsCheckable() ? gtk_check_menu_item_new_with_label(item
->GetText().mbc_str())
958 : gtk_menu_item_new_with_label(item
->GetText().mbc_str());
960 if (!item
->IsSeparator())
962 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
963 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
966 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
967 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
970 if (!item
->IsSubMenu())
972 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
973 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
978 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
979 gtk_widget_show( menuItem
);
980 item
->SetMenuItem(menuItem
);
983 void wxMenu::Delete( int id
)
985 wxNode
*node
= m_items
.First();
988 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
989 if (item
->GetId() == id
)
991 gtk_widget_destroy( item
->GetMenuItem() );
992 m_items
.DeleteNode( node
);
999 int wxMenu::FindItem( const wxString itemString
) const
1001 wxString s
= wxT("");
1002 for ( const wxChar
*pc
= itemString
; *pc
!= wxT('\0'); pc
++ )
1004 if (*pc
== wxT('&'))
1007 #if (GTK_MINOR_VERSION > 0)
1014 wxNode
*node
= m_items
.First();
1017 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1018 if (item
->GetText() == s
)
1020 return item
->GetId();
1022 node
= node
->Next();
1028 void wxMenu::Enable( int id
, bool enable
)
1030 wxMenuItem
*item
= FindItem(id
);
1032 wxCHECK_RET( item
, wxT("wxMenu::Enable: no such item") );
1034 item
->Enable(enable
);
1037 bool wxMenu::IsEnabled( int id
) const
1039 wxMenuItem
*item
= FindItem(id
);
1041 wxCHECK_MSG( item
, FALSE
, wxT("wxMenu::IsEnabled: no such item") );
1043 return item
->IsEnabled();
1046 void wxMenu::Check( int id
, bool enable
)
1048 wxMenuItem
*item
= FindItem(id
);
1050 wxCHECK_RET( item
, wxT("wxMenu::Check: no such item") );
1052 item
->Check(enable
);
1055 bool wxMenu::IsChecked( int id
) const
1057 wxMenuItem
*item
= FindItem(id
);
1059 wxCHECK_MSG( item
, FALSE
, wxT("wxMenu::IsChecked: no such item") );
1061 return item
->IsChecked();
1064 void wxMenu::SetLabel( int id
, const wxString
&label
)
1066 wxMenuItem
*item
= FindItem(id
);
1068 wxCHECK_RET( item
, wxT("wxMenu::SetLabel: no such item") );
1070 item
->SetText(label
);
1073 wxString
wxMenu::GetLabel( int id
) const
1075 wxMenuItem
*item
= FindItem(id
);
1077 wxCHECK_MSG( item
, wxT(""), wxT("wxMenu::GetLabel: no such item") );
1079 return item
->GetText();
1082 void wxMenu::SetHelpString( int id
, const wxString
& helpString
)
1084 wxMenuItem
*item
= FindItem(id
);
1086 wxCHECK_RET( item
, wxT("wxMenu::SetHelpString: no such item") );
1088 item
->SetHelp( helpString
);
1091 wxString
wxMenu::GetHelpString( int id
) const
1093 wxMenuItem
*item
= FindItem(id
);
1095 wxCHECK_MSG( item
, wxT(""), wxT("wxMenu::GetHelpString: no such item") );
1097 return item
->GetHelp();
1100 int wxMenu::FindMenuIdByMenuItem( GtkWidget
*menuItem
) const
1102 wxNode
*node
= m_items
.First();
1105 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1106 if (item
->GetMenuItem() == menuItem
)
1107 return item
->GetId();
1108 node
= node
->Next();
1114 wxMenuItem
*wxMenu::FindItem(int id
) const
1116 wxNode
*node
= m_items
.First();
1119 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1120 if (item
->GetId() == id
)
1124 node
= node
->Next();
1127 /* Not finding anything here can be correct
1128 * when search the entire menu system for
1129 * an entry -> no error message. */
1131 return (wxMenuItem
*) NULL
;
1134 void wxMenu::SetInvokingWindow( wxWindow
*win
)
1136 m_invokingWindow
= win
;
1139 wxWindow
*wxMenu::GetInvokingWindow()
1141 return m_invokingWindow
;
1144 // Update a menu and all submenus recursively. source is the object that has
1145 // the update event handlers defined for it. If NULL, the menu or associated
1146 // window will be used.
1147 void wxMenu::UpdateUI(wxEvtHandler
* source
)
1149 if (!source
&& GetInvokingWindow())
1150 source
= GetInvokingWindow()->GetEventHandler();
1152 source
= GetEventHandler();
1156 wxNode
* node
= GetItems().First();
1159 wxMenuItem
* item
= (wxMenuItem
*) node
->Data();
1160 if ( !item
->IsSeparator() )
1162 wxWindowID id
= item
->GetId();
1163 wxUpdateUIEvent
event(id
);
1164 event
.SetEventObject( source
);
1166 if (source
->ProcessEvent(event
))
1168 if (event
.GetSetText())
1169 SetLabel(id
, event
.GetText());
1170 if (event
.GetSetChecked())
1171 Check(id
, event
.GetChecked());
1172 if (event
.GetSetEnabled())
1173 Enable(id
, event
.GetEnabled());
1176 if (item
->GetSubMenu())
1177 item
->GetSubMenu()->UpdateUI(source
);
1179 node
= node
->Next();