]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolitem.c
Call gtk_tool_item_rebuild_menu().
[~andy/gtk] / gtk / gtktoolitem.c
1 /* gtktoolitem.c
2  *
3  * Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
4  * Copyright (C) 2002 James Henstridge <james@daa.com.au>
5  * Copyright (C) 2003 Soeren Sandmann <sandmann@daimi.au.dk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <config.h>
24 #include "gtkalias.h"
25 #include "gtktoolitem.h"
26 #include "gtkmarshalers.h"
27 #include "gtktoolbar.h"
28 #include "gtkseparatormenuitem.h"
29 #include "gtkintl.h"
30 #include "gtkmain.h"
31
32 #include <string.h>
33
34 enum {
35   CREATE_MENU_PROXY,
36   TOOLBAR_RECONFIGURED,
37   SET_TOOLTIP,
38   LAST_SIGNAL
39 };
40
41 enum {
42   PROP_0,
43   PROP_VISIBLE_HORIZONTAL,
44   PROP_VISIBLE_VERTICAL,
45   PROP_IS_IMPORTANT
46 };
47
48 #define GTK_TOOL_ITEM_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOL_ITEM, GtkToolItemPrivate))
49
50 struct _GtkToolItemPrivate
51 {
52   gchar *tip_text;
53   gchar *tip_private;
54
55   guint visible_horizontal : 1;
56   guint visible_vertical : 1;
57   guint homogeneous : 1;
58   guint expand : 1;
59   guint use_drag_window : 1;
60   guint is_important : 1;
61
62   GdkWindow *drag_window;
63   
64   gchar *menu_item_id;
65   GtkWidget *menu_item;
66 };
67   
68 static void gtk_tool_item_init       (GtkToolItem *toolitem);
69 static void gtk_tool_item_class_init (GtkToolItemClass *class);
70 static void gtk_tool_item_finalize    (GObject *object);
71 static void gtk_tool_item_parent_set   (GtkWidget   *toolitem,
72                                         GtkWidget   *parent);
73 static void gtk_tool_item_set_property (GObject         *object,
74                                         guint            prop_id,
75                                         const GValue    *value,
76                                         GParamSpec      *pspec);
77 static void gtk_tool_item_get_property (GObject         *object,
78                                         guint            prop_id,
79                                         GValue          *value,
80                                         GParamSpec      *pspec);
81 static void gtk_tool_item_property_notify (GObject      *object,
82                                            GParamSpec   *pspec);
83 static void gtk_tool_item_realize       (GtkWidget      *widget);
84 static void gtk_tool_item_unrealize     (GtkWidget      *widget);
85 static void gtk_tool_item_map           (GtkWidget      *widget);
86 static void gtk_tool_item_unmap         (GtkWidget      *widget);
87 static void gtk_tool_item_size_request  (GtkWidget      *widget,
88                                          GtkRequisition *requisition);
89 static void gtk_tool_item_size_allocate (GtkWidget      *widget,
90                                          GtkAllocation  *allocation);
91 static gboolean gtk_tool_item_real_set_tooltip (GtkToolItem *tool_item,
92                                                 GtkTooltips *tooltips,
93                                                 const gchar *tip_text,
94                                                 const gchar *tip_private);
95
96 static gboolean gtk_tool_item_create_menu_proxy (GtkToolItem *item);
97
98
99 static GObjectClass *parent_class = NULL;
100 static guint         toolitem_signals[LAST_SIGNAL] = { 0 };
101
102 GType
103 gtk_tool_item_get_type (void)
104 {
105   static GtkType type = 0;
106
107   if (!type)
108     {
109       static const GTypeInfo type_info =
110         {
111           sizeof (GtkToolItemClass),
112           (GBaseInitFunc) NULL,
113           (GBaseFinalizeFunc) NULL,
114           (GClassInitFunc) gtk_tool_item_class_init,
115           (GClassFinalizeFunc) NULL,
116           NULL,
117         
118           sizeof (GtkToolItem),
119           0, /* n_preallocs */
120           (GInstanceInitFunc) gtk_tool_item_init,
121         };
122
123       type = g_type_register_static (GTK_TYPE_BIN,
124                                      "GtkToolItem",
125                                      &type_info, 0);
126     }
127   return type;
128 }
129
130 static void
131 gtk_tool_item_class_init (GtkToolItemClass *klass)
132 {
133   GObjectClass *object_class;
134   GtkWidgetClass *widget_class;
135   
136   parent_class = g_type_class_peek_parent (klass);
137   object_class = (GObjectClass *)klass;
138   widget_class = (GtkWidgetClass *)klass;
139   
140   object_class->set_property = gtk_tool_item_set_property;
141   object_class->get_property = gtk_tool_item_get_property;
142   object_class->finalize = gtk_tool_item_finalize;
143   object_class->notify = gtk_tool_item_property_notify;
144
145   widget_class->realize       = gtk_tool_item_realize;
146   widget_class->unrealize     = gtk_tool_item_unrealize;
147   widget_class->map           = gtk_tool_item_map;
148   widget_class->unmap         = gtk_tool_item_unmap;
149   widget_class->size_request  = gtk_tool_item_size_request;
150   widget_class->size_allocate = gtk_tool_item_size_allocate;
151   widget_class->parent_set    = gtk_tool_item_parent_set;
152
153   klass->create_menu_proxy = gtk_tool_item_create_menu_proxy;
154   klass->set_tooltip       = gtk_tool_item_real_set_tooltip;
155   
156   g_object_class_install_property (object_class,
157                                    PROP_VISIBLE_HORIZONTAL,
158                                    g_param_spec_boolean ("visible_horizontal",
159                                                          P_("Visible when horizontal"),
160                                                          P_("Whether the toolbar item is visible when the toolbar is in a horizontal orientation."),
161                                                          TRUE,
162                                                          G_PARAM_READWRITE));
163   g_object_class_install_property (object_class,
164                                    PROP_VISIBLE_VERTICAL,
165                                    g_param_spec_boolean ("visible_vertical",
166                                                          P_("Visible when vertical"),
167                                                          P_("Whether the toolbar item is visible when the toolbar is in a vertical orientation."),
168                                                          TRUE,
169                                                          G_PARAM_READWRITE));
170   g_object_class_install_property (object_class,
171                                    PROP_IS_IMPORTANT,
172                                    g_param_spec_boolean ("is_important",
173                                                          P_("Is important"),
174                                                          P_("Whether the toolbar item is considered important. When TRUE, toolbar buttons show text in GTK_TOOLBAR_BOTH_HORIZ mode"),
175                                                          FALSE,
176                                                          G_PARAM_READWRITE));
177
178 /**
179  * GtkToolItem::create-menu-proxy:
180  * @toolitem: the object the signal was emitted on
181  *
182  * This signal is emitted when the toolbar needs information from @tool_item
183  * about whether the item should appear in the toolbar overflow menu. In
184  * response the tool item should either
185  * <itemizedlist>
186  * <listitem> call gtk_tool_item_set_proxy_menu_item() with a %NULL
187  * pointer and return %TRUE to indicate that the item should not appear
188  * in the overflow menu
189  * </listitem>
190  * <listitem> call gtk_tool_item_set_proxy_menu_item() with a new menu
191  * item and return %TRUE, or 
192  * </listitem>
193  * <listitem> return %FALSE to indicate that the signal was not
194  * handled by the item. This means that
195  * the item will not appear in the overflow menu unless a later handler
196  * installs a menu item.
197  * </listitem>
198  * </itemizedlist>
199  *
200  * The toolbar may cache the result of this signal. When the tool item changes
201  * how it will respond to this signal it must call gtk_tool_item_rebuild_menu()
202  * to invalidate the cache and ensure that the toolbar rebuilds its overflow
203  * menu.
204  *
205  * Return value: %TRUE if the signal was handled, %FALSE if not
206  **/
207   toolitem_signals[CREATE_MENU_PROXY] =
208     g_signal_new ("create_menu_proxy",
209                   G_OBJECT_CLASS_TYPE (klass),
210                   G_SIGNAL_RUN_LAST,
211                   G_STRUCT_OFFSET (GtkToolItemClass, create_menu_proxy),
212                   _gtk_boolean_handled_accumulator, NULL,
213                   _gtk_marshal_BOOLEAN__VOID,
214                   G_TYPE_BOOLEAN, 0);
215
216 /**
217  * GtkToolItem::toolbar-reconfigured:
218  * @toolitem: the object the signal was emitted on
219  *
220  * This signal is emitted when some property of the toolbar that the
221  * item is a child of changes. For custom subclasses of #GtkToolItem,
222  * the default handler of this signal use the functions
223  * <itemizedlist>
224  * <listitem>gtk_toolbar_get_orientation()</listitem>
225  * <listitem>gtk_toolbar_get_style()</listitem>
226  * <listitem>gtk_toolbar_get_icon_size()</listitem>
227  * <listitem>gtk_toolbar_get_relief_style()</listitem>
228  * </itemizedlist>
229  * to find out what the toolbar should look like and change
230  * themselves accordingly.
231  **/
232   toolitem_signals[TOOLBAR_RECONFIGURED] =
233     g_signal_new ("toolbar_reconfigured",
234                   G_OBJECT_CLASS_TYPE (klass),
235                   G_SIGNAL_RUN_LAST,
236                   G_STRUCT_OFFSET (GtkToolItemClass, toolbar_reconfigured),
237                   NULL, NULL,
238                   _gtk_marshal_VOID__VOID,
239                   G_TYPE_NONE, 0);
240 /**
241  * GtkToolItem::set-tooltip:
242  * @toolitem: the object the signal was emitted on
243  * @tooltips: the #GtkTooltips
244  * @tip_text: the tooltip text
245  * @tip_private: the tooltip private text
246  *
247  * This signal is emitted when the toolitem's tooltip changes.
248  * Application developers can use gtk_tool_item_set_tooltip() to
249  * set the item's tooltip.
250  *
251  * Return value: %TRUE if the signal was handled, %FALSE if not
252  **/
253   toolitem_signals[SET_TOOLTIP] =
254     g_signal_new ("set_tooltip",
255                   G_OBJECT_CLASS_TYPE (klass),
256                   G_SIGNAL_RUN_LAST,
257                   G_STRUCT_OFFSET (GtkToolItemClass, set_tooltip),
258                   _gtk_boolean_handled_accumulator, NULL,
259                   _gtk_marshal_BOOLEAN__OBJECT_STRING_STRING,
260                   G_TYPE_BOOLEAN, 3,
261                   GTK_TYPE_TOOLTIPS,
262                   G_TYPE_STRING,
263                   G_TYPE_STRING);                 
264
265   g_type_class_add_private (object_class, sizeof (GtkToolItemPrivate));
266 }
267
268 static void
269 gtk_tool_item_init (GtkToolItem *toolitem)
270 {
271   GTK_WIDGET_UNSET_FLAGS (toolitem, GTK_CAN_FOCUS);  
272
273   toolitem->priv = GTK_TOOL_ITEM_GET_PRIVATE (toolitem);
274
275   toolitem->priv->visible_horizontal = TRUE;
276   toolitem->priv->visible_vertical = TRUE;
277   toolitem->priv->homogeneous = FALSE;
278   toolitem->priv->expand = FALSE;
279 }
280
281 static void
282 gtk_tool_item_finalize (GObject *object)
283 {
284   GtkToolItem *item = GTK_TOOL_ITEM (object);
285
286   if (item->priv->menu_item_id)
287     g_free (item->priv->menu_item_id);
288   
289   if (item->priv->menu_item)
290     g_object_unref (item->priv->menu_item);
291   
292   if (G_OBJECT_CLASS (parent_class)->finalize)
293     G_OBJECT_CLASS (parent_class)->finalize (object);
294 }
295
296 static void
297 gtk_tool_item_parent_set   (GtkWidget   *toolitem,
298                             GtkWidget   *prev_parent)
299 {
300   _gtk_tool_item_toolbar_reconfigured (GTK_TOOL_ITEM (toolitem));
301 }
302
303 static void
304 gtk_tool_item_set_property (GObject      *object,
305                             guint         prop_id,
306                             const GValue *value,
307                             GParamSpec   *pspec)
308 {
309   GtkToolItem *toolitem = GTK_TOOL_ITEM (object);
310
311   switch (prop_id)
312     {
313     case PROP_VISIBLE_HORIZONTAL:
314       gtk_tool_item_set_visible_horizontal (toolitem, g_value_get_boolean (value));
315       break;
316     case PROP_VISIBLE_VERTICAL:
317       gtk_tool_item_set_visible_vertical (toolitem, g_value_get_boolean (value));
318       break;
319     case PROP_IS_IMPORTANT:
320       gtk_tool_item_set_is_important (toolitem, g_value_get_boolean (value));
321       break;
322     default:
323       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
324     }
325 }
326
327 static void
328 gtk_tool_item_get_property (GObject    *object,
329                             guint       prop_id,
330                             GValue     *value,
331                             GParamSpec *pspec)
332 {
333   GtkToolItem *toolitem = GTK_TOOL_ITEM (object);
334
335   switch (prop_id)
336     {
337     case PROP_VISIBLE_HORIZONTAL:
338       g_value_set_boolean (value, toolitem->priv->visible_horizontal);
339       break;
340     case PROP_VISIBLE_VERTICAL:
341       g_value_set_boolean (value, toolitem->priv->visible_vertical);
342       break;
343     case PROP_IS_IMPORTANT:
344       g_value_set_boolean (value, toolitem->priv->is_important);
345       break;
346     default:
347       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
348     }
349 }
350
351 static void
352 gtk_tool_item_property_notify (GObject    *object,
353                                GParamSpec *pspec)
354 {
355   GtkToolItem *tool_item = GTK_TOOL_ITEM (object);
356
357   if (tool_item->priv->menu_item && strcmp (pspec->name, "sensitive") == 0)
358     gtk_widget_set_sensitive (tool_item->priv->menu_item,
359                               GTK_WIDGET_SENSITIVE (tool_item));
360 }
361
362 static void
363 create_drag_window (GtkToolItem *toolitem)
364 {
365   GtkWidget *widget;
366   GdkWindowAttr attributes;
367   gint attributes_mask, border_width;
368
369   g_return_if_fail (toolitem->priv->use_drag_window == TRUE);
370
371   widget = GTK_WIDGET (toolitem);
372   border_width = GTK_CONTAINER (toolitem)->border_width;
373
374   attributes.window_type = GDK_WINDOW_CHILD;
375   attributes.x = widget->allocation.x + border_width;
376   attributes.y = widget->allocation.y + border_width;
377   attributes.width = widget->allocation.width - border_width * 2;
378   attributes.height = widget->allocation.height - border_width * 2;
379   attributes.wclass = GDK_INPUT_ONLY;
380   attributes.event_mask = gtk_widget_get_events (widget);
381   attributes.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
382
383   attributes_mask = GDK_WA_X | GDK_WA_Y;
384
385   toolitem->priv->drag_window = gdk_window_new (gtk_widget_get_parent_window (widget),
386                                           &attributes, attributes_mask);
387   gdk_window_set_user_data (toolitem->priv->drag_window, toolitem);
388 }
389
390 static void
391 gtk_tool_item_realize (GtkWidget *widget)
392 {
393   GtkToolItem *toolitem;
394
395   toolitem = GTK_TOOL_ITEM (widget);
396   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
397
398   widget->window = gtk_widget_get_parent_window (widget);
399   g_object_ref (widget->window);
400
401   if (toolitem->priv->use_drag_window)
402     create_drag_window(toolitem);
403
404   widget->style = gtk_style_attach (widget->style, widget->window);
405 }
406
407 static void
408 destroy_drag_window (GtkToolItem *toolitem)
409 {
410   if (toolitem->priv->drag_window)
411     {
412       gdk_window_set_user_data (toolitem->priv->drag_window, NULL);
413       gdk_window_destroy (toolitem->priv->drag_window);
414       toolitem->priv->drag_window = NULL;
415     }
416 }
417
418 static void
419 gtk_tool_item_unrealize (GtkWidget *widget)
420 {
421   GtkToolItem *toolitem;
422
423   toolitem = GTK_TOOL_ITEM (widget);
424
425   destroy_drag_window (toolitem);
426   
427   GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
428 }
429
430 static void
431 gtk_tool_item_map (GtkWidget *widget)
432 {
433   GtkToolItem *toolitem;
434
435   toolitem = GTK_TOOL_ITEM (widget);
436   GTK_WIDGET_CLASS (parent_class)->map (widget);
437   if (toolitem->priv->drag_window)
438     gdk_window_show (toolitem->priv->drag_window);
439 }
440
441 static void
442 gtk_tool_item_unmap (GtkWidget *widget)
443 {
444   GtkToolItem *toolitem;
445
446   toolitem = GTK_TOOL_ITEM (widget);
447   if (toolitem->priv->drag_window)
448     gdk_window_hide (toolitem->priv->drag_window);
449   GTK_WIDGET_CLASS (parent_class)->unmap (widget);
450 }
451
452 static void
453 gtk_tool_item_size_request (GtkWidget      *widget,
454                             GtkRequisition *requisition)
455 {
456   GtkWidget *child = GTK_BIN (widget)->child;
457
458   if (child && GTK_WIDGET_VISIBLE (child))
459     {
460       gtk_widget_size_request (child, requisition);
461     }
462   else
463     {
464       requisition->height = 0;
465       requisition->width = 0;
466     }
467   
468   requisition->width += (GTK_CONTAINER (widget)->border_width) * 2;
469   requisition->height += (GTK_CONTAINER (widget)->border_width) * 2;
470 }
471
472 static void
473 gtk_tool_item_size_allocate (GtkWidget     *widget,
474                              GtkAllocation *allocation)
475 {
476   GtkToolItem *toolitem = GTK_TOOL_ITEM (widget);
477   GtkAllocation child_allocation;
478   gint border_width;
479   GtkWidget *child = GTK_BIN (widget)->child;
480
481   widget->allocation = *allocation;
482   border_width = GTK_CONTAINER (widget)->border_width;
483
484   if (toolitem->priv->drag_window)
485     gdk_window_move_resize (toolitem->priv->drag_window,
486                             widget->allocation.x + border_width,
487                             widget->allocation.y + border_width,
488                             widget->allocation.width - border_width * 2,
489                             widget->allocation.height - border_width * 2);
490   
491   if (child && GTK_WIDGET_VISIBLE (child))
492     {
493       child_allocation.x = allocation->x + border_width;
494       child_allocation.y = allocation->y + border_width;
495       child_allocation.width = allocation->width - 2 * border_width;
496       child_allocation.height = allocation->height - 2 * border_width;
497       
498       gtk_widget_size_allocate (child, &child_allocation);
499     }
500 }
501
502 static gboolean
503 gtk_tool_item_create_menu_proxy (GtkToolItem *item)
504 {
505   return FALSE;
506 }
507
508 /**
509  * gtk_tool_item_new:
510  * 
511  * Creates a new #GtkToolItem
512  * 
513  * Return value: the new #GtkToolItem
514  * 
515  * Since: 2.4
516  **/
517 GtkToolItem *
518 gtk_tool_item_new (void)
519 {
520   GtkToolItem *item;
521
522   item = g_object_new (GTK_TYPE_TOOL_ITEM, NULL);
523
524   return item;
525 }
526
527 /**
528  * gtk_tool_item_get_icon_size:
529  * @tool_item: a #GtkToolItem:
530  * 
531  * Returns the icon size used for @tool_item. Custom subclasses of
532  * #GtkToolItem should call this function to find out what size icons
533  * they should use.
534  * 
535  * Return value: a #GtkIconSize indicating the icon size used for @tool_item
536  * 
537  * Since: 2.4
538  **/
539 GtkIconSize
540 gtk_tool_item_get_icon_size (GtkToolItem *tool_item)
541 {
542   GtkWidget *parent;
543
544   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_ICON_SIZE_LARGE_TOOLBAR);
545
546   parent = GTK_WIDGET (tool_item)->parent;
547   if (!parent || !GTK_IS_TOOLBAR (parent))
548     return GTK_ICON_SIZE_LARGE_TOOLBAR;
549
550   return gtk_toolbar_get_icon_size (GTK_TOOLBAR (parent));
551 }
552
553 /**
554  * gtk_tool_item_get_orientation:
555  * @tool_item: a #GtkToolItem: 
556  * 
557  * Returns the orientation used for @tool_item. Custom subclasses of
558  * #GtkToolItem should call this function to find out what size icons
559  * they should use.
560  * 
561  * Return value: a #GtkOrientation indicating the orientation
562  * used for @tool_item
563  * 
564  * Since: 2.4
565  **/
566 GtkOrientation
567 gtk_tool_item_get_orientation (GtkToolItem *tool_item)
568 {
569   GtkWidget *parent;
570   
571   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_ORIENTATION_HORIZONTAL);
572
573   parent = GTK_WIDGET (tool_item)->parent;
574   if (!parent || !GTK_IS_TOOLBAR (parent))
575     return GTK_ORIENTATION_HORIZONTAL;
576
577   return gtk_toolbar_get_orientation (GTK_TOOLBAR (parent));
578 }
579
580 /**
581  * gtk_tool_item_get_toolbar_style:
582  * @tool_item: a #GtkToolItem: 
583  * 
584  * Returns the toolbar style used for @tool_item. Custom subclasses of
585  * #GtkToolItem should call this function in the handler of the
586  * GtkToolItem::toolbar_reconfigured signal to find out in what style
587  * the toolbar is displayed and change themselves accordingly 
588  *
589  * Possibilities are:
590  * <itemizedlist>
591  * <listitem> GTK_TOOLBAR_BOTH, meaning the tool item should show
592  * both an icon and a label, stacked vertically </listitem>
593  * <listitem> GTK_TOOLBAR_ICONS, meaning the toolbar shows
594  * only icons </listitem>
595  * <listitem> GTK_TOOLBAR_TEXT, meaning the tool item should only
596  * show text</listitem>
597  * <listitem> GTK_TOOLBAR_BOTH_HORIZ, meaning the tool item should show
598  * both an icon and a label, arranged horizontally (however, note the 
599  * #GtkToolButton::has_text_horizontally that makes tool buttons not
600  * show labels when the toolbar style is GTK_TOOLBAR_BOTH_HORIZ.
601  * </listitem>
602  * </itemizedlist>
603  * 
604  * Return value: A #GtkToolbarStyle indicating the toolbar style used
605  * for @tool_item.
606  * 
607  * Since: 2.4
608  **/
609 GtkToolbarStyle
610 gtk_tool_item_get_toolbar_style (GtkToolItem *tool_item)
611 {
612   GtkWidget *parent;
613   
614   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_TOOLBAR_ICONS);
615
616   parent = GTK_WIDGET (tool_item)->parent;
617   if (!parent || !GTK_IS_TOOLBAR (parent))
618     return GTK_TOOLBAR_ICONS;
619
620   return gtk_toolbar_get_style (GTK_TOOLBAR (parent));
621 }
622
623 /**
624  * gtk_tool_item_get_relief_style:
625  * @tool_item: a #GtkToolItem: 
626  * 
627  * Returns the relief style of @tool_item. See gtk_button_set_relief_style().
628  * Custom subclasses of #GtkToolItem should call this function in the handler
629  * of the #GtkToolItem::toolbar_reconfigured signal to find out the
630  * relief style of buttons.
631  * 
632  * Return value: a #GtkReliefStyle indicating the relief style used
633  * for @tool_item.
634  * 
635  * Since: 2.4
636  **/
637 GtkReliefStyle 
638 gtk_tool_item_get_relief_style (GtkToolItem *tool_item)
639 {
640   GtkWidget *parent;
641   
642   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), GTK_RELIEF_NONE);
643
644   parent = GTK_WIDGET (tool_item)->parent;
645   if (!parent || !GTK_IS_TOOLBAR (parent))
646     return GTK_RELIEF_NONE;
647
648   return gtk_toolbar_get_relief_style (GTK_TOOLBAR (parent));
649 }
650
651 /**
652  * gtk_tool_item_set_expand:
653  * @tool_item: a #GtkToolItem: 
654  * @expand: Whether @tool_item is allocated extra space
655  * 
656  * Sets whether @tool_item is allocated extra space when there
657  * is more room on the toolbar then needed for the items. The
658  * effect is that the item gets bigger when the toolbar gets bigger
659  * and smaller when the toolbar gets smaller.
660  * 
661  * Since: 2.4
662  **/
663 void
664 gtk_tool_item_set_expand (GtkToolItem *tool_item,
665                           gboolean     expand)
666 {
667   g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item));
668     
669   expand = expand != FALSE;
670
671   if (tool_item->priv->expand != expand)
672     {
673       tool_item->priv->expand = expand;
674       gtk_widget_child_notify (GTK_WIDGET (tool_item), "expand");
675       gtk_widget_queue_resize (GTK_WIDGET (tool_item));
676     }
677 }
678
679 /**
680  * gtk_tool_item_get_expand:
681  * @tool_item: a #GtkToolItem: 
682  * 
683  * Returns whether @tool_item is allocated extra space.
684  * See gtk_tool_item_set_expand().
685  * 
686  * Return value: %TRUE if @tool_item is allocated extra space.
687  * 
688  * Since: 2.4
689  **/
690 gboolean
691 gtk_tool_item_get_expand (GtkToolItem *tool_item)
692 {
693   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), FALSE);
694
695   return tool_item->priv->expand;
696 }
697
698 /**
699  * gtk_tool_item_set_homogeneous:
700  * @tool_item: a #GtkToolItem: 
701  * @homogeneous: whether @tool_item is the same size as other homogeneous items
702  * 
703  * Sets whether @tool_item is to be allocated the same size as other
704  * homogeneous items. The effect is that all homogeneous items will have
705  * the same width as the widest of the items.
706  * 
707  * Since: 2.4
708  **/
709 void
710 gtk_tool_item_set_homogeneous (GtkToolItem *tool_item,
711                                gboolean     homogeneous)
712 {
713   g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item));
714     
715   homogeneous = homogeneous != FALSE;
716
717   if (tool_item->priv->homogeneous != homogeneous)
718     {
719       tool_item->priv->homogeneous = homogeneous;
720       gtk_widget_child_notify (GTK_WIDGET (tool_item), "homogeneous");
721       gtk_widget_queue_resize (GTK_WIDGET (tool_item));
722     }
723 }
724
725 /**
726  * gtk_tool_item_get_homogeneous:
727  * @tool_item: a #GtkToolItem: 
728  * 
729  * Returns whether @tool_item is the same size as other homogeneous
730  * items. See gtk_tool_item_set_homogeneous().
731  * 
732  * Return value: %TRUE if the item is the same size as other homogeneous
733  * item.s
734  * 
735  * Since: 2.4
736  **/
737 gboolean
738 gtk_tool_item_get_homogeneous (GtkToolItem *tool_item)
739 {
740   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), FALSE);
741
742   return tool_item->priv->homogeneous;
743 }
744
745 /**
746  * gtk_tool_item_get_is_important:
747  * @tool_item: a #GtkToolItem
748  * 
749  * Returns whether @tool_item is considered important. See
750  * gtk_tool_item_set_is_important()
751  * 
752  * Return value: %TRUE if @tool_item is considered important.
753  * 
754  * Since: 2.4
755  **/
756 gboolean
757 gtk_tool_item_get_is_important (GtkToolItem *tool_item)
758 {
759   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), FALSE);
760
761   return tool_item->priv->is_important;
762 }
763
764 /**
765  * gtk_tool_item_set_is_important:
766  * @tool_item: a #GtkToolItem
767  * @is_important: whether the tool item should be considered important
768  * 
769  * Sets whether @tool_item should be considered important. The #GtkToolButton
770  * class uses this property to determine whether to show or hide its label
771  * when the toolbar style is %GTK_TOOLBAR_BOTH_HORIZ. The result is that
772  * only tool buttons with the "is_important" property set have labels, an
773  * effect known as "priority text"
774  * 
775  * Since: 2.4
776  **/
777 void
778 gtk_tool_item_set_is_important (GtkToolItem *tool_item, gboolean is_important)
779 {
780   g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item));
781
782   is_important = is_important != FALSE;
783
784   if (is_important != tool_item->priv->is_important)
785     {
786       tool_item->priv->is_important = is_important;
787
788       gtk_widget_queue_resize (GTK_WIDGET (tool_item));
789
790       g_object_notify (G_OBJECT (tool_item), "is_important");
791     }
792 }
793
794 static gboolean
795 gtk_tool_item_real_set_tooltip (GtkToolItem *tool_item,
796                                 GtkTooltips *tooltips,
797                                 const gchar *tip_text,
798                                 const gchar *tip_private)
799 {
800   GtkWidget *child = GTK_BIN (tool_item)->child;
801
802   if (!child)
803     return FALSE;
804
805   gtk_tooltips_set_tip (tooltips, child, tip_text, tip_private);
806
807   return TRUE;
808 }
809
810 /**
811  * gtk_tool_item_set_tooltip:
812  * @tool_item: a #GtkToolItem: 
813  * @tooltips: The #GtkTooltips object to be used
814  * @tip_text: text to be used as tooltip text for @tool_item
815  * @tip_private: text to be used as private tooltip text
816  *
817  * Sets the #GtkTooltips object to be used for @tool_item, the
818  * text to be displayed as tooltip on the item and the private text
819  * to be used. See gtk_tooltips_set_tip().
820  * 
821  * Since: 2.4
822  **/
823 void
824 gtk_tool_item_set_tooltip (GtkToolItem *tool_item,
825                            GtkTooltips *tooltips,
826                            const gchar *tip_text,
827                            const gchar *tip_private)
828 {
829   gboolean retval;
830   
831   g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item));
832
833   g_signal_emit (tool_item, toolitem_signals[SET_TOOLTIP], 0,
834                  tooltips, tip_text, tip_private, &retval);
835 }
836
837 /**
838  * gtk_tool_item_set_use_drag_window:
839  * @toolitem: a #GtkToolItem 
840  * @use_drag_window: Whether @toolitem has a drag window.
841  * 
842  * Sets whether @toolitem has a drag window. When %TRUE the
843  * toolitem can be used as a drag source through gtk_drag_source_set().
844  * When @toolitem has a drag window it will intercept all events,
845  * even those that would otherwise be sent to a child of @toolitem.
846  * 
847  * Since: 2.4
848  **/
849 void
850 gtk_tool_item_set_use_drag_window (GtkToolItem *toolitem,
851                                    gboolean     use_drag_window)
852 {
853   g_return_if_fail (GTK_IS_TOOL_ITEM (toolitem));
854
855   use_drag_window = use_drag_window != FALSE;
856
857   if (toolitem->priv->use_drag_window != use_drag_window)
858     {
859       toolitem->priv->use_drag_window = use_drag_window;
860       
861       if (use_drag_window)
862         {
863           if (!toolitem->priv->drag_window && GTK_WIDGET_REALIZED (toolitem))
864             {
865               create_drag_window(toolitem);
866               if (GTK_WIDGET_MAPPED (toolitem))
867                 gdk_window_show (toolitem->priv->drag_window);
868             }
869         }
870       else
871         {
872           destroy_drag_window (toolitem);
873         }
874     }
875 }
876
877 /**
878  * gtk_tool_item_get_use_drag_window:
879  * @toolitem: a #GtkToolItem 
880  * 
881  * Returns whether @toolitem has a drag window. See
882  * gtk_tool_item_set_use_drag_window().
883  * 
884  * Return value: %TRUE if @toolitem uses a drag window.
885  * 
886  * Since: 2.4
887  **/
888 gboolean
889 gtk_tool_item_get_use_drag_window (GtkToolItem *toolitem)
890 {
891   g_return_val_if_fail (GTK_IS_TOOL_ITEM (toolitem), FALSE);
892
893   return toolitem->priv->use_drag_window;
894 }
895
896 /**
897  * gtk_tool_item_set_visible_horizontal:
898  * @toolitem: a #GtkToolItem
899  * @visible_horizontal: Whether @toolitem is visible when in horizontal mode
900  * 
901  * Sets whether @toolitem is visible when the toolbar is docked horizontally.
902  * 
903  * Since: 2.4
904  **/
905 void
906 gtk_tool_item_set_visible_horizontal (GtkToolItem *toolitem,
907                                       gboolean     visible_horizontal)
908 {
909   g_return_if_fail (GTK_IS_TOOL_ITEM (toolitem));
910
911   visible_horizontal = visible_horizontal != FALSE;
912
913   if (toolitem->priv->visible_horizontal != visible_horizontal)
914     {
915       toolitem->priv->visible_horizontal = visible_horizontal;
916
917       g_object_notify (G_OBJECT (toolitem), "visible_horizontal");
918
919       gtk_widget_queue_resize (GTK_WIDGET (toolitem));
920     }
921 }
922
923 /**
924  * gtk_tool_item_get_visible_horizontal:
925  * @toolitem: a #GtkToolItem 
926  * 
927  * Returns whether the @toolitem is visible on toolbars that are
928  * docked horizontally.
929  * 
930  * Return value: %TRUE if @toolitem is visible on toolbars that are
931  * docked horizontally.
932  * 
933  * Since: 2.4
934  **/
935 gboolean
936 gtk_tool_item_get_visible_horizontal (GtkToolItem *toolitem)
937 {
938   g_return_val_if_fail (GTK_IS_TOOL_ITEM (toolitem), FALSE);
939
940   return toolitem->priv->visible_horizontal;
941 }
942
943 /**
944  * gtk_tool_item_set_visible_vertical:
945  * @toolitem: a #GtkToolItem 
946  * @visible_vertical: whether @toolitem is visible when the toolbar
947  * is in vertical mode
948  *
949  * Sets whether @toolitem is visible when the toolbar is docked
950  * vertically. Some tool items, such as text entries, are too wide to be
951  * useful on a vertically docked toolbar. If @visible_vertical is %FALSE
952  * @toolitem will not appear on toolbars that are docked vertically.
953  * 
954  * Since: 2.4
955  **/
956 void
957 gtk_tool_item_set_visible_vertical (GtkToolItem *toolitem,
958                                     gboolean     visible_vertical)
959 {
960   g_return_if_fail (GTK_IS_TOOL_ITEM (toolitem));
961
962   visible_vertical = visible_vertical != FALSE;
963
964   if (toolitem->priv->visible_vertical != visible_vertical)
965     {
966       toolitem->priv->visible_vertical = visible_vertical;
967
968       g_object_notify (G_OBJECT (toolitem), "visible_vertical");
969
970       gtk_widget_queue_resize (GTK_WIDGET (toolitem));
971     }
972 }
973
974 /**
975  * gtk_tool_item_get_visible_vertical:
976  * @toolitem: a #GtkToolItem 
977  * 
978  * Returns whether @toolitem is visible when the toolbar is docked vertically.
979  * See gtk_tool_item_set_visible_vertical().
980  * 
981  * Return value: Whether @toolitem is visible when the toolbar is docked vertically
982  * 
983  * Since: 2.4
984  **/
985 gboolean
986 gtk_tool_item_get_visible_vertical (GtkToolItem *toolitem)
987 {
988   g_return_val_if_fail (GTK_IS_TOOL_ITEM (toolitem), FALSE);
989
990   return toolitem->priv->visible_vertical;
991 }
992
993 /**
994  * gtk_tool_item_retrieve_proxy_menu_item:
995  * @tool_item: a #GtkToolItem: 
996  * 
997  * Returns the #GtkMenuItem that was last set by
998  * gtk_tool_item_set_proxy_menu_item(), ie. the #GtkMenuItem
999  * that is going to appear in the overflow menu.
1000  * 
1001  * Return value: The #GtkMenuItem that is going to appear in the
1002  * overflow menu for @tool_item.
1003  * 
1004  * Since: 2.4
1005  **/
1006 GtkWidget *
1007 gtk_tool_item_retrieve_proxy_menu_item (GtkToolItem *tool_item)
1008 {
1009   gboolean retval;
1010   
1011   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), NULL);
1012
1013   g_signal_emit (tool_item, toolitem_signals[CREATE_MENU_PROXY], 0,
1014                  &retval);
1015   
1016   return tool_item->priv->menu_item;
1017 }
1018
1019 /**
1020  * gtk_tool_item_get_proxy_menu_item:
1021  * @tool_item: a #GtkToolItem: 
1022  * @menu_item_id: a string used to identify the menu item
1023  * 
1024  * If @menu_item_id matches the string passed to
1025  * gtk_tool_item_set_proxy_menu_item() return the corresponding #GtkMenuItem.
1026  *
1027  * Custom subclasses of #GtkToolItem should use this function to update
1028  * their menu item when the #GtkToolItem changes. That the
1029  * @menu_item_id<!-- -->s must match ensures that a #GtkToolItem will not
1030  * inadvertently change a menu item that they did not create.
1031  * 
1032  * Return value: The #GtkMenuItem passed to
1033  * gtk_tool_item_set_proxy_menu_item(), if the @menu_item_id<!-- -->s match.
1034  * 
1035  * Since: 2.4
1036  **/
1037 GtkWidget *
1038 gtk_tool_item_get_proxy_menu_item (GtkToolItem *tool_item,
1039                                    const gchar *menu_item_id)
1040 {
1041   g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), NULL);
1042   g_return_val_if_fail (menu_item_id != NULL, NULL);
1043
1044   if (tool_item->priv->menu_item_id && strcmp (tool_item->priv->menu_item_id, menu_item_id) == 0)
1045     return tool_item->priv->menu_item;
1046
1047   return NULL;
1048 }
1049
1050 /**
1051  * gtk_tool_item_rebuild_menu()
1052  * @tool_item: a #GtkToolItem
1053  * 
1054  * Calling this function signals to the toolbar that the
1055  * overflow menu item for @tool_item has changed. If the
1056  * overflow menu is visible when this function it called,
1057  * the menu will be rebuilt.
1058  *
1059  * The function must be called when the tool item
1060  * changes what it will do in response to the "create_menu_proxy"
1061  * signal.
1062  * 
1063  * Since: 2.6
1064  **/
1065 void
1066 gtk_tool_item_rebuild_menu (GtkToolItem *tool_item)
1067 {
1068   GtkWidget *widget;
1069   
1070   g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item));
1071
1072   widget = GTK_WIDGET (tool_item);
1073   
1074   if (widget->parent && GTK_IS_TOOLBAR (widget->parent))
1075     _gtk_toolbar_rebuild_menu (GTK_TOOLBAR (widget->parent));
1076 }
1077
1078 /**
1079  * gtk_tool_item_set_proxy_menu_item:
1080  * @tool_item: a #GtkToolItem:
1081  * @menu_item_id: a string used to identify @menu_item
1082  * @menu_item: a #GtkMenuItem to be used in the overflow menu
1083  * 
1084  * Sets the #GtkMenuItem used in the toolbar overflow menu. The
1085  * @menu_item_id is used to identify the caller of this function and
1086  * should also be used with gtk_tool_item_get_proxy_menu_item().
1087  * 
1088  * Since: 2.4
1089  **/
1090 void
1091 gtk_tool_item_set_proxy_menu_item (GtkToolItem *tool_item,
1092                                    const gchar *menu_item_id,
1093                                    GtkWidget   *menu_item)
1094 {
1095   g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item));
1096   g_return_if_fail (menu_item == NULL || GTK_IS_MENU_ITEM (menu_item));
1097   g_return_if_fail (menu_item_id != NULL);
1098
1099   if (tool_item->priv->menu_item_id)
1100     g_free (tool_item->priv->menu_item_id);
1101       
1102   tool_item->priv->menu_item_id = g_strdup (menu_item_id);
1103
1104   if (tool_item->priv->menu_item != menu_item)
1105     {
1106       if (tool_item->priv->menu_item)
1107         g_object_unref (G_OBJECT (tool_item->priv->menu_item));
1108       
1109       if (menu_item)
1110         {
1111           g_object_ref (menu_item);
1112           gtk_object_sink (GTK_OBJECT (menu_item));
1113
1114           gtk_widget_set_sensitive (menu_item,
1115                                     GTK_WIDGET_SENSITIVE (tool_item));
1116         }
1117       
1118       tool_item->priv->menu_item = menu_item;
1119     }
1120 }
1121
1122 /**
1123  * _gtk_tool_item_toolbar_reconfigured:
1124  * @tool_item: a #GtkToolItem: 
1125  * 
1126  * Emits the signal #GtkToolItem::toolbar_reconfigured on @tool_item. This
1127  * internal function is called by #GtkToolbar when some aspect of its
1128  * configuration changes.
1129  * 
1130  * Since: 2.4
1131  **/
1132 void
1133 _gtk_tool_item_toolbar_reconfigured (GtkToolItem *tool_item)
1134 {
1135   g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item));
1136
1137   g_signal_emit (tool_item, toolitem_signals[TOOLBAR_RECONFIGURED], 0);
1138   
1139   gtk_widget_queue_resize (GTK_WIDGET (tool_item));
1140 }
1141