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"
28 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
32 extern void wxapp_install_idle_handler();
35 #if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL
36 static wxString
GetHotKey( const wxMenuItem
& item
);
39 ////// BEGIN CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////
41 #define GTK_TYPE_PIXMAP_MENU_ITEM (gtk_pixmap_menu_item_get_type ())
42 #define GTK_PIXMAP_MENU_ITEM(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_PIXMAP_MENU_ITEM, GtkPixmapMenuItem))
43 #define GTK_PIXMAP_MENU_ITEM_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_PIXMAP_MENU_ITEM, GtkPixmapMenuItemClass))
44 #define GTK_IS_PIXMAP_MENU_ITEM(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_PIXMAP_MENU_ITEM))
45 #define GTK_IS_PIXMAP_MENU_ITEM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PIXMAP_MENU_ITEM))
46 //#define GTK_PIXMAP_MENU_ITEM_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_PIXMAP_MENU_ITEM))
47 #define GTK_PIXMAP_MENU_ITEM_GET_CLASS(obj) (GTK_PIXMAP_MENU_ITEM_CLASS( GTK_OBJECT_GET_CLASS(obj)))
49 #ifndef GTK_MENU_ITEM_GET_CLASS
50 #define GTK_MENU_ITEM_GET_CLASS(obj) (GTK_MENU_ITEM_CLASS( GTK_OBJECT_GET_CLASS(obj)))
53 typedef struct _GtkPixmapMenuItem GtkPixmapMenuItem
;
54 typedef struct _GtkPixmapMenuItemClass GtkPixmapMenuItemClass
;
56 struct _GtkPixmapMenuItem
58 GtkMenuItem menu_item
;
63 struct _GtkPixmapMenuItemClass
65 GtkMenuItemClass parent_class
;
67 guint orig_toggle_size
;
68 guint have_pixmap_count
;
72 GtkType
gtk_pixmap_menu_item_get_type (void);
73 GtkWidget
* gtk_pixmap_menu_item_new (void);
74 void gtk_pixmap_menu_item_set_pixmap (GtkPixmapMenuItem
*menu_item
,
78 GtkWidget
* gtk_pixmap_menu_item_new_with_label (const gchar
*label
, GtkWidget
** labelWidget
);
80 ////// END CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////
82 //-----------------------------------------------------------------------------
84 //-----------------------------------------------------------------------------
86 static wxString
wxReplaceUnderscore( const wxString
& title
)
90 /* GTK 1.2 wants to have "_" instead of "&" for accelerators */
92 for ( pc
= title
; *pc
!= wxT('\0'); pc
++ )
96 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
99 else if (*pc
== wxT('/'))
107 if ( *pc
== wxT('_') )
109 // underscores must be doubled to prevent them from being
110 // interpreted as accelerator character prefix by GTK
121 //-----------------------------------------------------------------------------
123 //-----------------------------------------------------------------------------
125 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
,wxWindow
)
127 wxMenuBar::wxMenuBar( long style
)
129 /* the parent window is known after wxFrame::SetMenu() */
130 m_needParent
= FALSE
;
132 m_invokingWindow
= (wxWindow
*) NULL
;
134 if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize
) ||
135 !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, style
, wxDefaultValidator
, wxT("menubar") ))
137 wxFAIL_MSG( wxT("wxMenuBar creation failed") );
141 m_menus
.DeleteContents( TRUE
);
143 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
144 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
145 m_accel
= gtk_accel_group_new();
146 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel
);
147 m_menubar
= gtk_item_factory_get_widget( m_factory
, "<main>" );
149 m_menubar
= gtk_menu_bar_new();
152 if (style
& wxMB_DOCKABLE
)
154 m_widget
= gtk_handle_box_new();
155 gtk_container_add( GTK_CONTAINER(m_widget
), GTK_WIDGET(m_menubar
) );
156 gtk_widget_show( GTK_WIDGET(m_menubar
) );
160 m_widget
= GTK_WIDGET(m_menubar
);
168 wxMenuBar::wxMenuBar()
170 /* the parent window is known after wxFrame::SetMenu() */
171 m_needParent
= FALSE
;
173 m_invokingWindow
= (wxWindow
*) NULL
;
175 if (!PreCreation( (wxWindow
*) NULL
, wxDefaultPosition
, wxDefaultSize
) ||
176 !CreateBase( (wxWindow
*) NULL
, -1, wxDefaultPosition
, wxDefaultSize
, 0, wxDefaultValidator
, wxT("menubar") ))
178 wxFAIL_MSG( wxT("wxMenuBar creation failed") );
182 m_menus
.DeleteContents( TRUE
);
184 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
185 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
186 m_accel
= gtk_accel_group_new();
187 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU_BAR
, "<main>", m_accel
);
188 m_menubar
= gtk_item_factory_get_widget( m_factory
, "<main>" );
190 m_menubar
= gtk_menu_bar_new();
193 m_widget
= GTK_WIDGET(m_menubar
);
200 wxMenuBar::~wxMenuBar()
202 // gtk_object_unref( GTK_OBJECT(m_factory) ); why not ?
205 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
207 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
209 #if (GTK_MINOR_VERSION > 0)
210 wxWindow
*top_frame
= win
;
211 while (top_frame
->GetParent() && !(top_frame
->IsTopLevel()))
212 top_frame
= top_frame
->GetParent();
214 /* support for native hot keys */
215 gtk_accel_group_detach( menu
->m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
218 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
221 wxMenuItem
*menuitem
= node
->GetData();
222 if (menuitem
->IsSubMenu())
223 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu(), win
);
224 node
= node
->GetNext();
228 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
230 menu
->SetInvokingWindow( win
);
232 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
233 wxWindow
*top_frame
= win
;
234 while (top_frame
->GetParent() && !(top_frame
->IsTopLevel()))
235 top_frame
= top_frame
->GetParent();
237 /* support for native hot keys */
238 GtkObject
*obj
= GTK_OBJECT(top_frame
->m_widget
);
239 if ( !g_slist_find( menu
->m_accel
->attach_objects
, obj
) )
240 gtk_accel_group_attach( menu
->m_accel
, obj
);
243 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
246 wxMenuItem
*menuitem
= node
->GetData();
247 if (menuitem
->IsSubMenu())
248 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu(), win
);
249 node
= node
->GetNext();
253 void wxMenuBar::SetInvokingWindow( wxWindow
*win
)
255 m_invokingWindow
= win
;
256 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
257 wxWindow
*top_frame
= win
;
258 while (top_frame
->GetParent() && !(top_frame
->IsTopLevel()))
259 top_frame
= top_frame
->GetParent();
261 /* support for native key accelerators indicated by underscroes */
262 GtkObject
*obj
= GTK_OBJECT(top_frame
->m_widget
);
263 if ( !g_slist_find( m_accel
->attach_objects
, obj
) )
264 gtk_accel_group_attach( m_accel
, obj
);
267 wxMenuList::Node
*node
= m_menus
.GetFirst();
270 wxMenu
*menu
= node
->GetData();
271 wxMenubarSetInvokingWindow( menu
, win
);
272 node
= node
->GetNext();
276 void wxMenuBar::UnsetInvokingWindow( wxWindow
*win
)
278 m_invokingWindow
= (wxWindow
*) NULL
;
279 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
280 wxWindow
*top_frame
= win
;
281 while (top_frame
->GetParent() && !(top_frame
->IsTopLevel()))
282 top_frame
= top_frame
->GetParent();
284 /* support for native key accelerators indicated by underscroes */
285 gtk_accel_group_detach( m_accel
, GTK_OBJECT(top_frame
->m_widget
) );
288 wxMenuList::Node
*node
= m_menus
.GetFirst();
291 wxMenu
*menu
= node
->GetData();
292 wxMenubarUnsetInvokingWindow( menu
, win
);
293 node
= node
->GetNext();
297 bool wxMenuBar::Append( wxMenu
*menu
, const wxString
&title
)
299 if ( !wxMenuBarBase::Append( menu
, title
) )
302 return GtkAppend(menu
, title
);
305 bool wxMenuBar::GtkAppend(wxMenu
*menu
, const wxString
& title
)
307 wxString
str( wxReplaceUnderscore( title
) );
309 /* this doesn't have much effect right now */
310 menu
->SetTitle( str
);
312 /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */
313 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
315 /* local buffer in multibyte form */
317 buf
<< wxT('/') << str
.c_str();
319 char *cbuf
= new char[buf
.Length()+1];
320 strcpy(cbuf
, buf
.mbc_str());
322 GtkItemFactoryEntry entry
;
323 entry
.path
= (gchar
*)cbuf
; // const_cast
324 entry
.accelerator
= (gchar
*) NULL
;
325 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
326 entry
.callback_action
= 0;
327 entry
.item_type
= "<Branch>";
329 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
330 /* in order to get the pointer to the item we need the item text _without_ underscores */
331 wxString tmp
= wxT("<main>/");
333 for ( pc
= str
; *pc
!= wxT('\0'); pc
++ )
335 // contrary to the common sense, we must throw out _all_ underscores,
336 // (i.e. "Hello__World" => "HelloWorld" and not "Hello_World" as we
337 // might naively think). IMHO it's a bug in GTK+ (VZ)
338 while (*pc
== wxT('_'))
342 menu
->m_owner
= gtk_item_factory_get_item( m_factory
, tmp
.mb_str() );
343 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
347 menu
->m_owner
= gtk_menu_item_new_with_label( str
.mb_str() );
348 gtk_widget_show( menu
->m_owner
);
349 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu
->m_owner
), menu
->m_menu
);
351 gtk_menu_bar_append( GTK_MENU_BAR(m_menubar
), menu
->m_owner
);
355 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
356 // adding menu later on.
357 if (m_invokingWindow
)
358 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
363 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
365 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
369 // GTK+ doesn't have a function to insert a menu using GtkItemFactory (as
370 // of version 1.2.6), so we first append the item and then change its
372 if ( !GtkAppend(menu
, title
) )
375 if (pos
+1 >= m_menus
.GetCount())
378 GtkMenuShell
*menu_shell
= GTK_MENU_SHELL(m_factory
->widget
);
379 gpointer data
= g_list_last(menu_shell
->children
)->data
;
380 menu_shell
->children
= g_list_remove(menu_shell
->children
, data
);
381 menu_shell
->children
= g_list_insert(menu_shell
->children
, data
, pos
);
385 // this should be easy to do with GTK 1.0 - can use standard functions for
386 // this and don't need any hacks like above, but as I don't have GTK 1.0
387 // any more I can't do it
388 wxFAIL_MSG( wxT("TODO") );
391 #endif // GTK 1.2/1.0
394 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
396 // remove the old item and insert a new one
397 wxMenu
*menuOld
= Remove(pos
);
398 if ( menuOld
&& !Insert(pos
, menu
, title
) )
400 return (wxMenu
*) NULL
;
403 // either Insert() succeeded or Remove() failed and menuOld is NULL
407 wxMenu
*wxMenuBar::Remove(size_t pos
)
409 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
411 return (wxMenu
*) NULL
;
414 GtkMenuShell *menu_shell = GTK_MENU_SHELL(m_factory->widget);
416 printf( "factory entries before %d\n", (int)g_slist_length(m_factory->items) );
417 printf( "menu shell entries before %d\n", (int)g_list_length( menu_shell->children ) );
420 // unparent calls unref() and that would delete the widget so we raise
421 // the ref count to 2 artificially before invoking unparent.
422 gtk_widget_ref( menu
->m_menu
);
423 gtk_widget_unparent( menu
->m_menu
);
425 gtk_widget_destroy( menu
->m_owner
);
428 printf( "factory entries after %d\n", (int)g_slist_length(m_factory->items) );
429 printf( "menu shell entries after %d\n", (int)g_list_length( menu_shell->children ) );
435 static int FindMenuItemRecursive( const wxMenu
*menu
, const wxString
&menuString
, const wxString
&itemString
)
437 if (wxMenuItem::GetLabelFromText(menu
->GetTitle()) == wxMenuItem::GetLabelFromText(menuString
))
439 int res
= menu
->FindItem( itemString
);
440 if (res
!= wxNOT_FOUND
)
444 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
447 wxMenuItem
*item
= node
->GetData();
448 if (item
->IsSubMenu())
449 return FindMenuItemRecursive(item
->GetSubMenu(), menuString
, itemString
);
451 node
= node
->GetNext();
457 int wxMenuBar::FindMenuItem( const wxString
&menuString
, const wxString
&itemString
) const
459 wxMenuList::Node
*node
= m_menus
.GetFirst();
462 wxMenu
*menu
= node
->GetData();
463 int res
= FindMenuItemRecursive( menu
, menuString
, itemString
);
466 node
= node
->GetNext();
472 // Find a wxMenuItem using its id. Recurses down into sub-menus
473 static wxMenuItem
* FindMenuItemByIdRecursive(const wxMenu
* menu
, int id
)
475 wxMenuItem
* result
= menu
->FindChildItem(id
);
477 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
478 while ( node
&& result
== NULL
)
480 wxMenuItem
*item
= node
->GetData();
481 if (item
->IsSubMenu())
483 result
= FindMenuItemByIdRecursive( item
->GetSubMenu(), id
);
485 node
= node
->GetNext();
491 wxMenuItem
* wxMenuBar::FindItem( int id
, wxMenu
**menuForItem
) const
493 wxMenuItem
* result
= 0;
494 wxMenuList::Node
*node
= m_menus
.GetFirst();
495 while (node
&& result
== 0)
497 wxMenu
*menu
= node
->GetData();
498 result
= FindMenuItemByIdRecursive( menu
, id
);
499 node
= node
->GetNext();
504 *menuForItem
= result
? result
->GetMenu() : (wxMenu
*)NULL
;
510 void wxMenuBar::EnableTop( size_t pos
, bool flag
)
512 wxMenuList::Node
*node
= m_menus
.Item( pos
);
514 wxCHECK_RET( node
, wxT("menu not found") );
516 wxMenu
* menu
= node
->GetData();
519 gtk_widget_set_sensitive( menu
->m_owner
, flag
);
522 wxString
wxMenuBar::GetLabelTop( size_t pos
) const
524 wxMenuList::Node
*node
= m_menus
.Item( pos
);
526 wxCHECK_MSG( node
, wxT("invalid"), wxT("menu not found") );
528 wxMenu
* menu
= node
->GetData();
531 wxString
text( menu
->GetTitle() );
532 #if (GTK_MINOR_VERSION > 0)
533 for ( const wxChar
*pc
= text
.c_str(); *pc
; pc
++ )
535 if ( *pc
== wxT('_') || *pc
== wxT('&') )
537 // '_' is the escape character for GTK+ and '&' is the one for
538 // wxWindows - skip both of them
546 #endif // GTK+ 1.2/1.0
551 void wxMenuBar::SetLabelTop( size_t pos
, const wxString
& label
)
553 wxMenuList::Node
*node
= m_menus
.Item( pos
);
555 wxCHECK_RET( node
, wxT("menu not found") );
557 wxMenu
* menu
= node
->GetData();
559 wxString
str( wxReplaceUnderscore( label
) );
561 menu
->SetTitle( str
);
565 GtkLabel
*label
= GTK_LABEL( GTK_BIN(menu
->m_owner
)->child
);
568 gtk_label_set( label
, str
.mb_str());
570 /* reparse key accel */
571 (void)gtk_label_parse_uline (GTK_LABEL(label
), str
.mb_str() );
572 gtk_accel_label_refetch( GTK_ACCEL_LABEL(label
) );
577 //-----------------------------------------------------------------------------
579 //-----------------------------------------------------------------------------
581 static void gtk_menu_clicked_callback( GtkWidget
*widget
, wxMenu
*menu
)
583 if (g_isIdle
) wxapp_install_idle_handler();
585 int id
= menu
->FindMenuIdByMenuItem(widget
);
587 /* should find it for normal (not popup) menu */
588 wxASSERT( (id
!= -1) || (menu
->GetInvokingWindow() != NULL
) );
590 if (!menu
->IsEnabled(id
))
593 wxMenuItem
* item
= menu
->FindChildItem( id
);
594 wxCHECK_RET( item
, wxT("error in menu item callback") );
596 if (item
->IsCheckable())
598 bool isReallyChecked
= item
->IsChecked();
599 if ( item
->wxMenuItemBase::IsChecked() == isReallyChecked
)
601 /* the menu item has been checked by calling wxMenuItem->Check() */
606 /* the user pressed on the menu item -> report and make consistent
608 item
->wxMenuItemBase::Check(isReallyChecked
);
612 wxCommandEvent
event( wxEVT_COMMAND_MENU_SELECTED
, id
);
613 event
.SetEventObject( menu
);
614 if (item
->IsCheckable())
615 event
.SetInt( item
->IsChecked() );
617 #if wxUSE_MENU_CALLBACK
618 if (menu
->GetCallback())
620 (void) (*(menu
->GetCallback())) (*menu
, event
);
623 #endif // wxUSE_MENU_CALLBACK
625 if (menu
->GetEventHandler()->ProcessEvent(event
))
628 wxWindow
*win
= menu
->GetInvokingWindow();
630 win
->GetEventHandler()->ProcessEvent( event
);
633 //-----------------------------------------------------------------------------
635 //-----------------------------------------------------------------------------
637 static void gtk_menu_hilight_callback( GtkWidget
*widget
, wxMenu
*menu
)
639 if (g_isIdle
) wxapp_install_idle_handler();
641 int id
= menu
->FindMenuIdByMenuItem(widget
);
643 wxASSERT( id
!= -1 ); // should find it!
645 if (!menu
->IsEnabled(id
))
648 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, id
);
649 event
.SetEventObject( menu
);
651 if (menu
->GetEventHandler()->ProcessEvent(event
))
654 wxWindow
*win
= menu
->GetInvokingWindow();
655 if (win
) win
->GetEventHandler()->ProcessEvent( event
);
658 //-----------------------------------------------------------------------------
660 //-----------------------------------------------------------------------------
662 static void gtk_menu_nolight_callback( GtkWidget
*widget
, wxMenu
*menu
)
664 if (g_isIdle
) wxapp_install_idle_handler();
666 int id
= menu
->FindMenuIdByMenuItem(widget
);
668 wxASSERT( id
!= -1 ); // should find it!
670 if (!menu
->IsEnabled(id
))
673 wxMenuEvent
event( wxEVT_MENU_HIGHLIGHT
, -1 );
674 event
.SetEventObject( menu
);
676 if (menu
->GetEventHandler()->ProcessEvent(event
))
679 wxWindow
*win
= menu
->GetInvokingWindow();
681 win
->GetEventHandler()->ProcessEvent( event
);
684 //-----------------------------------------------------------------------------
686 //-----------------------------------------------------------------------------
688 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxMenuItemBase
)
690 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
692 const wxString
& name
,
693 const wxString
& help
,
697 return new wxMenuItem(parentMenu
, id
, name
, help
, isCheckable
, subMenu
);
700 wxMenuItem::wxMenuItem(wxMenu
*parentMenu
,
702 const wxString
& text
,
703 const wxString
& help
,
708 m_isCheckable
= isCheckable
;
712 m_parentMenu
= parentMenu
;
715 m_labelWidget
= (GtkWidget
*) NULL
;
716 m_menuItem
= (GtkWidget
*) NULL
;
721 wxMenuItem::~wxMenuItem()
723 // don't delete menu items, the menus take care of that
726 // return the menu item text without any menu accels
728 wxString
wxMenuItemBase::GetLabelFromText(const wxString
& text
)
731 #if (GTK_MINOR_VERSION > 0)
732 for ( const wxChar
*pc
= text
.c_str(); *pc
; pc
++ )
734 if ( *pc
== wxT('_') || *pc
== wxT('&') )
736 // '_' is the escape character for GTK+ and '&' is the one for
737 // wxWindows - skip both of them
745 #endif // GTK+ 1.2/1.0
750 void wxMenuItem::SetText( const wxString
& str
)
758 label
= (GtkLabel
*) m_labelWidget
;
760 label
= GTK_LABEL( GTK_BIN(m_menuItem
)->child
);
763 gtk_label_set( label
, m_text
.mb_str());
765 /* reparse key accel */
766 (void)gtk_label_parse_uline (GTK_LABEL(label
), m_text
.mb_str() );
767 gtk_accel_label_refetch( GTK_ACCEL_LABEL(label
) );
771 // it's valid for this function to be called even if m_menuItem == NULL
772 void wxMenuItem::DoSetText( const wxString
& str
)
774 /* '\t' is the deliminator indicating a hot key */
776 const wxChar
*pc
= str
;
777 for (; (*pc
!= wxT('\0')) && (*pc
!= wxT('\t')); pc
++ )
781 #if (GTK_MINOR_VERSION > 0)
784 else if ( *pc
== wxT('_') ) // escape underscores
788 else if (*pc
== wxT('/')) /* we have to filter out slashes ... */
790 m_text
<< wxT('\\'); /* ... and replace them with back slashes */
797 /* only GTK 1.2 knows about hot keys */
799 #if (GTK_MINOR_VERSION > 0)
810 wxAcceleratorEntry
*wxMenuItem::GetAccel() const
815 return (wxAcceleratorEntry
*)NULL
;
818 // as wxGetAccelFromString() looks for TAB, insert a dummy one here
820 label
<< wxT('\t') << GetHotKey();
822 return wxGetAccelFromString(label
);
825 #endif // wxUSE_ACCEL
827 void wxMenuItem::Check( bool check
)
829 wxCHECK_RET( m_menuItem
, wxT("invalid menu item") );
831 wxCHECK_RET( IsCheckable(), wxT("Can't check uncheckable item!") )
833 if (check
== m_isChecked
)
836 wxMenuItemBase::Check( check
);
837 gtk_check_menu_item_set_state( (GtkCheckMenuItem
*)m_menuItem
, (gint
)check
);
840 void wxMenuItem::Enable( bool enable
)
842 wxCHECK_RET( m_menuItem
, wxT("invalid menu item") );
844 gtk_widget_set_sensitive( m_menuItem
, enable
);
845 wxMenuItemBase::Enable( enable
);
848 bool wxMenuItem::IsChecked() const
850 wxCHECK_MSG( m_menuItem
, FALSE
, wxT("invalid menu item") );
852 wxCHECK_MSG( IsCheckable(), FALSE
,
853 wxT("can't get state of uncheckable item!") );
855 return ((GtkCheckMenuItem
*)m_menuItem
)->active
!= 0;
858 wxString
wxMenuItem::GetFactoryPath() const
860 /* in order to get the pointer to the item we need the item text _without_
862 wxString
path( wxT("<main>/") );
868 //-----------------------------------------------------------------------------
870 //-----------------------------------------------------------------------------
872 IMPLEMENT_DYNAMIC_CLASS(wxMenu
,wxEvtHandler
)
876 #if (GTK_MINOR_VERSION > 0)
877 m_accel
= gtk_accel_group_new();
878 m_factory
= gtk_item_factory_new( GTK_TYPE_MENU
, "<main>", m_accel
);
879 m_menu
= gtk_item_factory_get_widget( m_factory
, "<main>" );
881 m_menu
= gtk_menu_new(); // Do not show!
884 m_owner
= (GtkWidget
*) NULL
;
886 #if (GTK_MINOR_VERSION > 0)
887 /* Tearoffs are entries, just like separators. So if we want this
888 menu to be a tear-off one, we just append a tearoff entry
890 if(m_style
& wxMENU_TEAROFF
)
892 GtkItemFactoryEntry entry
;
893 entry
.path
= "/tearoff";
894 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
895 entry
.callback_action
= 0;
896 entry
.item_type
= "<Tearoff>";
897 entry
.accelerator
= (gchar
*) NULL
;
898 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
899 //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
903 // append the title as the very first entry if we have it
915 gtk_widget_destroy( m_menu
);
917 gtk_object_unref( GTK_OBJECT(m_factory
) );
920 bool wxMenu::GtkAppend(wxMenuItem
*mitem
)
924 bool appended
= FALSE
;
926 if ( mitem
->IsSeparator() )
928 #if (GTK_MINOR_VERSION > 0)
929 GtkItemFactoryEntry entry
;
931 entry
.callback
= (GtkItemFactoryCallback
) NULL
;
932 entry
.callback_action
= 0;
933 entry
.item_type
= "<Separator>";
934 entry
.accelerator
= (gchar
*) NULL
;
936 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
938 /* this will be wrong for more than one separator. do we care? */
939 menuItem
= gtk_item_factory_get_widget( m_factory
, "<main>/sep" );
941 menuItem
= gtk_menu_item_new();
942 #endif // GTK 1.2/1.0
944 else if ( mitem
->IsSubMenu() )
946 #if (GTK_MINOR_VERSION > 0)
947 /* text has "_" instead of "&" after mitem->SetText() */
948 wxString
text( mitem
->GetText() );
950 /* local buffer in multibyte form */
953 strcat( buf
, text
.mb_str() );
955 GtkItemFactoryEntry entry
;
957 entry
.callback
= (GtkItemFactoryCallback
) 0;
958 entry
.callback_action
= 0;
959 entry
.item_type
= "<Branch>";
960 entry
.accelerator
= (gchar
*) NULL
;
962 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
964 wxString
path( mitem
->GetFactoryPath() );
965 menuItem
= gtk_item_factory_get_item( m_factory
, path
.mb_str() );
967 menuItem
= gtk_menu_item_new_with_label(mitem
->GetText().mbc_str());
968 #endif // GTK 1.2/1.0
970 gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem
), mitem
->GetSubMenu()->m_menu
);
972 // if adding a submenu to a menu already existing in the menu bar, we
973 // must set invoking window to allow processing events from this
975 if ( m_invokingWindow
)
976 wxMenubarSetInvokingWindow(mitem
->GetSubMenu(), m_invokingWindow
);
978 else if (mitem
->GetBitmap().Ok()) // An item with bitmap
980 //// UNFINISHED, because I don't know how to handle hotkeys and
981 //// accelerators :-(
983 GtkWidget
* labelWidget
;
984 menuItem
= gtk_pixmap_menu_item_new_with_label(mitem
->GetText().mb_str(), &labelWidget
);
985 //menuItem = gtk_pixmap_menu_item_new_with_label("", &labelWidget);
986 mitem
->SetLabelWidget(labelWidget
);
988 //// TODO: should we store the widget somewhere to avoid a memory leak?
989 GtkWidget
* w
= gtk_pixmap_new(mitem
->GetBitmap().GetPixmap(), mitem
->GetBitmap().GetMask() ? mitem
->GetBitmap().GetMask()->GetBitmap() : (GdkBitmap
* )NULL
);
991 gtk_pixmap_menu_item_set_pixmap(GTK_PIXMAP_MENU_ITEM( menuItem
), w
);
993 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
994 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
996 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
997 gtk_widget_show( menuItem
);
999 //mitem->SetMenuItem(menuItem);
1000 //mitem->SetText(mitem->GetText());
1002 appended
= TRUE
; // We've done this, don't do it again
1004 else // a normal item
1006 #if (GTK_MINOR_VERSION > 0)
1007 /* text has "_" instead of "&" after mitem->SetText() */
1008 wxString
text( mitem
->GetText() );
1010 /* local buffer in multibyte form */
1013 strcat( buf
, text
.mb_str() );
1015 GtkItemFactoryEntry entry
;
1017 entry
.callback
= (GtkItemFactoryCallback
) gtk_menu_clicked_callback
;
1018 entry
.callback_action
= 0;
1019 if ( mitem
->IsCheckable() )
1020 entry
.item_type
= "<CheckItem>";
1022 entry
.item_type
= "<Item>";
1023 entry
.accelerator
= (gchar
*) NULL
;
1026 // due to an apparent bug in GTK+, we have to use a static buffer here -
1027 // otherwise GTK+ 1.2.2 manages to override the memory we pass to it
1029 static char s_accel
[50]; // must be big enougg
1030 wxString
tmp( GetHotKey(*mitem
) );
1031 strncpy(s_accel
, tmp
.mb_str(), WXSIZEOF(s_accel
));
1032 entry
.accelerator
= s_accel
;
1033 #else // !wxUSE_ACCEL
1034 entry
.accelerator
= (char*) NULL
;
1035 #endif // wxUSE_ACCEL/!wxUSE_ACCEL
1037 gtk_item_factory_create_item( m_factory
, &entry
, (gpointer
) this, 2 ); /* what is 2 ? */
1039 wxString
path( mitem
->GetFactoryPath() );
1040 menuItem
= gtk_item_factory_get_widget( m_factory
, path
.mb_str() );
1042 menuItem
= checkable
? gtk_check_menu_item_new_with_label( mitem
->GetText().mb_str() )
1043 : gtk_menu_item_new_with_label( mitem
->GetText().mb_str() );
1045 gtk_signal_connect( GTK_OBJECT(menuItem
), "activate",
1046 GTK_SIGNAL_FUNC(gtk_menu_clicked_callback
),
1048 #endif // GTK+ 1.2/1.0
1051 if ( !mitem
->IsSeparator() )
1053 gtk_signal_connect( GTK_OBJECT(menuItem
), "select",
1054 GTK_SIGNAL_FUNC(gtk_menu_hilight_callback
),
1057 gtk_signal_connect( GTK_OBJECT(menuItem
), "deselect",
1058 GTK_SIGNAL_FUNC(gtk_menu_nolight_callback
),
1062 #if GTK_MINOR_VERSION == 0
1065 gtk_menu_append( GTK_MENU(m_menu
), menuItem
);
1066 gtk_widget_show( menuItem
);
1070 mitem
->SetMenuItem(menuItem
);
1075 bool wxMenu::DoAppend(wxMenuItem
*mitem
)
1077 return GtkAppend(mitem
) && wxMenuBase::DoAppend(mitem
);
1080 bool wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
1082 if ( !wxMenuBase::DoInsert(pos
, item
) )
1086 // GTK+ doesn't have a function to insert a menu using GtkItemFactory (as
1087 // of version 1.2.6), so we first append the item and then change its
1089 if ( !GtkAppend(item
) )
1092 if ( m_style
& wxMENU_TEAROFF
)
1094 // change the position as the first item is the tear-off marker
1098 GtkMenuShell
*menu_shell
= GTK_MENU_SHELL(m_factory
->widget
);
1099 gpointer data
= g_list_last(menu_shell
->children
)->data
;
1100 menu_shell
->children
= g_list_remove(menu_shell
->children
, data
);
1101 menu_shell
->children
= g_list_insert(menu_shell
->children
, data
, pos
);
1105 // this should be easy to do...
1106 wxFAIL_MSG( wxT("not implemented") );
1109 #endif // GTK 1.2/1.0
1112 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
1114 if ( !wxMenuBase::DoRemove(item
) )
1115 return (wxMenuItem
*)NULL
;
1117 // TODO: this code doesn't delete the item factory item and this seems
1118 // impossible as of GTK 1.2.6.
1119 gtk_widget_destroy( item
->GetMenuItem() );
1124 int wxMenu::FindMenuIdByMenuItem( GtkWidget
*menuItem
) const
1126 wxNode
*node
= m_items
.First();
1129 wxMenuItem
*item
= (wxMenuItem
*)node
->Data();
1130 if (item
->GetMenuItem() == menuItem
)
1131 return item
->GetId();
1132 node
= node
->Next();
1138 // ----------------------------------------------------------------------------
1140 // ----------------------------------------------------------------------------
1142 #if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL
1143 static wxString
GetHotKey( const wxMenuItem
& item
)
1147 wxAcceleratorEntry
*accel
= item
.GetAccel();
1150 int flags
= accel
->GetFlags();
1151 if ( flags
& wxACCEL_ALT
)
1152 hotkey
+= wxT("<alt>");
1153 if ( flags
& wxACCEL_CTRL
)
1154 hotkey
+= wxT("<control>");
1155 if ( flags
& wxACCEL_SHIFT
)
1156 hotkey
+= wxT("<shift>");
1158 int code
= accel
->GetKeyCode();
1173 hotkey
<< wxT('F') << code
- WXK_F1
+ 1;
1176 // GTK seems to use XStringToKeySym here
1177 case WXK_NUMPAD_INSERT
:
1178 hotkey
<< wxT("KP_Insert" );
1180 case WXK_NUMPAD_DELETE
:
1181 hotkey
<< wxT("KP_Delete" );
1184 hotkey
<< wxT("Insert" );
1187 hotkey
<< wxT("Delete" );
1190 // if there are any other keys wxGetAccelFromString() may return,
1191 // we should process them here
1194 if ( wxIsalnum(code
) )
1196 hotkey
<< (wxChar
)code
;
1201 wxFAIL_MSG( wxT("unknown keyboard accel") );
1209 #endif // wxUSE_ACCEL
1212 ////// BEGIN CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////
1215 * Copyright (C) 1998, 1999, 2000 Free Software Foundation
1216 * All rights reserved.
1218 * This file is part of the Gnome Library.
1220 * The Gnome Library is free software; you can redistribute it and/or
1221 * modify it under the terms of the GNU Library General Public License as
1222 * published by the Free Software Foundation; either version 2 of the
1223 * License, or (at your option) any later version.
1225 * The Gnome Library is distributed in the hope that it will be useful,
1226 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1227 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1228 * Library General Public License for more details.
1230 * You should have received a copy of the GNU Library General Public
1231 * License along with the Gnome Library; see the file COPYING.LIB. If not,
1232 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1233 * Boston, MA 02111-1307, USA.
1239 /* Author: Dietmar Maurer <dm@vlsivie.tuwien.ac.at> */
1241 //#include "gtkpixmapmenuitem.h"
1242 #include <gtk/gtkaccellabel.h>
1243 #include <gtk/gtksignal.h>
1244 #include <gtk/gtkmenuitem.h>
1245 #include <gtk/gtkmenu.h>
1246 #include <gtk/gtkcontainer.h>
1248 static void gtk_pixmap_menu_item_class_init (GtkPixmapMenuItemClass
*klass
);
1249 static void gtk_pixmap_menu_item_init (GtkPixmapMenuItem
*menu_item
);
1250 static void gtk_pixmap_menu_item_draw (GtkWidget
*widget
,
1251 GdkRectangle
*area
);
1252 static gint
gtk_pixmap_menu_item_expose (GtkWidget
*widget
,
1253 GdkEventExpose
*event
);
1255 /* we must override the following functions */
1257 static void gtk_pixmap_menu_item_map (GtkWidget
*widget
);
1258 static void gtk_pixmap_menu_item_size_allocate (GtkWidget
*widget
,
1259 GtkAllocation
*allocation
);
1260 static void gtk_pixmap_menu_item_forall (GtkContainer
*container
,
1261 gboolean include_internals
,
1262 GtkCallback callback
,
1263 gpointer callback_data
);
1264 static void gtk_pixmap_menu_item_size_request (GtkWidget
*widget
,
1265 GtkRequisition
*requisition
);
1266 static void gtk_pixmap_menu_item_remove (GtkContainer
*container
,
1269 static void changed_have_pixmap_status (GtkPixmapMenuItem
*menu_item
);
1271 static GtkMenuItemClass
*parent_class
= NULL
;
1273 #define BORDER_SPACING 3
1274 #define PMAP_WIDTH 20
1277 gtk_pixmap_menu_item_get_type (void)
1279 static GtkType pixmap_menu_item_type
= 0;
1281 if (!pixmap_menu_item_type
)
1283 GtkTypeInfo pixmap_menu_item_info
=
1285 "GtkPixmapMenuItem",
1286 sizeof (GtkPixmapMenuItem
),
1287 sizeof (GtkPixmapMenuItemClass
),
1288 (GtkClassInitFunc
) gtk_pixmap_menu_item_class_init
,
1289 (GtkObjectInitFunc
) gtk_pixmap_menu_item_init
,
1290 /* reserved_1 */ NULL
,
1291 /* reserved_2 */ NULL
,
1292 (GtkClassInitFunc
) NULL
,
1295 pixmap_menu_item_type
= gtk_type_unique (gtk_menu_item_get_type (),
1296 &pixmap_menu_item_info
);
1299 return pixmap_menu_item_type
;
1303 * gtk_pixmap_menu_item_new
1305 * Creates a new pixmap menu item. Use gtk_pixmap_menu_item_set_pixmap()
1306 * to set the pixmap wich is displayed at the left side.
1309 * &GtkWidget pointer to new menu item
1313 gtk_pixmap_menu_item_new (void)
1315 return GTK_WIDGET (gtk_type_new (gtk_pixmap_menu_item_get_type ()));
1319 gtk_pixmap_menu_item_class_init (GtkPixmapMenuItemClass
*klass
)
1321 GtkObjectClass
*object_class
;
1322 GtkWidgetClass
*widget_class
;
1323 GtkMenuItemClass
*menu_item_class
;
1324 GtkContainerClass
*container_class
;
1326 object_class
= (GtkObjectClass
*) klass
;
1327 widget_class
= (GtkWidgetClass
*) klass
;
1328 menu_item_class
= (GtkMenuItemClass
*) klass
;
1329 container_class
= (GtkContainerClass
*) klass
;
1331 parent_class
= (GtkMenuItemClass
*) gtk_type_class (gtk_menu_item_get_type ());
1333 widget_class
->draw
= gtk_pixmap_menu_item_draw
;
1334 widget_class
->expose_event
= gtk_pixmap_menu_item_expose
;
1335 widget_class
->map
= gtk_pixmap_menu_item_map
;
1336 widget_class
->size_allocate
= gtk_pixmap_menu_item_size_allocate
;
1337 widget_class
->size_request
= gtk_pixmap_menu_item_size_request
;
1339 container_class
->forall
= gtk_pixmap_menu_item_forall
;
1340 container_class
->remove
= gtk_pixmap_menu_item_remove
;
1342 klass
->orig_toggle_size
= menu_item_class
->toggle_size
;
1343 klass
->have_pixmap_count
= 0;
1347 gtk_pixmap_menu_item_init (GtkPixmapMenuItem
*menu_item
)
1351 mi
= GTK_MENU_ITEM (menu_item
);
1353 menu_item
->pixmap
= NULL
;
1357 gtk_pixmap_menu_item_draw (GtkWidget
*widget
,
1360 g_return_if_fail (widget
!= NULL
);
1361 g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (widget
));
1362 g_return_if_fail (area
!= NULL
);
1364 if (GTK_WIDGET_CLASS (parent_class
)->draw
)
1365 (* GTK_WIDGET_CLASS (parent_class
)->draw
) (widget
, area
);
1367 if (GTK_WIDGET_DRAWABLE (widget
) &&
1368 GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
) {
1369 gtk_widget_draw(GTK_WIDGET(GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
),NULL
);
1374 gtk_pixmap_menu_item_expose (GtkWidget
*widget
,
1375 GdkEventExpose
*event
)
1377 g_return_val_if_fail (widget
!= NULL
, FALSE
);
1378 g_return_val_if_fail (GTK_IS_PIXMAP_MENU_ITEM (widget
), FALSE
);
1379 g_return_val_if_fail (event
!= NULL
, FALSE
);
1381 if (GTK_WIDGET_CLASS (parent_class
)->expose_event
)
1382 (* GTK_WIDGET_CLASS (parent_class
)->expose_event
) (widget
, event
);
1384 if (GTK_WIDGET_DRAWABLE (widget
) &&
1385 GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
) {
1386 gtk_widget_draw(GTK_WIDGET(GTK_PIXMAP_MENU_ITEM(widget
)->pixmap
),NULL
);
1393 * gtk_pixmap_menu_item_set_pixmap
1394 * @menu_item: Pointer to the pixmap menu item
1395 * @pixmap: Pointer to a pixmap widget
1397 * Set the pixmap of the menu item.
1402 gtk_pixmap_menu_item_set_pixmap (GtkPixmapMenuItem
*menu_item
,
1405 g_return_if_fail (menu_item
!= NULL
);
1406 g_return_if_fail (pixmap
!= NULL
);
1407 g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (menu_item
));
1408 g_return_if_fail (GTK_IS_WIDGET (pixmap
));
1409 g_return_if_fail (menu_item
->pixmap
== NULL
);
1411 gtk_widget_set_parent (pixmap
, GTK_WIDGET (menu_item
));
1412 menu_item
->pixmap
= pixmap
;
1414 if (GTK_WIDGET_REALIZED (pixmap
->parent
) &&
1415 !GTK_WIDGET_REALIZED (pixmap
))
1416 gtk_widget_realize (pixmap
);
1418 if (GTK_WIDGET_VISIBLE (pixmap
->parent
)) {
1419 if (GTK_WIDGET_MAPPED (pixmap
->parent
) &&
1420 GTK_WIDGET_VISIBLE(pixmap
) &&
1421 !GTK_WIDGET_MAPPED (pixmap
))
1422 gtk_widget_map (pixmap
);
1425 changed_have_pixmap_status(menu_item
);
1427 if (GTK_WIDGET_VISIBLE (pixmap
) && GTK_WIDGET_VISIBLE (menu_item
))
1428 gtk_widget_queue_resize (pixmap
);
1432 gtk_pixmap_menu_item_map (GtkWidget
*widget
)
1434 GtkPixmapMenuItem
*menu_item
;
1436 g_return_if_fail (widget
!= NULL
);
1437 g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (widget
));
1439 menu_item
= GTK_PIXMAP_MENU_ITEM(widget
);
1441 GTK_WIDGET_CLASS(parent_class
)->map(widget
);
1443 if (menu_item
->pixmap
&&
1444 GTK_WIDGET_VISIBLE (menu_item
->pixmap
) &&
1445 !GTK_WIDGET_MAPPED (menu_item
->pixmap
))
1446 gtk_widget_map (menu_item
->pixmap
);
1450 gtk_pixmap_menu_item_size_allocate (GtkWidget
*widget
,
1451 GtkAllocation
*allocation
)
1453 GtkPixmapMenuItem
*pmenu_item
;
1455 pmenu_item
= GTK_PIXMAP_MENU_ITEM(widget
);
1457 if (pmenu_item
->pixmap
&& GTK_WIDGET_VISIBLE(pmenu_item
))
1459 GtkAllocation child_allocation
;
1462 border_width
= GTK_CONTAINER (widget
)->border_width
;
1464 child_allocation
.width
= pmenu_item
->pixmap
->requisition
.width
;
1465 child_allocation
.height
= pmenu_item
->pixmap
->requisition
.height
;
1466 child_allocation
.x
= border_width
+ BORDER_SPACING
;
1467 child_allocation
.y
= (border_width
+ BORDER_SPACING
1468 + (((allocation
->height
- child_allocation
.height
) - child_allocation
.x
)
1469 / 2)); /* center pixmaps vertically */
1470 gtk_widget_size_allocate (pmenu_item
->pixmap
, &child_allocation
);
1473 if (GTK_WIDGET_CLASS (parent_class
)->size_allocate
)
1474 GTK_WIDGET_CLASS(parent_class
)->size_allocate (widget
, allocation
);
1478 gtk_pixmap_menu_item_forall (GtkContainer
*container
,
1479 gboolean include_internals
,
1480 GtkCallback callback
,
1481 gpointer callback_data
)
1483 GtkPixmapMenuItem
*menu_item
;
1485 g_return_if_fail (container
!= NULL
);
1486 g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (container
));
1487 g_return_if_fail (callback
!= NULL
);
1489 menu_item
= GTK_PIXMAP_MENU_ITEM (container
);
1491 if (menu_item
->pixmap
)
1492 (* callback
) (menu_item
->pixmap
, callback_data
);
1494 GTK_CONTAINER_CLASS(parent_class
)->forall(container
,include_internals
,
1495 callback
,callback_data
);
1499 gtk_pixmap_menu_item_size_request (GtkWidget
*widget
,
1500 GtkRequisition
*requisition
)
1502 GtkPixmapMenuItem
*menu_item
;
1503 GtkRequisition req
= {0, 0};
1505 g_return_if_fail (widget
!= NULL
);
1506 g_return_if_fail (GTK_IS_MENU_ITEM (widget
));
1507 g_return_if_fail (requisition
!= NULL
);
1509 GTK_WIDGET_CLASS(parent_class
)->size_request(widget
,requisition
);
1511 menu_item
= GTK_PIXMAP_MENU_ITEM (widget
);
1513 if (menu_item
->pixmap
)
1514 gtk_widget_size_request(menu_item
->pixmap
, &req
);
1516 requisition
->height
= MAX(req
.height
+ GTK_CONTAINER(widget
)->border_width
+ BORDER_SPACING
, (unsigned int) requisition
->height
);
1517 requisition
->width
+= (req
.width
+ GTK_CONTAINER(widget
)->border_width
+ BORDER_SPACING
);
1521 gtk_pixmap_menu_item_remove (GtkContainer
*container
,
1525 gboolean widget_was_visible
;
1527 g_return_if_fail (container
!= NULL
);
1528 g_return_if_fail (GTK_IS_PIXMAP_MENU_ITEM (container
));
1529 g_return_if_fail (child
!= NULL
);
1530 g_return_if_fail (GTK_IS_WIDGET (child
));
1532 bin
= GTK_BIN (container
);
1533 g_return_if_fail ((bin
->child
== child
||
1534 (GTK_PIXMAP_MENU_ITEM(container
)->pixmap
== child
)));
1536 widget_was_visible
= GTK_WIDGET_VISIBLE (child
);
1538 gtk_widget_unparent (child
);
1539 if (bin
->child
== child
)
1542 GTK_PIXMAP_MENU_ITEM(container
)->pixmap
= NULL
;
1543 changed_have_pixmap_status(GTK_PIXMAP_MENU_ITEM(container
));
1546 if (widget_was_visible
)
1547 gtk_widget_queue_resize (GTK_WIDGET (container
));
1551 /* important to only call this if there was actually a _change_ in pixmap == NULL */
1553 changed_have_pixmap_status (GtkPixmapMenuItem
*menu_item
)
1555 if (menu_item
->pixmap
!= NULL
) {
1556 GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count
+= 1;
1558 if (GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count
== 1) {
1559 /* Install pixmap toggle size */
1560 GTK_MENU_ITEM_GET_CLASS(menu_item
)->toggle_size
= MAX(GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->orig_toggle_size
, PMAP_WIDTH
);
1563 GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count
-= 1;
1565 if (GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->have_pixmap_count
== 0) {
1566 /* Install normal toggle size */
1567 GTK_MENU_ITEM_GET_CLASS(menu_item
)->toggle_size
= GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item
)->orig_toggle_size
;
1571 /* Note that we actually need to do this for _all_ GtkPixmapMenuItem
1572 whenever the klass->toggle_size changes; but by doing it anytime
1573 this function is called, we get the same effect, just because of
1574 how the preferences option to show pixmaps works. Bogus, broken.
1576 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(menu_item
)))
1577 gtk_widget_queue_resize(GTK_WIDGET(menu_item
));
1583 gtk_pixmap_menu_item_new_with_label (const gchar
*label
, GtkWidget
** labelWidget
)
1585 GtkWidget
*menu_item
;
1586 GtkWidget
*accel_label
;
1588 menu_item
= gtk_pixmap_menu_item_new ();
1589 accel_label
= gtk_accel_label_new (label
);
1591 *labelWidget
= accel_label
;
1592 gtk_misc_set_alignment (GTK_MISC (accel_label
), 0.0, 0.5);
1594 gtk_container_add (GTK_CONTAINER (menu_item
), accel_label
);
1595 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label
), menu_item
);
1596 gtk_widget_show (accel_label
);
1601 ////// END CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////