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" 
  18 #include "wx/bitmap.h" 
  26 #include <gdk/gdkkeysyms.h> 
  29 //----------------------------------------------------------------------------- 
  31 //----------------------------------------------------------------------------- 
  33 extern void wxapp_install_idle_handler(); 
  36 #if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL 
  37 static wxString 
GetHotKey( const wxMenuItem
& item 
); 
  40 //----------------------------------------------------------------------------- 
  41 // substitute for missing GtkPixmapMenuItem 
  42 //----------------------------------------------------------------------------- 
  44 #define GTK_TYPE_PIXMAP_MENU_ITEM            (gtk_pixmap_menu_item_get_type ()) 
  45 #define GTK_PIXMAP_MENU_ITEM(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_PIXMAP_MENU_ITEM, GtkPixmapMenuItem)) 
  46 #define GTK_PIXMAP_MENU_ITEM_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_PIXMAP_MENU_ITEM, GtkPixmapMenuItemClass)) 
  47 #define GTK_IS_PIXMAP_MENU_ITEM(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_PIXMAP_MENU_ITEM)) 
  48 #define GTK_IS_PIXMAP_MENU_ITEM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PIXMAP_MENU_ITEM)) 
  49 //#define GTK_PIXMAP_MENU_ITEM_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_PIXMAP_MENU_ITEM)) 
  50 #define GTK_PIXMAP_MENU_ITEM_GET_CLASS(obj)  (GTK_PIXMAP_MENU_ITEM_CLASS( GTK_OBJECT_GET_CLASS(obj))) 
  52 #ifndef GTK_MENU_ITEM_GET_CLASS 
  53 #define GTK_MENU_ITEM_GET_CLASS(obj) (GTK_MENU_ITEM_CLASS( GTK_OBJECT_GET_CLASS(obj))) 
  56 typedef struct _GtkPixmapMenuItem       GtkPixmapMenuItem
; 
  57 typedef struct _GtkPixmapMenuItemClass  GtkPixmapMenuItemClass
; 
  59 struct _GtkPixmapMenuItem
 
  61     GtkMenuItem menu_item
; 
  66 struct _GtkPixmapMenuItemClass
 
  68     GtkMenuItemClass parent_class
; 
  70     guint orig_toggle_size
; 
  71     guint have_pixmap_count
; 
  75 GtkType    
gtk_pixmap_menu_item_get_type       (void); 
  76 GtkWidget
* gtk_pixmap_menu_item_new            (void); 
  77 void       gtk_pixmap_menu_item_set_pixmap     (GtkPixmapMenuItem 
*menu_item
, 
  80 //----------------------------------------------------------------------------- 
  82 //----------------------------------------------------------------------------- 
  84 static wxString 
wxReplaceUnderscore( const wxString
& title 
) 
  88     /* GTK 1.2 wants to have "_" instead of "&" for accelerators */ 
  90     for ( pc 
= title
; *pc 
!= wxT('\0'); pc
++ ) 
  94 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) 
  97         else if (*pc 
== wxT('/')) 
 105             if ( *pc 
== wxT('_') ) 
 107                 // underscores must be doubled to prevent them from being 
 108                 // interpreted as accelerator character prefix by GTK 
 119 //----------------------------------------------------------------------------- 
 121 //----------------------------------------------------------------------------- 
 123 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
,wxWindow
) 
 125 wxMenuBar::wxMenuBar( long style 
) 
 127     /* the parent window is known after wxFrame::SetMenu() */ 
 128     m_needParent 
= FALSE
; 
 130     m_invokingWindow 
= (wxWindow
*) NULL
; 
 132     if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize 
) || 
 133         !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("menubar") )) 
 135         wxFAIL_MSG( wxT("wxMenuBar creation failed") ); 
 139     m_menus
.DeleteContents( TRUE 
); 
 141     /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */ 
 142 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) 
 143     m_accel 
= gtk_accel_group_new(); 
 144     m_factory 
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel 
); 
 145     m_menubar 
= gtk_item_factory_get_widget( m_factory
, "<main>" ); 
 147     m_menubar 
= gtk_menu_bar_new(); 
 150     if (style 
& wxMB_DOCKABLE
) 
 152         m_widget 
= gtk_handle_box_new(); 
 153         gtk_container_add( GTK_CONTAINER(m_widget
), GTK_WIDGET(m_menubar
) ); 
 154         gtk_widget_show( GTK_WIDGET(m_menubar
) ); 
 158         m_widget 
= GTK_WIDGET(m_menubar
); 
 166 wxMenuBar::wxMenuBar() 
 168     /* the parent window is known after wxFrame::SetMenu() */ 
 169     m_needParent 
= FALSE
; 
 171     m_invokingWindow 
= (wxWindow
*) NULL
; 
 173     if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize 
) || 
 174         !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, 0, wxDefaultValidator
, wxT("menubar") )) 
 176         wxFAIL_MSG( wxT("wxMenuBar creation failed") ); 
 180     m_menus
.DeleteContents( TRUE 
); 
 182     /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */ 
 183 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) 
 184     m_accel 
= gtk_accel_group_new(); 
 185     m_factory 
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel 
); 
 186     m_menubar 
= gtk_item_factory_get_widget( m_factory
, "<main>" ); 
 188     m_menubar 
= gtk_menu_bar_new(); 
 191     m_widget 
= GTK_WIDGET(m_menubar
); 
 198 wxMenuBar::~wxMenuBar() 
 200 //    gtk_object_unref( GTK_OBJECT(m_factory) );  why not ? 
 203 static void wxMenubarUnsetInvokingWindow( wxMenu 
*menu
, wxWindow 
*win 
) 
 205     menu
->SetInvokingWindow( (wxWindow
*) NULL 
); 
 207 #if (GTK_MINOR_VERSION > 0) 
 208     wxWindow 
*top_frame 
= win
; 
 209     while (top_frame
->GetParent() && !(top_frame
->IsTopLevel())) 
 210         top_frame 
= top_frame
->GetParent(); 
 212     /* support for native hot keys  */ 
 213     gtk_accel_group_detach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) ); 
 216     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
 219         wxMenuItem 
*menuitem 
= node
->GetData(); 
 220         if (menuitem
->IsSubMenu()) 
 221             wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
 222         node 
= node
->GetNext(); 
 226 static void wxMenubarSetInvokingWindow( wxMenu 
*menu
, wxWindow 
*win 
) 
 228     menu
->SetInvokingWindow( win 
); 
 230 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) 
 231     wxWindow 
*top_frame 
= win
; 
 232     while (top_frame
->GetParent() && !(top_frame
->IsTopLevel())) 
 233         top_frame 
= top_frame
->GetParent(); 
 235     /* support for native hot keys  */ 
 236     GtkObject 
*obj 
= GTK_OBJECT(top_frame
->m_widget
); 
 237     if ( !g_slist_find( menu
->m_accel
->attach_objects
, obj 
) ) 
 238         gtk_accel_group_attach( menu
->m_accel
, obj 
); 
 241     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
 244         wxMenuItem 
*menuitem 
= node
->GetData(); 
 245         if (menuitem
->IsSubMenu()) 
 246             wxMenubarSetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
 247         node 
= node
->GetNext(); 
 251 void wxMenuBar::SetInvokingWindow( wxWindow 
*win 
) 
 253     m_invokingWindow 
= win
; 
 254 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) 
 255     wxWindow 
*top_frame 
= win
; 
 256     while (top_frame
->GetParent() && !(top_frame
->IsTopLevel())) 
 257         top_frame 
= top_frame
->GetParent(); 
 259     /* support for native key accelerators indicated by underscroes */ 
 260     GtkObject 
*obj 
= GTK_OBJECT(top_frame
->m_widget
); 
 261     if ( !g_slist_find( m_accel
->attach_objects
, obj 
) ) 
 262         gtk_accel_group_attach( m_accel
, obj 
); 
 265     wxMenuList::Node 
*node 
= m_menus
.GetFirst(); 
 268         wxMenu 
*menu 
= node
->GetData(); 
 269         wxMenubarSetInvokingWindow( menu
, win 
); 
 270         node 
= node
->GetNext(); 
 274 void wxMenuBar::UnsetInvokingWindow( wxWindow 
*win 
) 
 276     m_invokingWindow 
= (wxWindow
*) NULL
; 
 277 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) 
 278     wxWindow 
*top_frame 
= win
; 
 279     while (top_frame
->GetParent() && !(top_frame
->IsTopLevel())) 
 280         top_frame 
= top_frame
->GetParent(); 
 282     /* support for native key accelerators indicated by underscroes */ 
 283     gtk_accel_group_detach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) ); 
 286     wxMenuList::Node 
*node 
= m_menus
.GetFirst(); 
 289         wxMenu 
*menu 
= node
->GetData(); 
 290         wxMenubarUnsetInvokingWindow( menu
, win 
); 
 291         node 
= node
->GetNext(); 
 295 bool wxMenuBar::Append( wxMenu 
*menu
, const wxString 
&title 
) 
 297     if ( !wxMenuBarBase::Append( menu
, title 
) ) 
 300     return GtkAppend(menu
, title
); 
 303 bool wxMenuBar::GtkAppend(wxMenu 
*menu
, const wxString
& title
) 
 305     wxString 
str( wxReplaceUnderscore( title 
) ); 
 307     /* this doesn't have much effect right now */ 
 308     menu
->SetTitle( str 
); 
 310     /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */ 
 311 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0) 
 313     /* local buffer in multibyte form */ 
 315     buf 
<< wxT('/') << str
.c_str(); 
 317     char *cbuf 
= new char[buf
.Length()+1]; 
 318     strcpy(cbuf
, buf
.mbc_str()); 
 320     GtkItemFactoryEntry entry
; 
 321     entry
.path 
= (gchar 
*)cbuf
;  // const_cast 
 322     entry
.accelerator 
= (gchar
*) NULL
; 
 323     entry
.callback 
= (GtkItemFactoryCallback
) NULL
; 
 324     entry
.callback_action 
= 0; 
 325     entry
.item_type 
= "<Branch>"; 
 327     gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 );  /* what is 2 ? */ 
 328     /* in order to get the pointer to the item we need the item text _without_ underscores */ 
 329     wxString tmp 
= wxT("<main>/"); 
 331     for ( pc 
= str
; *pc 
!= wxT('\0'); pc
++ ) 
 333        // contrary to the common sense, we must throw out _all_ underscores, 
 334        // (i.e. "Hello__World" => "HelloWorld" and not "Hello_World" as we 
 335        // might naively think). IMHO it's a bug in GTK+ (VZ) 
 336        while (*pc 
== wxT('_')) 
 340     menu
->m_owner 
= gtk_item_factory_get_item( m_factory
, tmp
.mb_str() ); 
 341     gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu 
); 
 345     menu
->m_owner 
= gtk_menu_item_new_with_label( str
.mb_str() ); 
 346     gtk_widget_show( menu
->m_owner 
); 
 347     gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu 
); 
 349     gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), menu
->m_owner 
); 
 353     // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables 
 354     // adding menu later on. 
 355     if (m_invokingWindow
) 
 356         wxMenubarSetInvokingWindow( menu
, m_invokingWindow 
); 
 361 bool wxMenuBar::Insert(size_t pos
, wxMenu 
*menu
, const wxString
& title
) 
 363     if ( !wxMenuBarBase::Insert(pos
, menu
, title
) ) 
 367     // GTK+ doesn't have a function to insert a menu using GtkItemFactory (as 
 368     // of version 1.2.6), so we first append the item and then change its 
 370     if ( !GtkAppend(menu
, title
) ) 
 373     if (pos
+1 >= m_menus
.GetCount()) 
 376     GtkMenuShell 
*menu_shell 
= GTK_MENU_SHELL(m_factory
->widget
); 
 377     gpointer data 
= g_list_last(menu_shell
->children
)->data
; 
 378     menu_shell
->children 
= g_list_remove(menu_shell
->children
, data
); 
 379     menu_shell
->children 
= g_list_insert(menu_shell
->children
, data
, pos
); 
 383     // this should be easy to do with GTK 1.0 - can use standard functions for 
 384     // this and don't need any hacks like above, but as I don't have GTK 1.0 
 385     // any more I can't do it 
 386     wxFAIL_MSG( wxT("TODO") ); 
 389 #endif // GTK 1.2/1.0 
 392 wxMenu 
*wxMenuBar::Replace(size_t pos
, wxMenu 
*menu
, const wxString
& title
) 
 394     // remove the old item and insert a new one 
 395     wxMenu 
*menuOld 
= Remove(pos
); 
 396     if ( menuOld 
&& !Insert(pos
, menu
, title
) ) 
 398         return (wxMenu
*) NULL
; 
 401     // either Insert() succeeded or Remove() failed and menuOld is NULL 
 405 wxMenu 
*wxMenuBar::Remove(size_t pos
) 
 407     wxMenu 
*menu 
= wxMenuBarBase::Remove(pos
); 
 409         return (wxMenu
*) NULL
; 
 412     GtkMenuShell *menu_shell = GTK_MENU_SHELL(m_factory->widget); 
 414     printf( "factory entries before %d\n", (int)g_slist_length(m_factory->items) ); 
 415     printf( "menu shell entries before %d\n", (int)g_list_length( menu_shell->children ) ); 
 418     // unparent calls unref() and that would delete the widget so we raise 
 419     // the ref count to 2 artificially before invoking unparent. 
 420     gtk_widget_ref( menu
->m_menu 
); 
 421     gtk_widget_unparent( menu
->m_menu 
); 
 423     gtk_widget_destroy( menu
->m_owner 
); 
 426     printf( "factory entries after %d\n", (int)g_slist_length(m_factory->items) ); 
 427     printf( "menu shell entries after %d\n", (int)g_list_length( menu_shell->children ) ); 
 433 static int FindMenuItemRecursive( const wxMenu 
*menu
, const wxString 
&menuString
, const wxString 
&itemString 
) 
 435     if (wxMenuItem::GetLabelFromText(menu
->GetTitle()) == wxMenuItem::GetLabelFromText(menuString
)) 
 437         int res 
= menu
->FindItem( itemString 
); 
 438         if (res 
!= wxNOT_FOUND
) 
 442     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
 445         wxMenuItem 
*item 
= node
->GetData(); 
 446         if (item
->IsSubMenu()) 
 447             return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
); 
 449         node 
= node
->GetNext(); 
 455 int wxMenuBar::FindMenuItem( const wxString 
&menuString
, const wxString 
&itemString 
) const 
 457     wxMenuList::Node 
*node 
= m_menus
.GetFirst(); 
 460         wxMenu 
*menu 
= node
->GetData(); 
 461         int res 
= FindMenuItemRecursive( menu
, menuString
, itemString
); 
 464         node 
= node
->GetNext(); 
 470 // Find a wxMenuItem using its id. Recurses down into sub-menus 
 471 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
) 
 473     wxMenuItem
* result 
= menu
->FindChildItem(id
); 
 475     wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetFirst(); 
 476     while ( node 
&& result 
== NULL 
) 
 478         wxMenuItem 
*item 
= node
->GetData(); 
 479         if (item
->IsSubMenu()) 
 481             result 
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id 
); 
 483         node 
= node
->GetNext(); 
 489 wxMenuItem
* wxMenuBar::FindItem( int id
, wxMenu 
**menuForItem 
) const 
 491     wxMenuItem
* result 
= 0; 
 492     wxMenuList::Node 
*node 
= m_menus
.GetFirst(); 
 493     while (node 
&& result 
== 0) 
 495         wxMenu 
*menu 
= node
->GetData(); 
 496         result 
= FindMenuItemByIdRecursive( menu
, id 
); 
 497         node 
= node
->GetNext(); 
 502         *menuForItem 
= result 
? result
->GetMenu() : (wxMenu 
*)NULL
; 
 508 void wxMenuBar::EnableTop( size_t pos
, bool flag 
) 
 510     wxMenuList::Node 
*node 
= m_menus
.Item( pos 
); 
 512     wxCHECK_RET( node
, wxT("menu not found") ); 
 514     wxMenu
* menu 
= node
->GetData(); 
 517         gtk_widget_set_sensitive( menu
->m_owner
, flag 
); 
 520 wxString 
wxMenuBar::GetLabelTop( size_t pos 
) const 
 522     wxMenuList::Node 
*node 
= m_menus
.Item( pos 
); 
 524     wxCHECK_MSG( node
, wxT("invalid"), wxT("menu not found") ); 
 526     wxMenu
* menu 
= node
->GetData(); 
 529     wxString 
text( menu
->GetTitle() ); 
 530 #if (GTK_MINOR_VERSION > 0) 
 531     for ( const wxChar 
*pc 
= text
.c_str(); *pc
; pc
++ ) 
 533         if ( *pc 
== wxT('_') || *pc 
== wxT('&') ) 
 535             // '_' is the escape character for GTK+ and '&' is the one for 
 536             // wxWindows - skip both of them 
 544 #endif // GTK+ 1.2/1.0 
 549 void wxMenuBar::SetLabelTop( size_t pos
, const wxString
& label 
) 
 551     wxMenuList::Node 
*node 
= m_menus
.Item( pos 
); 
 553     wxCHECK_RET( node
, wxT("menu not found") ); 
 555     wxMenu
* menu 
= node
->GetData(); 
 557     wxString 
str( wxReplaceUnderscore( label 
) ); 
 559     menu
->SetTitle( str 
); 
 563         GtkLabel 
*label 
= GTK_LABEL( GTK_BIN(menu
->m_owner
)->child 
); 
 566         gtk_label_set( label
, str
.mb_str()); 
 568         /* reparse key accel */ 
 569         (void)gtk_label_parse_uline (GTK_LABEL(label
), str
.mb_str() ); 
 570         gtk_accel_label_refetch( GTK_ACCEL_LABEL(label
) ); 
 575 //----------------------------------------------------------------------------- 
 577 //----------------------------------------------------------------------------- 
 579 static void gtk_menu_clicked_callback( GtkWidget 
*widget
, wxMenu 
*menu 
) 
 581     if (g_isIdle
) wxapp_install_idle_handler(); 
 583     int id 
= menu
->FindMenuIdByMenuItem(widget
); 
 585     /* should find it for normal (not popup) menu */ 
 586     wxASSERT( (id 
!= -1) || (menu
->GetInvokingWindow() != NULL
) ); 
 588     if (!menu
->IsEnabled(id
)) 
 591     wxMenuItem
* item 
= menu
->FindChildItem( id 
); 
 592     wxCHECK_RET( item
, wxT("error in menu item callback") ); 
 594     if (item
->IsCheckable()) 
 596         bool isReallyChecked 
= item
->IsChecked(); 
 597         if ( item
->wxMenuItemBase::IsChecked() == isReallyChecked 
) 
 599             /* the menu item has been checked by calling wxMenuItem->Check() */ 
 604             /* the user pressed on the menu item -> report and make consistent 
 606             item
->wxMenuItemBase::Check(isReallyChecked
); 
 610     wxCommandEvent 
event( wxEVT_COMMAND_MENU_SELECTED
, id 
); 
 611     event
.SetEventObject( menu 
); 
 612     if (item
->IsCheckable()) 
 613         event
.SetInt( item
->IsChecked() ); 
 615 #if wxUSE_MENU_CALLBACK 
 616     if (menu
->GetCallback()) 
 618         (void) (*(menu
->GetCallback())) (*menu
, event
); 
 621 #endif // wxUSE_MENU_CALLBACK 
 623     if (menu
->GetEventHandler()->ProcessEvent(event
)) 
 626     wxWindow 
*win 
= menu
->GetInvokingWindow(); 
 628         win
->GetEventHandler()->ProcessEvent( event 
); 
 631 //----------------------------------------------------------------------------- 
 633 //----------------------------------------------------------------------------- 
 635 static void gtk_menu_hilight_callback( GtkWidget 
*widget
, wxMenu 
*menu 
) 
 637     if (g_isIdle
) wxapp_install_idle_handler(); 
 639     int id 
= menu
->FindMenuIdByMenuItem(widget
); 
 641     wxASSERT( id 
!= -1 ); // should find it! 
 643     if (!menu
->IsEnabled(id
)) 
 646     wxMenuEvent 
event( wxEVT_MENU_HIGHLIGHT
, id 
); 
 647     event
.SetEventObject( menu 
); 
 649     if (menu
->GetEventHandler()->ProcessEvent(event
)) 
 652     wxWindow 
*win 
= menu
->GetInvokingWindow(); 
 653     if (win
) win
->GetEventHandler()->ProcessEvent( event 
); 
 656 //----------------------------------------------------------------------------- 
 658 //----------------------------------------------------------------------------- 
 660 static void gtk_menu_nolight_callback( GtkWidget 
*widget
, wxMenu 
*menu 
) 
 662     if (g_isIdle
) wxapp_install_idle_handler(); 
 664     int id 
= menu
->FindMenuIdByMenuItem(widget
); 
 666     wxASSERT( id 
!= -1 ); // should find it! 
 668     if (!menu
->IsEnabled(id
)) 
 671     wxMenuEvent 
event( wxEVT_MENU_HIGHLIGHT
, -1 ); 
 672     event
.SetEventObject( menu 
); 
 674     if (menu
->GetEventHandler()->ProcessEvent(event
)) 
 677     wxWindow 
*win 
= menu
->GetInvokingWindow(); 
 679         win
->GetEventHandler()->ProcessEvent( event 
); 
 682 //----------------------------------------------------------------------------- 
 684 //----------------------------------------------------------------------------- 
 686 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxMenuItemBase
) 
 688 wxMenuItem 
*wxMenuItemBase::New(wxMenu 
*parentMenu
, 
 690                                 const wxString
& name
, 
 691                                 const wxString
& help
, 
 695     return new wxMenuItem(parentMenu
, id
, name
, help
, isCheckable
, subMenu
); 
 698 wxMenuItem::wxMenuItem(wxMenu 
*parentMenu
, 
 700                        const wxString
& text
, 
 701                        const wxString
& help
, 
 706     m_isCheckable 
= isCheckable
; 
 710     m_parentMenu 
= parentMenu
; 
 713     m_labelWidget 
= (GtkWidget 
*) NULL
; 
 714     m_menuItem 
= (GtkWidget 
*) NULL
; 
 719 wxMenuItem::~wxMenuItem() 
 721    // don't delete menu items, the menus take care of that 
 724 // return the menu item text without any menu accels 
 726 wxString 
wxMenuItemBase::GetLabelFromText(const wxString
& text
) 
 729 #if (GTK_MINOR_VERSION > 0) 
 730     for ( const wxChar 
*pc 
= text
.c_str(); *pc
; pc
++ ) 
 732         if ( *pc 
== wxT('_') || *pc 
== wxT('&') ) 
 734             // '_' is the escape character for GTK+ and '&' is the one for 
 735             // wxWindows - skip both of them 
 743 #endif // GTK+ 1.2/1.0 
 748 void wxMenuItem::SetText( const wxString
& str 
) 
 756           label 
= (GtkLabel
*) m_labelWidget
; 
 758           label 
= GTK_LABEL( GTK_BIN(m_menuItem
)->child 
); 
 761         gtk_label_set( label
, m_text
.mb_str()); 
 763         /* reparse key accel */ 
 764         (void)gtk_label_parse_uline (GTK_LABEL(label
), m_text
.mb_str() ); 
 765         gtk_accel_label_refetch( GTK_ACCEL_LABEL(label
) ); 
 769 // it's valid for this function to be called even if m_menuItem == NULL 
 770 void wxMenuItem::DoSetText( const wxString
& str 
) 
 772     /* '\t' is the deliminator indicating a hot key */ 
 774     const wxChar 
*pc 
= str
; 
 775     for (; (*pc 
!= wxT('\0')) && (*pc 
!= wxT('\t')); pc
++ ) 
 779 #if (GTK_MINOR_VERSION > 0) 
 782         else if ( *pc 
== wxT('_') )    // escape underscores 
 786         else if (*pc 
== wxT('/'))      /* we have to filter out slashes ... */ 
 788             m_text 
<< wxT('\\');  /* ... and replace them with back slashes */ 
 795     /* only GTK 1.2 knows about hot keys */ 
 797 #if (GTK_MINOR_VERSION > 0) 
 808 wxAcceleratorEntry 
*wxMenuItem::GetAccel() const 
 813         return (wxAcceleratorEntry 
*)NULL
; 
 816     // as wxGetAccelFromString() looks for TAB, insert a dummy one here 
 818     label 
<< wxT('\t') << GetHotKey(); 
 820     return wxGetAccelFromString(label
); 
 823 #endif // wxUSE_ACCEL 
 825 void wxMenuItem::Check( bool check 
) 
 827     wxCHECK_RET( m_menuItem
, wxT("invalid menu item") ); 
 829     wxCHECK_RET( IsCheckable(), wxT("Can't check uncheckable item!") ) 
 831     if (check 
== m_isChecked
) 
 834     wxMenuItemBase::Check( check 
); 
 835     gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check 
); 
 838 void wxMenuItem::Enable( bool enable 
) 
 840     wxCHECK_RET( m_menuItem
, wxT("invalid menu item") ); 
 842     gtk_widget_set_sensitive( m_menuItem
, enable 
); 
 843     wxMenuItemBase::Enable( enable 
); 
 846 bool wxMenuItem::IsChecked() const 
 848     wxCHECK_MSG( m_menuItem
, FALSE
, wxT("invalid menu item") ); 
 850     wxCHECK_MSG( IsCheckable(), FALSE
, 
 851                  wxT("can't get state of uncheckable item!") ); 
 853     return ((GtkCheckMenuItem
*)m_menuItem
)->active 
!= 0; 
 856 wxString 
wxMenuItem::GetFactoryPath() const 
 858     /* in order to get the pointer to the item we need the item text _without_ 
 860     wxString 
path( wxT("<main>/") ); 
 866 //----------------------------------------------------------------------------- 
 868 //----------------------------------------------------------------------------- 
 870 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
) 
 874 #if (GTK_MINOR_VERSION > 0) 
 875     m_accel 
= gtk_accel_group_new(); 
 876     m_factory 
= gtk_item_factory_new( GTK_TYPE_MENU
, "<main>", m_accel 
); 
 877     m_menu 
= gtk_item_factory_get_widget( m_factory
, "<main>" ); 
 879     m_menu 
= gtk_menu_new();  // Do not show! 
 882     m_owner 
= (GtkWidget
*) NULL
; 
 884 #if (GTK_MINOR_VERSION > 0) 
 885     /* Tearoffs are entries, just like separators. So if we want this 
 886        menu to be a tear-off one, we just append a tearoff entry 
 888     if(m_style 
& wxMENU_TEAROFF
) 
 890        GtkItemFactoryEntry entry
; 
 891        entry
.path 
= "/tearoff"; 
 892        entry
.callback 
= (GtkItemFactoryCallback
) NULL
; 
 893        entry
.callback_action 
= 0; 
 894        entry
.item_type 
= "<Tearoff>"; 
 895        entry
.accelerator 
= (gchar
*) NULL
; 
 896        gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 );  /* what is 2 ? */ 
 897        //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" ); 
 901     // append the title as the very first entry if we have it 
 913    gtk_widget_destroy( m_menu 
); 
 915    gtk_object_unref( GTK_OBJECT(m_factory
) ); 
 918 bool wxMenu::GtkAppend(wxMenuItem 
*mitem
) 
 922     bool appended 
= FALSE
; 
 924     if ( mitem
->IsSeparator() ) 
 926 #if (GTK_MINOR_VERSION > 0) 
 927         GtkItemFactoryEntry entry
; 
 929         entry
.callback 
= (GtkItemFactoryCallback
) NULL
; 
 930         entry
.callback_action 
= 0; 
 931         entry
.item_type 
= "<Separator>"; 
 932         entry
.accelerator 
= (gchar
*) NULL
; 
 934         gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 );  /* what is 2 ? */ 
 936         /* this will be wrong for more than one separator. do we care? */ 
 937         menuItem 
= gtk_item_factory_get_widget( m_factory
, "<main>/sep" ); 
 939         menuItem 
= gtk_menu_item_new(); 
 940 #endif // GTK 1.2/1.0 
 942     else if ( mitem
->IsSubMenu() ) 
 944 #if (GTK_MINOR_VERSION > 0) 
 945         /* text has "_" instead of "&" after mitem->SetText() */ 
 946         wxString 
text( mitem
->GetText() ); 
 948         /* local buffer in multibyte form */ 
 951         strcat( buf
, text
.mb_str() ); 
 953         GtkItemFactoryEntry entry
; 
 955         entry
.callback 
= (GtkItemFactoryCallback
) 0; 
 956         entry
.callback_action 
= 0; 
 957         entry
.item_type 
= "<Branch>"; 
 958         entry
.accelerator 
= (gchar
*) NULL
; 
 960         gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 );  /* what is 2 ? */ 
 962         wxString 
path( mitem
->GetFactoryPath() ); 
 963         menuItem 
= gtk_item_factory_get_item( m_factory
, path
.mb_str() ); 
 965         menuItem 
= gtk_menu_item_new_with_label(mitem
->GetText().mbc_str()); 
 966 #endif // GTK 1.2/1.0 
 968         gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), mitem
->GetSubMenu()->m_menu 
); 
 970         // if adding a submenu to a menu already existing in the menu bar, we 
 971         // must set invoking window to allow processing events from this 
 973         if ( m_invokingWindow 
) 
 974             wxMenubarSetInvokingWindow(mitem
->GetSubMenu(), m_invokingWindow
); 
 976     else if (mitem
->GetBitmap().Ok()) // An item with bitmap 
 978         wxString 
text( mitem
->GetText() ); 
 979         const wxBitmap 
*bitmap 
= &mitem
->GetBitmap(); 
 981         menuItem 
= gtk_pixmap_menu_item_new (); 
 982         GtkWidget 
*label 
= gtk_accel_label_new (text
.mb_str()); 
 983         gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5); 
 984         gtk_container_add (GTK_CONTAINER (menuItem
), label
); 
 985         guint accel_key 
= gtk_label_parse_uline (GTK_LABEL(label
), text
.mb_str() ); 
 986         gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label
), menuItem
); 
 987         if (accel_key 
!= GDK_VoidSymbol
) 
 989             gtk_widget_add_accelerator (menuItem
, 
 991                                         gtk_menu_ensure_uline_accel_group (GTK_MENU (m_menu
)), 
 995         gtk_widget_show (label
); 
 997         mitem
->SetLabelWidget(label
); 
 999         GtkWidget
* pixmap 
= gtk_pixmap_new( bitmap
->GetPixmap(), bitmap
->GetMask() ? bitmap
->GetMask()->GetBitmap() : (GdkBitmap
* )NULL
); 
1000         gtk_widget_show(pixmap
); 
1001         gtk_pixmap_menu_item_set_pixmap(GTK_PIXMAP_MENU_ITEM( menuItem 
), pixmap
); 
1003         gtk_signal_connect( GTK_OBJECT(menuItem
), "activate", 
1004                             GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
), 
1006         gtk_menu_append( GTK_MENU(m_menu
), menuItem 
); 
1007         gtk_widget_show( menuItem 
); 
1009         appended 
= TRUE
; // We've done this, don't do it again 
1011     else // a normal item 
1013 #if (GTK_MINOR_VERSION > 0) 
1014         /* text has "_" instead of "&" after mitem->SetText() */ 
1015         wxString 
text( mitem
->GetText() ); 
1017         /* local buffer in multibyte form */ 
1020         strcat( buf
, text
.mb_str() ); 
1022         GtkItemFactoryEntry entry
; 
1024         entry
.callback 
= (GtkItemFactoryCallback
) gtk_menu_clicked_callback
; 
1025         entry
.callback_action 
= 0; 
1026         if ( mitem
->IsCheckable() ) 
1027             entry
.item_type 
= "<CheckItem>"; 
1029             entry
.item_type 
= "<Item>"; 
1030         entry
.accelerator 
= (gchar
*) NULL
; 
1033         // due to an apparent bug in GTK+, we have to use a static buffer here - 
1034         // otherwise GTK+ 1.2.2 manages to override the memory we pass to it 
1036         static char s_accel
[50]; // must be big enougg 
1037         wxString 
tmp( GetHotKey(*mitem
) ); 
1038         strncpy(s_accel
, tmp
.mb_str(), WXSIZEOF(s_accel
)); 
1039         entry
.accelerator 
= s_accel
; 
1040 #else // !wxUSE_ACCEL 
1041         entry
.accelerator 
= (char*) NULL
; 
1042 #endif // wxUSE_ACCEL/!wxUSE_ACCEL 
1044         gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 );  /* what is 2 ? */ 
1046         wxString 
path( mitem
->GetFactoryPath() ); 
1047         menuItem 
= gtk_item_factory_get_widget( m_factory
, path
.mb_str() ); 
1049         menuItem 
= checkable 
? gtk_check_menu_item_new_with_label( mitem
->GetText().mb_str() ) 
1050                              : gtk_menu_item_new_with_label( mitem
->GetText().mb_str() ); 
1052         gtk_signal_connect( GTK_OBJECT(menuItem
), "activate", 
1053                             GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
), 
1055 #endif // GTK+ 1.2/1.0 
1058     if ( !mitem
->IsSeparator() ) 
1060         gtk_signal_connect( GTK_OBJECT(menuItem
), "select", 
1061                             GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
), 
1064         gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect", 
1065                             GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
), 
1069 #if GTK_MINOR_VERSION == 0 
1072         gtk_menu_append( GTK_MENU(m_menu
), menuItem 
); 
1073         gtk_widget_show( menuItem 
); 
1077     mitem
->SetMenuItem(menuItem
); 
1082 bool wxMenu::DoAppend(wxMenuItem 
*mitem
) 
1084     return GtkAppend(mitem
) && wxMenuBase::DoAppend(mitem
); 
1087 bool wxMenu::DoInsert(size_t pos
, wxMenuItem 
*item
) 
1089     if ( !wxMenuBase::DoInsert(pos
, item
) ) 
1093     // GTK+ doesn't have a function to insert a menu using GtkItemFactory (as 
1094     // of version 1.2.6), so we first append the item and then change its 
1096     if ( !GtkAppend(item
) ) 
1099     if ( m_style 
& wxMENU_TEAROFF 
) 
1101         // change the position as the first item is the tear-off marker 
1105     GtkMenuShell 
*menu_shell 
= GTK_MENU_SHELL(m_factory
->widget
); 
1106     gpointer data 
= g_list_last(menu_shell
->children
)->data
; 
1107     menu_shell
->children 
= g_list_remove(menu_shell
->children
, data
); 
1108     menu_shell
->children 
= g_list_insert(menu_shell
->children
, data
, pos
); 
1112     // this should be easy to do... 
1113     wxFAIL_MSG( wxT("not implemented") ); 
1116 #endif // GTK 1.2/1.0 
1119 wxMenuItem 
*wxMenu::DoRemove(wxMenuItem 
*item
) 
1121     if ( !wxMenuBase::DoRemove(item
) ) 
1122         return (wxMenuItem 
*)NULL
; 
1124     // TODO: this code doesn't delete the item factory item and this seems 
1125     //       impossible as of GTK 1.2.6. 
1126     gtk_widget_destroy( item
->GetMenuItem() ); 
1131 int wxMenu::FindMenuIdByMenuItem( GtkWidget 
*menuItem 
) const 
1133     wxNode 
*node 
= m_items
.First(); 
1136         wxMenuItem 
*item 
= (wxMenuItem
*)node
->Data(); 
1137         if (item
->GetMenuItem() == menuItem
) 
1138            return item
->GetId(); 
1139         node 
= node
->Next(); 
1145 // ---------------------------------------------------------------------------- 
1147 // ---------------------------------------------------------------------------- 
1149 #if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL 
1150 static wxString 
GetHotKey( const wxMenuItem
& item 
) 
1154     wxAcceleratorEntry 
*accel 
= item
.GetAccel(); 
1157         int flags 
= accel
->GetFlags(); 
1158         if ( flags 
& wxACCEL_ALT 
) 
1159             hotkey 
+= wxT("<alt>"); 
1160         if ( flags 
& wxACCEL_CTRL 
) 
1161             hotkey 
+= wxT("<control>"); 
1162         if ( flags 
& wxACCEL_SHIFT 
) 
1163             hotkey 
+= wxT("<shift>"); 
1165         int code 
= accel
->GetKeyCode(); 
1180                 hotkey 
<< wxT('F') << code 
- WXK_F1 
+ 1; 
1183                 // GTK seems to use XStringToKeySym here 
1184             case WXK_NUMPAD_INSERT
: 
1185                 hotkey 
<< wxT("KP_Insert" ); 
1187             case WXK_NUMPAD_DELETE
: 
1188                 hotkey 
<< wxT("KP_Delete" ); 
1191                 hotkey 
<< wxT("Insert" ); 
1194                 hotkey 
<< wxT("Delete" ); 
1197                 // if there are any other keys wxGetAccelFromString() may return, 
1198                 // we should process them here 
1201                 if ( wxIsalnum(code
) ) 
1203                     hotkey 
<< (wxChar
)code
; 
1208                 wxFAIL_MSG( wxT("unknown keyboard accel") ); 
1216 #endif // wxUSE_ACCEL 
1219 //----------------------------------------------------------------------------- 
1220 // substitute for missing GtkPixmapMenuItem 
1221 //----------------------------------------------------------------------------- 
1224  * Copyright (C) 1998, 1999, 2000 Free Software Foundation 
1225  * All rights reserved. 
1227  * This file is part of the Gnome Library. 
1229  * The Gnome Library is free software; you can redistribute it and/or 
1230  * modify it under the terms of the GNU Library General Public License as 
1231  * published by the Free Software Foundation; either version 2 of the 
1232  * License, or (at your option) any later version. 
1234  * The Gnome Library is distributed in the hope that it will be useful, 
1235  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
1236  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
1237  * Library General Public License for more details. 
1239  * You should have received a copy of the GNU Library General Public 
1240  * License along with the Gnome Library; see the file COPYING.LIB.  If not, 
1241  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
1242  * Boston, MA 02111-1307, USA. 
1248 /* Author: Dietmar Maurer <dm@vlsivie.tuwien.ac.at> */ 
1250 #include <gtk/gtkaccellabel.h> 
1251 #include <gtk/gtksignal.h> 
1252 #include <gtk/gtkmenuitem.h> 
1253 #include <gtk/gtkmenu.h> 
1254 #include <gtk/gtkcontainer.h> 
1256 static void gtk_pixmap_menu_item_class_init    (GtkPixmapMenuItemClass 
*klass
); 
1257 static void gtk_pixmap_menu_item_init          (GtkPixmapMenuItem      
*menu_item
); 
1258 static void gtk_pixmap_menu_item_draw          (GtkWidget              
*widget
, 
1259                                                 GdkRectangle           
*area
); 
1260 static gint 
gtk_pixmap_menu_item_expose        (GtkWidget              
*widget
, 
1261                                                 GdkEventExpose         
*event
); 
1263 /* we must override the following functions */ 
1265 static void gtk_pixmap_menu_item_map           (GtkWidget        
*widget
); 
1266 static void gtk_pixmap_menu_item_size_allocate (GtkWidget        
*widget
, 
1267                                                 GtkAllocation    
*allocation
); 
1268 static void gtk_pixmap_menu_item_forall        (GtkContainer    
*container
, 
1269                                                 gboolean         include_internals
, 
1270                                                 GtkCallback      callback
, 
1271                                                 gpointer         callback_data
); 
1272 static void gtk_pixmap_menu_item_size_request  (GtkWidget        
*widget
, 
1273                                                 GtkRequisition   
*requisition
); 
1274 static void gtk_pixmap_menu_item_remove        (GtkContainer 
*container
, 
1277 static void changed_have_pixmap_status         (GtkPixmapMenuItem 
*menu_item
); 
1279 static GtkMenuItemClass 
*parent_class 
= NULL
; 
1281 #define BORDER_SPACING  3 
1282 #define PMAP_WIDTH 20 
1285 gtk_pixmap_menu_item_get_type (void) 
1287   static GtkType pixmap_menu_item_type 
= 0; 
1289   if (!pixmap_menu_item_type
) 
1291       GtkTypeInfo pixmap_menu_item_info 
= 
1293         "GtkPixmapMenuItem", 
1294         sizeof (GtkPixmapMenuItem
), 
1295         sizeof (GtkPixmapMenuItemClass
), 
1296         (GtkClassInitFunc
) gtk_pixmap_menu_item_class_init
, 
1297         (GtkObjectInitFunc
) gtk_pixmap_menu_item_init
, 
1298         /* reserved_1 */ NULL
, 
1299         /* reserved_2 */ NULL
, 
1300         (GtkClassInitFunc
) NULL
, 
1303       pixmap_menu_item_type 
= gtk_type_unique (gtk_menu_item_get_type (),  
1304                                                &pixmap_menu_item_info
); 
1307   return pixmap_menu_item_type
; 
1311  * gtk_pixmap_menu_item_new 
1313  * Creates a new pixmap menu item. Use gtk_pixmap_menu_item_set_pixmap()  
1314  * to set the pixmap wich is displayed at the left side. 
1317  * &GtkWidget pointer to new menu item 
1321 gtk_pixmap_menu_item_new (void) 
1323   return GTK_WIDGET (gtk_type_new (gtk_pixmap_menu_item_get_type ())); 
1327 gtk_pixmap_menu_item_class_init (GtkPixmapMenuItemClass 
*klass
) 
1329   GtkObjectClass 
*object_class
; 
1330   GtkWidgetClass 
*widget_class
; 
1331   GtkMenuItemClass 
*menu_item_class
; 
1332   GtkContainerClass 
*container_class
; 
1334   object_class 
= (GtkObjectClass
*) klass
; 
1335   widget_class 
= (GtkWidgetClass
*) klass
; 
1336   menu_item_class 
= (GtkMenuItemClass
*) klass
; 
1337   container_class 
= (GtkContainerClass
*) klass
; 
1339   parent_class 
= (GtkMenuItemClass
*) gtk_type_class (gtk_menu_item_get_type ()); 
1341   widget_class
->draw 
= gtk_pixmap_menu_item_draw
; 
1342   widget_class
->expose_event 
= gtk_pixmap_menu_item_expose
; 
1343   widget_class
->map 
= gtk_pixmap_menu_item_map
; 
1344   widget_class
->size_allocate 
= gtk_pixmap_menu_item_size_allocate
; 
1345   widget_class
->size_request 
= gtk_pixmap_menu_item_size_request
; 
1347   container_class
->forall 
= gtk_pixmap_menu_item_forall
; 
1348   container_class
->remove 
= gtk_pixmap_menu_item_remove
; 
1350   klass
->orig_toggle_size 
= menu_item_class
->toggle_size
; 
1351   klass
->have_pixmap_count 
= 0; 
1355 gtk_pixmap_menu_item_init (GtkPixmapMenuItem 
*menu_item
) 
1359   mi 
= GTK_MENU_ITEM (menu_item
); 
1361   menu_item
->pixmap 
= NULL
; 
1365 gtk_pixmap_menu_item_draw (GtkWidget    
*widget
, 
1368   g_return_if_fail (widget 
!= NULL
); 
1369   g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (widget
)); 
1370   g_return_if_fail (area 
!= NULL
); 
1372   if (GTK_WIDGET_CLASS (parent_class
)->draw
) 
1373     (* GTK_WIDGET_CLASS (parent_class
)->draw
) (widget
, area
); 
1375   if (GTK_WIDGET_DRAWABLE (widget
) &&  
1376       GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
) { 
1377     gtk_widget_draw(GTK_WIDGET(GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
),NULL
); 
1382 gtk_pixmap_menu_item_expose (GtkWidget      
*widget
, 
1383                              GdkEventExpose 
*event
) 
1385   g_return_val_if_fail (widget 
!= NULL
, FALSE
); 
1386   g_return_val_if_fail (GTK_IS_PIXMAP_MENU_ITEM (widget
), FALSE
); 
1387   g_return_val_if_fail (event 
!= NULL
, FALSE
); 
1389   if (GTK_WIDGET_CLASS (parent_class
)->expose_event
) 
1390     (* GTK_WIDGET_CLASS (parent_class
)->expose_event
) (widget
, event
); 
1392   if (GTK_WIDGET_DRAWABLE (widget
) &&  
1393       GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
) { 
1394     gtk_widget_draw(GTK_WIDGET(GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
),NULL
); 
1401  * gtk_pixmap_menu_item_set_pixmap 
1402  * @menu_item: Pointer to the pixmap menu item 
1403  * @pixmap: Pointer to a pixmap widget 
1405  * Set the pixmap of the menu item. 
1410 gtk_pixmap_menu_item_set_pixmap (GtkPixmapMenuItem 
*menu_item
, 
1413   g_return_if_fail (menu_item 
!= NULL
); 
1414   g_return_if_fail (pixmap 
!= NULL
); 
1415   g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (menu_item
)); 
1416   g_return_if_fail (GTK_IS_WIDGET (pixmap
)); 
1417   g_return_if_fail (menu_item
->pixmap 
== NULL
); 
1419   gtk_widget_set_parent (pixmap
, GTK_WIDGET (menu_item
)); 
1420   menu_item
->pixmap 
= pixmap
; 
1422   if (GTK_WIDGET_REALIZED (pixmap
->parent
) && 
1423       !GTK_WIDGET_REALIZED (pixmap
)) 
1424     gtk_widget_realize (pixmap
); 
1426   if (GTK_WIDGET_VISIBLE (pixmap
->parent
)) {       
1427     if (GTK_WIDGET_MAPPED (pixmap
->parent
) && 
1428         GTK_WIDGET_VISIBLE(pixmap
) && 
1429         !GTK_WIDGET_MAPPED (pixmap
)) 
1430       gtk_widget_map (pixmap
); 
1433   changed_have_pixmap_status(menu_item
); 
1435   if (GTK_WIDGET_VISIBLE (pixmap
) && GTK_WIDGET_VISIBLE (menu_item
)) 
1436     gtk_widget_queue_resize (pixmap
); 
1440 gtk_pixmap_menu_item_map (GtkWidget 
*widget
) 
1442   GtkPixmapMenuItem 
*menu_item
; 
1444   g_return_if_fail (widget 
!= NULL
); 
1445   g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (widget
)); 
1447   menu_item 
= GTK_PIXMAP_MENU_ITEM(widget
); 
1449   GTK_WIDGET_CLASS(parent_class
)->map(widget
); 
1451   if (menu_item
->pixmap 
&& 
1452       GTK_WIDGET_VISIBLE (menu_item
->pixmap
) && 
1453       !GTK_WIDGET_MAPPED (menu_item
->pixmap
)) 
1454     gtk_widget_map (menu_item
->pixmap
); 
1458 gtk_pixmap_menu_item_size_allocate (GtkWidget        
*widget
, 
1459                                     GtkAllocation    
*allocation
) 
1461   GtkPixmapMenuItem 
*pmenu_item
; 
1463   pmenu_item 
= GTK_PIXMAP_MENU_ITEM(widget
); 
1465   if (pmenu_item
->pixmap 
&& GTK_WIDGET_VISIBLE(pmenu_item
)) 
1467       GtkAllocation child_allocation
; 
1470       border_width 
= GTK_CONTAINER (widget
)->border_width
; 
1472       child_allocation
.width 
= pmenu_item
->pixmap
->requisition
.width
; 
1473       child_allocation
.height 
= pmenu_item
->pixmap
->requisition
.height
; 
1474       child_allocation
.x 
= border_width 
+ BORDER_SPACING
; 
1475       child_allocation
.y 
= (border_width 
+ BORDER_SPACING
 
1476                             + (((allocation
->height 
- child_allocation
.height
) - child_allocation
.x
) 
1477                                / 2)); /* center pixmaps vertically */ 
1478       gtk_widget_size_allocate (pmenu_item
->pixmap
, &child_allocation
); 
1481   if (GTK_WIDGET_CLASS (parent_class
)->size_allocate
) 
1482     GTK_WIDGET_CLASS(parent_class
)->size_allocate (widget
, allocation
); 
1486 gtk_pixmap_menu_item_forall (GtkContainer    
*container
, 
1487                              gboolean         include_internals
, 
1488                              GtkCallback      callback
, 
1489                              gpointer         callback_data
) 
1491   GtkPixmapMenuItem 
*menu_item
; 
1493   g_return_if_fail (container 
!= NULL
); 
1494   g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (container
)); 
1495   g_return_if_fail (callback 
!= NULL
); 
1497   menu_item 
= GTK_PIXMAP_MENU_ITEM (container
); 
1499   if (menu_item
->pixmap
) 
1500     (* callback
) (menu_item
->pixmap
, callback_data
); 
1502   GTK_CONTAINER_CLASS(parent_class
)->forall(container
,include_internals
, 
1503                                             callback
,callback_data
); 
1507 gtk_pixmap_menu_item_size_request (GtkWidget      
*widget
, 
1508                                    GtkRequisition 
*requisition
) 
1510   GtkPixmapMenuItem 
*menu_item
; 
1511   GtkRequisition req 
= {0, 0}; 
1513   g_return_if_fail (widget 
!= NULL
); 
1514   g_return_if_fail (GTK_IS_MENU_ITEM (widget
)); 
1515   g_return_if_fail (requisition 
!= NULL
); 
1517   GTK_WIDGET_CLASS(parent_class
)->size_request(widget
,requisition
); 
1519   menu_item 
= GTK_PIXMAP_MENU_ITEM (widget
); 
1521   if (menu_item
->pixmap
) 
1522     gtk_widget_size_request(menu_item
->pixmap
, &req
); 
1524   requisition
->height 
= MAX(req
.height 
+ GTK_CONTAINER(widget
)->border_width 
+ BORDER_SPACING
, (unsigned int) requisition
->height
); 
1525   requisition
->width 
+= (req
.width 
+ GTK_CONTAINER(widget
)->border_width 
+ BORDER_SPACING
); 
1529 gtk_pixmap_menu_item_remove (GtkContainer 
*container
, 
1533   gboolean widget_was_visible
; 
1535   g_return_if_fail (container 
!= NULL
); 
1536   g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (container
)); 
1537   g_return_if_fail (child 
!= NULL
); 
1538   g_return_if_fail (GTK_IS_WIDGET (child
)); 
1540   bin 
= GTK_BIN (container
); 
1541   g_return_if_fail ((bin
->child 
== child 
||  
1542                      (GTK_PIXMAP_MENU_ITEM(container
)->pixmap 
== child
))); 
1544   widget_was_visible 
= GTK_WIDGET_VISIBLE (child
); 
1546   gtk_widget_unparent (child
); 
1547   if (bin
->child 
== child
) 
1550     GTK_PIXMAP_MENU_ITEM(container
)->pixmap 
= NULL
; 
1551     changed_have_pixmap_status(GTK_PIXMAP_MENU_ITEM(container
)); 
1554   if (widget_was_visible
) 
1555     gtk_widget_queue_resize (GTK_WIDGET (container
)); 
1559 /* important to only call this if there was actually a _change_ in pixmap == NULL */ 
1561 changed_have_pixmap_status (GtkPixmapMenuItem 
*menu_item
) 
1563   if (menu_item
->pixmap 
!= NULL
) { 
1564     GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count 
+= 1; 
1566     if (GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count 
== 1) { 
1567       /* Install pixmap toggle size */ 
1568       GTK_MENU_ITEM_GET_CLASS(menu_item
)->toggle_size 
= MAX(GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->orig_toggle_size
, PMAP_WIDTH
); 
1571     GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count 
-= 1; 
1573     if (GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count 
== 0) { 
1574       /* Install normal toggle size */ 
1575       GTK_MENU_ITEM_GET_CLASS(menu_item
)->toggle_size 
= GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->orig_toggle_size
;     
1579   /* Note that we actually need to do this for _all_ GtkPixmapMenuItem 
1580      whenever the klass->toggle_size changes; but by doing it anytime 
1581      this function is called, we get the same effect, just because of 
1582      how the preferences option to show pixmaps works. Bogus, broken. 
1584   if (GTK_WIDGET_VISIBLE(GTK_WIDGET(menu_item
)))  
1585     gtk_widget_queue_resize(GTK_WIDGET(menu_item
));