1 /* GTK - The GIMP Toolkit
3 * Copyright (C) 2003 Sun Microsystems, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 * Mark McLoughlin <mark@skynet.ie>
26 #include "gtkexpander.h"
29 #include "gtkbuildable.h"
30 #include "gtkcontainer.h"
31 #include "gtkmarshalers.h"
34 #include "gtkprivate.h"
35 #include <gdk/gdkkeysyms.h>
39 #define DEFAULT_EXPANDER_SIZE 10
40 #define DEFAULT_EXPANDER_SPACING 2
54 struct _GtkExpanderPrivate
56 GtkWidget *label_widget;
57 GdkWindow *event_window;
60 GtkExpanderStyle expander_style;
61 guint animation_timeout;
65 guint use_underline : 1;
67 guint button_down : 1;
72 static void gtk_expander_set_property (GObject *object,
76 static void gtk_expander_get_property (GObject *object,
81 static void gtk_expander_destroy (GtkWidget *widget);
82 static void gtk_expander_realize (GtkWidget *widget);
83 static void gtk_expander_unrealize (GtkWidget *widget);
84 static void gtk_expander_size_allocate (GtkWidget *widget,
85 GtkAllocation *allocation);
86 static void gtk_expander_map (GtkWidget *widget);
87 static void gtk_expander_unmap (GtkWidget *widget);
88 static gboolean gtk_expander_draw (GtkWidget *widget,
90 static gboolean gtk_expander_button_press (GtkWidget *widget,
91 GdkEventButton *event);
92 static gboolean gtk_expander_button_release (GtkWidget *widget,
93 GdkEventButton *event);
94 static gboolean gtk_expander_enter_notify (GtkWidget *widget,
95 GdkEventCrossing *event);
96 static gboolean gtk_expander_leave_notify (GtkWidget *widget,
97 GdkEventCrossing *event);
98 static gboolean gtk_expander_focus (GtkWidget *widget,
99 GtkDirectionType direction);
100 static void gtk_expander_grab_notify (GtkWidget *widget,
101 gboolean was_grabbed);
102 static void gtk_expander_state_changed (GtkWidget *widget,
103 GtkStateType previous_state);
104 static gboolean gtk_expander_drag_motion (GtkWidget *widget,
105 GdkDragContext *context,
109 static void gtk_expander_drag_leave (GtkWidget *widget,
110 GdkDragContext *context,
113 static void gtk_expander_add (GtkContainer *container,
115 static void gtk_expander_remove (GtkContainer *container,
117 static void gtk_expander_forall (GtkContainer *container,
118 gboolean include_internals,
119 GtkCallback callback,
120 gpointer callback_data);
122 static void gtk_expander_activate (GtkExpander *expander);
124 static void get_expander_bounds (GtkExpander *expander,
128 static void gtk_expander_buildable_init (GtkBuildableIface *iface);
129 static void gtk_expander_buildable_add_child (GtkBuildable *buildable,
136 static void gtk_expander_get_preferred_width (GtkWidget *widget,
139 static void gtk_expander_get_preferred_height (GtkWidget *widget,
142 static void gtk_expander_get_preferred_height_for_width (GtkWidget *layout,
144 gint *minimum_height,
145 gint *natural_height);
146 static void gtk_expander_get_preferred_width_for_height (GtkWidget *layout,
148 gint *minimum_height,
149 gint *natural_height);
151 G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
152 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
153 gtk_expander_buildable_init))
156 gtk_expander_class_init (GtkExpanderClass *klass)
158 GObjectClass *gobject_class;
159 GtkWidgetClass *widget_class;
160 GtkContainerClass *container_class;
162 gobject_class = (GObjectClass *) klass;
163 widget_class = (GtkWidgetClass *) klass;
164 container_class = (GtkContainerClass *) klass;
166 gobject_class->set_property = gtk_expander_set_property;
167 gobject_class->get_property = gtk_expander_get_property;
169 widget_class->destroy = gtk_expander_destroy;
170 widget_class->realize = gtk_expander_realize;
171 widget_class->unrealize = gtk_expander_unrealize;
172 widget_class->size_allocate = gtk_expander_size_allocate;
173 widget_class->map = gtk_expander_map;
174 widget_class->unmap = gtk_expander_unmap;
175 widget_class->draw = gtk_expander_draw;
176 widget_class->button_press_event = gtk_expander_button_press;
177 widget_class->button_release_event = gtk_expander_button_release;
178 widget_class->enter_notify_event = gtk_expander_enter_notify;
179 widget_class->leave_notify_event = gtk_expander_leave_notify;
180 widget_class->focus = gtk_expander_focus;
181 widget_class->grab_notify = gtk_expander_grab_notify;
182 widget_class->state_changed = gtk_expander_state_changed;
183 widget_class->drag_motion = gtk_expander_drag_motion;
184 widget_class->drag_leave = gtk_expander_drag_leave;
185 widget_class->get_preferred_width = gtk_expander_get_preferred_width;
186 widget_class->get_preferred_height = gtk_expander_get_preferred_height;
187 widget_class->get_preferred_height_for_width = gtk_expander_get_preferred_height_for_width;
188 widget_class->get_preferred_width_for_height = gtk_expander_get_preferred_width_for_height;
190 container_class->add = gtk_expander_add;
191 container_class->remove = gtk_expander_remove;
192 container_class->forall = gtk_expander_forall;
194 klass->activate = gtk_expander_activate;
196 g_type_class_add_private (klass, sizeof (GtkExpanderPrivate));
198 g_object_class_install_property (gobject_class,
200 g_param_spec_boolean ("expanded",
202 P_("Whether the expander has been opened to reveal the child widget"),
204 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
206 g_object_class_install_property (gobject_class,
208 g_param_spec_string ("label",
210 P_("Text of the expander's label"),
212 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
214 g_object_class_install_property (gobject_class,
216 g_param_spec_boolean ("use-underline",
218 P_("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
220 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
222 g_object_class_install_property (gobject_class,
224 g_param_spec_boolean ("use-markup",
226 P_("The text of the label includes XML markup. See pango_parse_markup()"),
228 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
230 g_object_class_install_property (gobject_class,
232 g_param_spec_int ("spacing",
234 P_("Space to put between the label and the child"),
238 GTK_PARAM_READWRITE));
240 g_object_class_install_property (gobject_class,
242 g_param_spec_object ("label-widget",
244 P_("A widget to display in place of the usual expander label"),
246 GTK_PARAM_READWRITE));
248 g_object_class_install_property (gobject_class,
250 g_param_spec_boolean ("label-fill",
252 P_("Whether the label widget should fill all available horizontal space"),
254 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
256 gtk_widget_class_install_style_property (widget_class,
257 g_param_spec_int ("expander-size",
259 P_("Size of the expander arrow"),
262 DEFAULT_EXPANDER_SIZE,
263 GTK_PARAM_READABLE));
265 gtk_widget_class_install_style_property (widget_class,
266 g_param_spec_int ("expander-spacing",
267 P_("Indicator Spacing"),
268 P_("Spacing around expander arrow"),
271 DEFAULT_EXPANDER_SPACING,
272 GTK_PARAM_READABLE));
274 widget_class->activate_signal =
275 g_signal_new (I_("activate"),
276 G_TYPE_FROM_CLASS (gobject_class),
277 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
278 G_STRUCT_OFFSET (GtkExpanderClass, activate),
280 _gtk_marshal_VOID__VOID,
285 gtk_expander_init (GtkExpander *expander)
287 GtkExpanderPrivate *priv;
289 expander->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (expander,
293 gtk_widget_set_can_focus (GTK_WIDGET (expander), TRUE);
294 gtk_widget_set_has_window (GTK_WIDGET (expander), FALSE);
296 priv->label_widget = NULL;
297 priv->event_window = NULL;
300 priv->expander_style = GTK_EXPANDER_COLLAPSED;
301 priv->animation_timeout = 0;
303 priv->expanded = FALSE;
304 priv->use_underline = FALSE;
305 priv->use_markup = FALSE;
306 priv->button_down = FALSE;
307 priv->prelight = FALSE;
308 priv->label_fill = FALSE;
309 priv->expand_timer = 0;
311 gtk_drag_dest_set (GTK_WIDGET (expander), 0, NULL, 0, 0);
312 gtk_drag_dest_set_track_motion (GTK_WIDGET (expander), TRUE);
316 gtk_expander_buildable_add_child (GtkBuildable *buildable,
322 gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
323 else if (strcmp (type, "label") == 0)
324 gtk_expander_set_label_widget (GTK_EXPANDER (buildable), GTK_WIDGET (child));
326 GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_EXPANDER (buildable), type);
330 gtk_expander_buildable_init (GtkBuildableIface *iface)
332 iface->add_child = gtk_expander_buildable_add_child;
336 gtk_expander_set_property (GObject *object,
341 GtkExpander *expander = GTK_EXPANDER (object);
346 gtk_expander_set_expanded (expander, g_value_get_boolean (value));
349 gtk_expander_set_label (expander, g_value_get_string (value));
351 case PROP_USE_UNDERLINE:
352 gtk_expander_set_use_underline (expander, g_value_get_boolean (value));
354 case PROP_USE_MARKUP:
355 gtk_expander_set_use_markup (expander, g_value_get_boolean (value));
358 gtk_expander_set_spacing (expander, g_value_get_int (value));
360 case PROP_LABEL_WIDGET:
361 gtk_expander_set_label_widget (expander, g_value_get_object (value));
363 case PROP_LABEL_FILL:
364 gtk_expander_set_label_fill (expander, g_value_get_boolean (value));
367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
373 gtk_expander_get_property (GObject *object,
378 GtkExpander *expander = GTK_EXPANDER (object);
379 GtkExpanderPrivate *priv = expander->priv;
384 g_value_set_boolean (value, priv->expanded);
387 g_value_set_string (value, gtk_expander_get_label (expander));
389 case PROP_USE_UNDERLINE:
390 g_value_set_boolean (value, priv->use_underline);
392 case PROP_USE_MARKUP:
393 g_value_set_boolean (value, priv->use_markup);
396 g_value_set_int (value, priv->spacing);
398 case PROP_LABEL_WIDGET:
399 g_value_set_object (value,
401 G_OBJECT (priv->label_widget) : NULL);
403 case PROP_LABEL_FILL:
404 g_value_set_boolean (value, priv->label_fill);
407 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
413 gtk_expander_destroy (GtkWidget *widget)
415 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
417 if (priv->animation_timeout)
419 g_source_remove (priv->animation_timeout);
420 priv->animation_timeout = 0;
423 GTK_WIDGET_CLASS (gtk_expander_parent_class)->destroy (widget);
427 gtk_expander_realize (GtkWidget *widget)
429 GtkAllocation allocation;
430 GtkExpanderPrivate *priv;
432 GdkWindowAttr attributes;
433 gint attributes_mask;
435 GdkRectangle expander_rect;
438 priv = GTK_EXPANDER (widget)->priv;
440 gtk_widget_set_realized (widget, TRUE);
442 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
444 get_expander_bounds (GTK_EXPANDER (widget), &expander_rect);
446 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
448 GtkRequisition label_requisition;
450 gtk_widget_get_preferred_size (priv->label_widget,
451 &label_requisition, NULL);
452 label_height = label_requisition.height;
457 gtk_widget_get_allocation (widget, &allocation);
459 attributes.window_type = GDK_WINDOW_CHILD;
460 attributes.x = allocation.x + border_width;
461 attributes.y = allocation.y + border_width;
462 attributes.width = MAX (allocation.width - 2 * border_width, 1);
463 attributes.height = MAX (expander_rect.height, label_height - 2 * border_width);
464 attributes.wclass = GDK_INPUT_ONLY;
465 attributes.event_mask = gtk_widget_get_events (widget) |
466 GDK_BUTTON_PRESS_MASK |
467 GDK_BUTTON_RELEASE_MASK |
468 GDK_ENTER_NOTIFY_MASK |
469 GDK_LEAVE_NOTIFY_MASK;
471 attributes_mask = GDK_WA_X | GDK_WA_Y;
473 window = gtk_widget_get_parent_window (widget);
474 gtk_widget_set_window (widget, window);
475 g_object_ref (window);
477 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
478 &attributes, attributes_mask);
479 gdk_window_set_user_data (priv->event_window, widget);
481 gtk_widget_style_attach (widget);
485 gtk_expander_unrealize (GtkWidget *widget)
487 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
489 if (priv->event_window)
491 gdk_window_set_user_data (priv->event_window, NULL);
492 gdk_window_destroy (priv->event_window);
493 priv->event_window = NULL;
496 GTK_WIDGET_CLASS (gtk_expander_parent_class)->unrealize (widget);
500 get_expander_bounds (GtkExpander *expander,
503 GtkAllocation allocation;
505 GtkExpanderPrivate *priv;
508 gint expander_spacing;
509 gboolean interior_focus;
514 widget = GTK_WIDGET (expander);
515 priv = expander->priv;
517 gtk_widget_get_allocation (widget, &allocation);
519 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
521 gtk_widget_style_get (widget,
522 "interior-focus", &interior_focus,
523 "focus-line-width", &focus_width,
524 "focus-padding", &focus_pad,
525 "expander-size", &expander_size,
526 "expander-spacing", &expander_spacing,
529 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
531 rect->x = allocation.x + border_width;
532 rect->y = allocation.y + border_width;
535 rect->x += expander_spacing;
537 rect->x += allocation.width - 2 * border_width -
538 expander_spacing - expander_size;
540 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
542 GtkAllocation label_allocation;
544 gtk_widget_get_allocation (priv->label_widget, &label_allocation);
546 if (expander_size < label_allocation.height)
547 rect->y += focus_width + focus_pad + (label_allocation.height - expander_size) / 2;
549 rect->y += expander_spacing;
553 rect->y += expander_spacing;
559 rect->x += focus_width + focus_pad;
561 rect->x -= focus_width + focus_pad;
562 rect->y += focus_width + focus_pad;
565 rect->width = rect->height = expander_size;
569 gtk_expander_size_allocate (GtkWidget *widget,
570 GtkAllocation *allocation)
572 GtkExpander *expander;
574 GtkExpanderPrivate *priv;
575 gboolean child_visible = FALSE;
578 gint expander_spacing;
579 gboolean interior_focus;
582 gint label_height, top_min_height;
583 gint label_xpad, label_xoffset;
584 gint child_ypad, child_yoffset;
586 expander = GTK_EXPANDER (widget);
587 child = gtk_bin_get_child (GTK_BIN (widget));
588 priv = expander->priv;
590 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
592 gtk_widget_set_allocation (widget, allocation);
594 gtk_widget_style_get (widget,
595 "interior-focus", &interior_focus,
596 "focus-line-width", &focus_width,
597 "focus-padding", &focus_pad,
598 "expander-size", &expander_size,
599 "expander-spacing", &expander_spacing,
603 /* Calculate some offsets/padding first */
604 label_xoffset = border_width + expander_size + focus_width + 2 * expander_spacing + focus_pad;
605 label_xpad = 2 * border_width + expander_size + 2 * focus_width + 2 * expander_spacing + 2 * focus_pad;
607 child_yoffset = border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
608 child_ypad = 2 * border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
609 top_min_height = 2 * expander_spacing + expander_size;
611 child_visible = (child && gtk_widget_get_child_visible (child));
613 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
615 GtkAllocation label_allocation;
616 gint natural_label_width;
619 gtk_widget_get_preferred_width (priv->label_widget, NULL, &natural_label_width);
621 if (priv->label_fill)
622 label_allocation.width = allocation->width - label_xpad;
624 label_allocation.width = MIN (natural_label_width, allocation->width - label_xpad);
625 label_allocation.width = MAX (label_allocation.width, 1);
627 /* We distribute the minimum height to the label widget and prioritize
628 * the child widget giving it the remaining height */
629 gtk_widget_get_preferred_height_for_width (priv->label_widget,
630 label_allocation.width, &label_height, NULL);
632 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
634 if (priv->label_fill)
635 label_allocation.x = allocation->x + label_xoffset;
637 label_allocation.x = allocation->x + label_xoffset;
639 label_allocation.x = allocation->x + allocation->width -
640 (label_allocation.width + label_xoffset);
642 label_allocation.y = allocation->y + border_width + focus_width + focus_pad;
643 label_allocation.height = MIN (label_height,
644 allocation->height - 2 * border_width -
645 2 * focus_width - 2 * focus_pad -
646 (child_visible ? priv->spacing : 0));
647 label_allocation.height = MAX (label_allocation.height, 1);
649 gtk_widget_size_allocate (priv->label_widget, &label_allocation);
651 label_height = label_allocation.height;
658 if (gtk_widget_get_realized (widget))
662 get_expander_bounds (expander, &rect);
664 gdk_window_move_resize (priv->event_window,
665 allocation->x + border_width,
666 allocation->y + border_width,
667 MAX (allocation->width - 2 * border_width, 1),
668 MAX (rect.height, label_height - 2 * border_width));
673 GtkAllocation child_allocation;
676 top_height = MAX (top_min_height,
677 label_height + (interior_focus ? 2 * focus_width + 2 * focus_pad : 0));
679 child_allocation.x = allocation->x + border_width;
680 child_allocation.y = allocation->y + top_height + child_yoffset;
682 child_allocation.width = MAX (allocation->width - 2 * border_width, 1);
683 child_allocation.height = allocation->height - top_height - child_ypad;
684 child_allocation.height = MAX (child_allocation.height, 1);
686 gtk_widget_size_allocate (child, &child_allocation);
691 gtk_expander_map (GtkWidget *widget)
693 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
695 if (priv->label_widget)
696 gtk_widget_map (priv->label_widget);
698 GTK_WIDGET_CLASS (gtk_expander_parent_class)->map (widget);
700 if (priv->event_window)
701 gdk_window_show (priv->event_window);
705 gtk_expander_unmap (GtkWidget *widget)
707 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
709 if (priv->event_window)
710 gdk_window_hide (priv->event_window);
712 GTK_WIDGET_CLASS (gtk_expander_parent_class)->unmap (widget);
714 if (priv->label_widget)
715 gtk_widget_unmap (priv->label_widget);
719 gtk_expander_paint_prelight (GtkExpander *expander, cairo_t *cr)
721 GtkAllocation allocation;
723 GtkContainer *container;
724 GtkExpanderPrivate *priv;
726 gboolean interior_focus;
730 int expander_spacing;
733 priv = expander->priv;
734 widget = GTK_WIDGET (expander);
735 container = GTK_CONTAINER (expander);
737 gtk_widget_style_get (widget,
738 "interior-focus", &interior_focus,
739 "focus-line-width", &focus_width,
740 "focus-padding", &focus_pad,
741 "expander-size", &expander_size,
742 "expander-spacing", &expander_spacing,
745 gtk_widget_get_allocation (widget, &allocation);
747 border_width = gtk_container_get_border_width (container);
748 area.x = border_width;
749 area.y = border_width;
750 area.width = allocation.width - (2 * border_width);
752 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
754 GtkAllocation label_widget_allocation;
756 gtk_widget_get_allocation (priv->label_widget, &label_widget_allocation);
757 area.height = label_widget_allocation.height;
762 area.height += interior_focus ? (focus_width + focus_pad) * 2 : 0;
763 area.height = MAX (area.height, expander_size + 2 * expander_spacing);
764 area.height += !interior_focus ? (focus_width + focus_pad) * 2 : 0;
766 gtk_paint_flat_box (gtk_widget_get_style (widget),
769 GTK_SHADOW_ETCHED_OUT,
772 area.width, area.height);
776 gtk_expander_paint (GtkExpander *expander, cairo_t *cr)
780 GtkAllocation allocation;
783 widget = GTK_WIDGET (expander);
785 get_expander_bounds (expander, &clip);
786 gtk_widget_get_allocation (widget, &allocation);
788 state = gtk_widget_get_state (widget);
789 if (expander->priv->prelight)
791 state = GTK_STATE_PRELIGHT;
793 gtk_expander_paint_prelight (expander, cr);
796 gtk_paint_expander (gtk_widget_get_style (widget),
801 clip.x + clip.width / 2 - allocation.x,
802 clip.y + clip.height / 2 - allocation.y,
803 expander->priv->expander_style);
807 gtk_expander_paint_focus (GtkExpander *expander,
811 GtkExpanderPrivate *priv;
813 gint x, y, width, height;
814 gboolean interior_focus;
819 gint expander_spacing;
821 GtkAllocation allocation;
823 widget = GTK_WIDGET (expander);
824 priv = expander->priv;
826 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
827 gtk_widget_get_allocation (widget, &allocation);
829 gtk_widget_style_get (widget,
830 "interior-focus", &interior_focus,
831 "focus-line-width", &focus_width,
832 "focus-padding", &focus_pad,
833 "expander-size", &expander_size,
834 "expander-spacing", &expander_spacing,
837 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
841 if (priv->label_widget)
843 if (gtk_widget_get_visible (priv->label_widget))
845 GtkAllocation label_allocation;
847 gtk_widget_get_allocation (priv->label_widget, &label_allocation);
848 width = label_allocation.width;
849 height = label_allocation.height;
852 width += 2 * focus_pad + 2 * focus_width;
853 height += 2 * focus_pad + 2 * focus_width;
861 x += expander_spacing * 2 + expander_size;
865 x += allocation.width - 2 * border_width
866 - expander_spacing * 2 - expander_size - width;
871 width += expander_size + 2 * expander_spacing;
872 height = MAX (height, expander_size + 2 * expander_spacing);
877 get_expander_bounds (expander, &rect);
879 x = rect.x - allocation.x - focus_pad;
880 y = rect.y - allocation.y - focus_pad;
881 width = rect.width + 2 * focus_pad;
882 height = rect.height + 2 * focus_pad;
885 gtk_paint_focus (gtk_widget_get_style (widget),
887 gtk_widget_get_state (widget),
889 x, y, width, height);
893 gtk_expander_draw (GtkWidget *widget,
896 GtkExpander *expander = GTK_EXPANDER (widget);
898 gtk_expander_paint (expander, cr);
900 if (gtk_widget_has_focus (widget))
901 gtk_expander_paint_focus (expander, cr);
903 GTK_WIDGET_CLASS (gtk_expander_parent_class)->draw (widget, cr);
909 gtk_expander_button_press (GtkWidget *widget,
910 GdkEventButton *event)
912 GtkExpander *expander = GTK_EXPANDER (widget);
914 if (event->button == 1 && event->window == expander->priv->event_window)
916 expander->priv->button_down = TRUE;
924 gtk_expander_button_release (GtkWidget *widget,
925 GdkEventButton *event)
927 GtkExpander *expander = GTK_EXPANDER (widget);
929 if (event->button == 1 && expander->priv->button_down)
931 gtk_widget_activate (widget);
932 expander->priv->button_down = FALSE;
940 gtk_expander_grab_notify (GtkWidget *widget,
941 gboolean was_grabbed)
944 GTK_EXPANDER (widget)->priv->button_down = FALSE;
948 gtk_expander_state_changed (GtkWidget *widget,
949 GtkStateType previous_state)
951 if (!gtk_widget_is_sensitive (widget))
952 GTK_EXPANDER (widget)->priv->button_down = FALSE;
956 gtk_expander_redraw_expander (GtkExpander *expander)
958 GtkAllocation allocation;
959 GtkWidget *widget = GTK_WIDGET (expander);
961 if (gtk_widget_get_realized (widget))
963 gtk_widget_get_allocation (widget, &allocation);
964 gdk_window_invalidate_rect (gtk_widget_get_window (widget), &allocation, FALSE);
969 gtk_expander_enter_notify (GtkWidget *widget,
970 GdkEventCrossing *event)
972 GtkExpander *expander = GTK_EXPANDER (widget);
973 GtkWidget *event_widget;
975 event_widget = gtk_get_event_widget ((GdkEvent *) event);
977 if (event_widget == widget &&
978 event->detail != GDK_NOTIFY_INFERIOR)
980 expander->priv->prelight = TRUE;
982 if (expander->priv->label_widget)
983 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_PRELIGHT);
985 gtk_expander_redraw_expander (expander);
992 gtk_expander_leave_notify (GtkWidget *widget,
993 GdkEventCrossing *event)
995 GtkExpander *expander = GTK_EXPANDER (widget);
996 GtkWidget *event_widget;
998 event_widget = gtk_get_event_widget ((GdkEvent *) event);
1000 if (event_widget == widget &&
1001 event->detail != GDK_NOTIFY_INFERIOR)
1003 expander->priv->prelight = FALSE;
1005 if (expander->priv->label_widget)
1006 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_NORMAL);
1008 gtk_expander_redraw_expander (expander);
1015 expand_timeout (gpointer data)
1017 GtkExpander *expander = GTK_EXPANDER (data);
1018 GtkExpanderPrivate *priv = expander->priv;
1020 priv->expand_timer = 0;
1021 gtk_expander_set_expanded (expander, TRUE);
1027 gtk_expander_drag_motion (GtkWidget *widget,
1028 GdkDragContext *context,
1033 GtkExpander *expander = GTK_EXPANDER (widget);
1034 GtkExpanderPrivate *priv = expander->priv;
1036 if (!priv->expanded && !priv->expand_timer)
1038 GtkSettings *settings;
1041 settings = gtk_widget_get_settings (widget);
1042 g_object_get (settings, "gtk-timeout-expand", &timeout, NULL);
1044 priv->expand_timer = gdk_threads_add_timeout (timeout, (GSourceFunc) expand_timeout, expander);
1051 gtk_expander_drag_leave (GtkWidget *widget,
1052 GdkDragContext *context,
1055 GtkExpander *expander = GTK_EXPANDER (widget);
1056 GtkExpanderPrivate *priv = expander->priv;
1058 if (priv->expand_timer)
1060 g_source_remove (priv->expand_timer);
1061 priv->expand_timer = 0;
1074 focus_current_site (GtkExpander *expander,
1075 GtkDirectionType direction)
1077 GtkWidget *current_focus;
1079 current_focus = gtk_container_get_focus_child (GTK_CONTAINER (expander));
1084 return gtk_widget_child_focus (current_focus, direction);
1088 focus_in_site (GtkExpander *expander,
1090 GtkDirectionType direction)
1095 gtk_widget_grab_focus (GTK_WIDGET (expander));
1098 if (expander->priv->label_widget)
1099 return gtk_widget_child_focus (expander->priv->label_widget, direction);
1104 GtkWidget *child = gtk_bin_get_child (GTK_BIN (expander));
1106 if (child && gtk_widget_get_child_visible (child))
1107 return gtk_widget_child_focus (child, direction);
1115 g_assert_not_reached ();
1120 get_next_site (GtkExpander *expander,
1122 GtkDirectionType direction)
1126 ltr = gtk_widget_get_direction (GTK_WIDGET (expander)) != GTK_TEXT_DIR_RTL;
1133 case GTK_DIR_TAB_BACKWARD:
1137 case GTK_DIR_TAB_FORWARD:
1140 return FOCUS_WIDGET;
1145 case GTK_DIR_TAB_BACKWARD:
1149 return ltr ? FOCUS_NONE : FOCUS_LABEL;
1150 case GTK_DIR_TAB_FORWARD:
1154 return ltr ? FOCUS_LABEL : FOCUS_NONE;
1160 case GTK_DIR_TAB_BACKWARD:
1162 return FOCUS_WIDGET;
1164 return ltr ? FOCUS_WIDGET : FOCUS_CHILD;
1165 case GTK_DIR_TAB_FORWARD:
1169 return ltr ? FOCUS_CHILD : FOCUS_WIDGET;
1175 case GTK_DIR_TAB_BACKWARD:
1179 case GTK_DIR_TAB_FORWARD:
1186 g_assert_not_reached ();
1191 gtk_expander_focus (GtkWidget *widget,
1192 GtkDirectionType direction)
1194 GtkExpander *expander = GTK_EXPANDER (widget);
1196 if (!focus_current_site (expander, direction))
1198 GtkWidget *old_focus_child;
1199 gboolean widget_is_focus;
1200 FocusSite site = FOCUS_NONE;
1202 widget_is_focus = gtk_widget_is_focus (widget);
1203 old_focus_child = gtk_container_get_focus_child (GTK_CONTAINER (widget));
1205 if (old_focus_child && old_focus_child == expander->priv->label_widget)
1207 else if (old_focus_child)
1209 else if (widget_is_focus)
1210 site = FOCUS_WIDGET;
1212 while ((site = get_next_site (expander, site, direction)) != FOCUS_NONE)
1214 if (focus_in_site (expander, site, direction))
1225 gtk_expander_add (GtkContainer *container,
1228 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->add (container, widget);
1230 gtk_widget_set_child_visible (widget, GTK_EXPANDER (container)->priv->expanded);
1231 gtk_widget_queue_resize (GTK_WIDGET (container));
1235 gtk_expander_remove (GtkContainer *container,
1238 GtkExpander *expander = GTK_EXPANDER (container);
1240 if (GTK_EXPANDER (expander)->priv->label_widget == widget)
1241 gtk_expander_set_label_widget (expander, NULL);
1243 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->remove (container, widget);
1247 gtk_expander_forall (GtkContainer *container,
1248 gboolean include_internals,
1249 GtkCallback callback,
1250 gpointer callback_data)
1252 GtkBin *bin = GTK_BIN (container);
1253 GtkExpanderPrivate *priv = GTK_EXPANDER (container)->priv;
1256 child = gtk_bin_get_child (bin);
1258 (* callback) (child, callback_data);
1260 if (priv->label_widget)
1261 (* callback) (priv->label_widget, callback_data);
1265 gtk_expander_activate (GtkExpander *expander)
1267 gtk_expander_set_expanded (expander, !expander->priv->expanded);
1272 gtk_expander_get_preferred_width (GtkWidget *widget,
1276 GtkExpander *expander;
1278 GtkExpanderPrivate *priv;
1281 gint expander_spacing;
1282 gboolean interior_focus;
1286 child = gtk_bin_get_child (GTK_BIN (widget));
1287 expander = GTK_EXPANDER (widget);
1288 priv = expander->priv;
1290 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1292 gtk_widget_style_get (GTK_WIDGET (widget),
1293 "interior-focus", &interior_focus,
1294 "focus-line-width", &focus_width,
1295 "focus-padding", &focus_pad,
1296 "expander-size", &expander_size,
1297 "expander-spacing", &expander_spacing,
1300 *minimum_size = *natural_size =
1301 expander_size + 2 * expander_spacing +
1302 2 * focus_width + 2 * focus_pad;
1304 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1306 gint label_min, label_nat;
1308 gtk_widget_get_preferred_width (priv->label_widget,
1309 &label_min, &label_nat);
1311 *minimum_size += label_min;
1312 *natural_size += label_nat;
1315 if (child && gtk_widget_get_child_visible (child))
1317 gint child_min, child_nat;
1319 gtk_widget_get_preferred_width (child,
1320 &child_min, &child_nat);
1322 *minimum_size = MAX (*minimum_size, child_min);
1323 *natural_size = MAX (*natural_size, child_nat);
1327 *minimum_size += 2 * border_width;
1328 *natural_size += 2 * border_width;
1332 gtk_expander_get_preferred_height (GtkWidget *widget,
1336 GtkExpander *expander;
1338 GtkExpanderPrivate *priv;
1341 gint expander_spacing;
1342 gboolean interior_focus;
1346 child = gtk_bin_get_child (GTK_BIN (widget));
1347 expander = GTK_EXPANDER (widget);
1348 priv = expander->priv;
1350 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1352 gtk_widget_style_get (GTK_WIDGET (widget),
1353 "interior-focus", &interior_focus,
1354 "focus-line-width", &focus_width,
1355 "focus-padding", &focus_pad,
1356 "expander-size", &expander_size,
1357 "expander-spacing", &expander_spacing,
1360 *minimum_size = *natural_size =
1361 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1364 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1366 gint label_min, label_nat;
1368 gtk_widget_get_preferred_height (priv->label_widget,
1369 &label_min, &label_nat);
1371 *minimum_size += label_min;
1372 *natural_size += label_nat;
1375 *minimum_size = MAX (*minimum_size, expander_size + 2 * expander_spacing);
1376 *natural_size = MAX (*natural_size, *minimum_size);
1378 if (!interior_focus)
1380 gint extra = 2 * focus_width + 2 * focus_pad;
1381 *minimum_size += extra;
1382 *natural_size += extra;
1385 if (child && gtk_widget_get_child_visible (child))
1387 gint child_min, child_nat;
1389 gtk_widget_get_preferred_height (child,
1390 &child_min, &child_nat);
1392 *minimum_size += child_min + priv->spacing;
1393 *natural_size += child_nat + priv->spacing;
1397 *minimum_size += 2 * border_width;
1398 *natural_size += 2 * border_width;
1402 gtk_expander_get_preferred_height_for_width (GtkWidget *widget,
1404 gint *minimum_height,
1405 gint *natural_height)
1407 GtkExpander *expander;
1409 GtkExpanderPrivate *priv;
1412 gint expander_spacing;
1413 gboolean interior_focus;
1418 child = gtk_bin_get_child (GTK_BIN (widget));
1419 expander = GTK_EXPANDER (widget);
1420 priv = expander->priv;
1422 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1424 gtk_widget_style_get (GTK_WIDGET (widget),
1425 "interior-focus", &interior_focus,
1426 "focus-line-width", &focus_width,
1427 "focus-padding", &focus_pad,
1428 "expander-size", &expander_size,
1429 "expander-spacing", &expander_spacing,
1432 label_xpad = 2 * border_width + expander_size + 2 * expander_spacing - 2 * focus_width + 2 * focus_pad;
1434 *minimum_height = *natural_height =
1435 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1438 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1440 gint label_min, label_nat;
1442 gtk_widget_get_preferred_height_for_width (priv->label_widget,
1443 MAX (width - label_xpad, 1),
1444 &label_min, &label_nat);
1446 *minimum_height += label_min;
1447 *natural_height += label_nat;
1450 *minimum_height = MAX (*minimum_height, expander_size + 2 * expander_spacing);
1451 *natural_height = MAX (*natural_height, *minimum_height);
1453 if (!interior_focus)
1455 gint extra = 2 * focus_width + 2 * focus_pad;
1456 *minimum_height += extra;
1457 *natural_height += extra;
1460 if (child && gtk_widget_get_child_visible (child))
1462 gint child_min, child_nat;
1464 gtk_widget_get_preferred_height_for_width (child,
1465 MAX (width - 2 * border_width, 1),
1466 &child_min, &child_nat);
1468 *minimum_height += child_min + priv->spacing;
1469 *natural_height += child_nat + priv->spacing;
1472 *minimum_height += 2 * border_width;
1473 *natural_height += 2 * border_width;
1477 gtk_expander_get_preferred_width_for_height (GtkWidget *widget,
1479 gint *minimum_width,
1480 gint *natural_width)
1482 GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
1489 * @label: the text of the label
1491 * Creates a new expander using @label as the text of the label.
1493 * Return value: a new #GtkExpander widget.
1498 gtk_expander_new (const gchar *label)
1500 return g_object_new (GTK_TYPE_EXPANDER, "label", label, NULL);
1504 * gtk_expander_new_with_mnemonic:
1505 * @label: (allow-none): the text of the label with an underscore in front of the
1506 * mnemonic character
1508 * Creates a new expander using @label as the text of the label.
1509 * If characters in @label are preceded by an underscore, they are underlined.
1510 * If you need a literal underscore character in a label, use '__' (two
1511 * underscores). The first underlined character represents a keyboard
1512 * accelerator called a mnemonic.
1513 * Pressing Alt and that key activates the button.
1515 * Return value: a new #GtkExpander widget.
1520 gtk_expander_new_with_mnemonic (const gchar *label)
1522 return g_object_new (GTK_TYPE_EXPANDER,
1524 "use-underline", TRUE,
1529 gtk_expander_animation_timeout (GtkExpander *expander)
1531 GtkExpanderPrivate *priv = expander->priv;
1532 GtkWidget *widget = GTK_WIDGET (expander);
1535 gboolean finish = FALSE;
1537 if (gtk_widget_get_realized (widget))
1539 get_expander_bounds (expander, &area);
1540 gdk_window_invalidate_rect (gtk_widget_get_window (widget), &area, TRUE);
1545 if (priv->expander_style == GTK_EXPANDER_COLLAPSED)
1547 priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
1551 priv->expander_style = GTK_EXPANDER_EXPANDED;
1557 if (priv->expander_style == GTK_EXPANDER_EXPANDED)
1559 priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
1563 priv->expander_style = GTK_EXPANDER_COLLAPSED;
1570 priv->animation_timeout = 0;
1572 child = gtk_bin_get_child (GTK_BIN (expander));
1574 gtk_widget_set_child_visible (child, priv->expanded);
1575 gtk_widget_queue_resize (widget);
1582 gtk_expander_start_animation (GtkExpander *expander)
1584 GtkExpanderPrivate *priv = expander->priv;
1586 if (priv->animation_timeout)
1587 g_source_remove (priv->animation_timeout);
1589 priv->animation_timeout =
1590 gdk_threads_add_timeout (50,
1591 (GSourceFunc) gtk_expander_animation_timeout,
1596 * gtk_expander_set_expanded:
1597 * @expander: a #GtkExpander
1598 * @expanded: whether the child widget is revealed
1600 * Sets the state of the expander. Set to %TRUE, if you want
1601 * the child widget to be revealed, and %FALSE if you want the
1602 * child widget to be hidden.
1607 gtk_expander_set_expanded (GtkExpander *expander,
1610 GtkExpanderPrivate *priv;
1613 g_return_if_fail (GTK_IS_EXPANDER (expander));
1615 priv = expander->priv;
1617 expanded = expanded != FALSE;
1619 if (priv->expanded != expanded)
1621 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (expander));
1622 gboolean enable_animations;
1624 priv->expanded = expanded;
1626 g_object_get (settings, "gtk-enable-animations", &enable_animations, NULL);
1628 if (enable_animations && gtk_widget_get_realized (GTK_WIDGET (expander)))
1630 gtk_expander_start_animation (expander);
1634 priv->expander_style = expanded ? GTK_EXPANDER_EXPANDED :
1635 GTK_EXPANDER_COLLAPSED;
1637 child = gtk_bin_get_child (GTK_BIN (expander));
1640 gtk_widget_set_child_visible (child, priv->expanded);
1641 gtk_widget_queue_resize (GTK_WIDGET (expander));
1645 g_object_notify (G_OBJECT (expander), "expanded");
1650 * gtk_expander_get_expanded:
1651 * @expander:a #GtkExpander
1653 * Queries a #GtkExpander and returns its current state. Returns %TRUE
1654 * if the child widget is revealed.
1656 * See gtk_expander_set_expanded().
1658 * Return value: the current state of the expander.
1663 gtk_expander_get_expanded (GtkExpander *expander)
1665 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1667 return expander->priv->expanded;
1671 * gtk_expander_set_spacing:
1672 * @expander: a #GtkExpander
1673 * @spacing: distance between the expander and child in pixels.
1675 * Sets the spacing field of @expander, which is the number of pixels to
1676 * place between expander and the child.
1681 gtk_expander_set_spacing (GtkExpander *expander,
1684 g_return_if_fail (GTK_IS_EXPANDER (expander));
1685 g_return_if_fail (spacing >= 0);
1687 if (expander->priv->spacing != spacing)
1689 expander->priv->spacing = spacing;
1691 gtk_widget_queue_resize (GTK_WIDGET (expander));
1693 g_object_notify (G_OBJECT (expander), "spacing");
1698 * gtk_expander_get_spacing:
1699 * @expander: a #GtkExpander
1701 * Gets the value set by gtk_expander_set_spacing().
1703 * Return value: spacing between the expander and child.
1708 gtk_expander_get_spacing (GtkExpander *expander)
1710 g_return_val_if_fail (GTK_IS_EXPANDER (expander), 0);
1712 return expander->priv->spacing;
1716 * gtk_expander_set_label:
1717 * @expander: a #GtkExpander
1718 * @label: (allow-none): a string
1720 * Sets the text of the label of the expander to @label.
1722 * This will also clear any previously set labels.
1727 gtk_expander_set_label (GtkExpander *expander,
1730 g_return_if_fail (GTK_IS_EXPANDER (expander));
1734 gtk_expander_set_label_widget (expander, NULL);
1740 child = gtk_label_new (label);
1741 gtk_label_set_use_underline (GTK_LABEL (child), expander->priv->use_underline);
1742 gtk_label_set_use_markup (GTK_LABEL (child), expander->priv->use_markup);
1743 gtk_widget_show (child);
1745 gtk_expander_set_label_widget (expander, child);
1748 g_object_notify (G_OBJECT (expander), "label");
1752 * gtk_expander_get_label:
1753 * @expander: a #GtkExpander
1755 * Fetches the text from a label widget including any embedded
1756 * underlines indicating mnemonics and Pango markup, as set by
1757 * gtk_expander_set_label(). If the label text has not been set the
1758 * return value will be %NULL. This will be the case if you create an
1759 * empty button with gtk_button_new() to use as a container.
1761 * Note that this function behaved differently in versions prior to
1762 * 2.14 and used to return the label text stripped of embedded
1763 * underlines indicating mnemonics and Pango markup. This problem can
1764 * be avoided by fetching the label text directly from the label
1767 * Return value: The text of the label widget. This string is owned
1768 * by the widget and must not be modified or freed.
1772 G_CONST_RETURN char *
1773 gtk_expander_get_label (GtkExpander *expander)
1775 GtkExpanderPrivate *priv;
1777 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1779 priv = expander->priv;
1781 if (GTK_IS_LABEL (priv->label_widget))
1782 return gtk_label_get_label (GTK_LABEL (priv->label_widget));
1788 * gtk_expander_set_use_underline:
1789 * @expander: a #GtkExpander
1790 * @use_underline: %TRUE if underlines in the text indicate mnemonics
1792 * If true, an underline in the text of the expander label indicates
1793 * the next character should be used for the mnemonic accelerator key.
1798 gtk_expander_set_use_underline (GtkExpander *expander,
1799 gboolean use_underline)
1801 GtkExpanderPrivate *priv;
1803 g_return_if_fail (GTK_IS_EXPANDER (expander));
1805 priv = expander->priv;
1807 use_underline = use_underline != FALSE;
1809 if (priv->use_underline != use_underline)
1811 priv->use_underline = use_underline;
1813 if (GTK_IS_LABEL (priv->label_widget))
1814 gtk_label_set_use_underline (GTK_LABEL (priv->label_widget), use_underline);
1816 g_object_notify (G_OBJECT (expander), "use-underline");
1821 * gtk_expander_get_use_underline:
1822 * @expander: a #GtkExpander
1824 * Returns whether an embedded underline in the expander label indicates a
1825 * mnemonic. See gtk_expander_set_use_underline().
1827 * Return value: %TRUE if an embedded underline in the expander label
1828 * indicates the mnemonic accelerator keys.
1833 gtk_expander_get_use_underline (GtkExpander *expander)
1835 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1837 return expander->priv->use_underline;
1841 * gtk_expander_set_use_markup:
1842 * @expander: a #GtkExpander
1843 * @use_markup: %TRUE if the label's text should be parsed for markup
1845 * Sets whether the text of the label contains markup in <link
1846 * linkend="PangoMarkupFormat">Pango's text markup
1847 * language</link>. See gtk_label_set_markup().
1852 gtk_expander_set_use_markup (GtkExpander *expander,
1853 gboolean use_markup)
1855 GtkExpanderPrivate *priv;
1857 g_return_if_fail (GTK_IS_EXPANDER (expander));
1859 priv = expander->priv;
1861 use_markup = use_markup != FALSE;
1863 if (priv->use_markup != use_markup)
1865 priv->use_markup = use_markup;
1867 if (GTK_IS_LABEL (priv->label_widget))
1868 gtk_label_set_use_markup (GTK_LABEL (priv->label_widget), use_markup);
1870 g_object_notify (G_OBJECT (expander), "use-markup");
1875 * gtk_expander_get_use_markup:
1876 * @expander: a #GtkExpander
1878 * Returns whether the label's text is interpreted as marked up with
1879 * the <link linkend="PangoMarkupFormat">Pango text markup
1880 * language</link>. See gtk_expander_set_use_markup ().
1882 * Return value: %TRUE if the label's text will be parsed for markup
1887 gtk_expander_get_use_markup (GtkExpander *expander)
1889 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1891 return expander->priv->use_markup;
1895 * gtk_expander_set_label_widget:
1896 * @expander: a #GtkExpander
1897 * @label_widget: (allow-none): the new label widget
1899 * Set the label widget for the expander. This is the widget
1900 * that will appear embedded alongside the expander arrow.
1905 gtk_expander_set_label_widget (GtkExpander *expander,
1906 GtkWidget *label_widget)
1908 GtkExpanderPrivate *priv;
1911 g_return_if_fail (GTK_IS_EXPANDER (expander));
1912 g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
1913 g_return_if_fail (label_widget == NULL || gtk_widget_get_parent (label_widget) == NULL);
1915 priv = expander->priv;
1917 if (priv->label_widget == label_widget)
1920 if (priv->label_widget)
1922 gtk_widget_set_state (priv->label_widget, GTK_STATE_NORMAL);
1923 gtk_widget_unparent (priv->label_widget);
1926 priv->label_widget = label_widget;
1927 widget = GTK_WIDGET (expander);
1931 priv->label_widget = label_widget;
1933 gtk_widget_set_parent (label_widget, widget);
1936 gtk_widget_set_state (label_widget, GTK_STATE_PRELIGHT);
1939 if (gtk_widget_get_visible (widget))
1940 gtk_widget_queue_resize (widget);
1942 g_object_freeze_notify (G_OBJECT (expander));
1943 g_object_notify (G_OBJECT (expander), "label-widget");
1944 g_object_notify (G_OBJECT (expander), "label");
1945 g_object_thaw_notify (G_OBJECT (expander));
1949 * gtk_expander_get_label_widget:
1950 * @expander: a #GtkExpander
1952 * Retrieves the label widget for the frame. See
1953 * gtk_expander_set_label_widget().
1955 * Return value: (transfer none): the label widget,
1956 * or %NULL if there is none.
1961 gtk_expander_get_label_widget (GtkExpander *expander)
1963 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1965 return expander->priv->label_widget;
1969 * gtk_expander_set_label_fill:
1970 * @expander: a #GtkExpander
1971 * @label_fill: %TRUE if the label should should fill all available horizontal
1974 * Sets whether the label widget should fill all available horizontal space
1975 * allocated to @expander.
1980 gtk_expander_set_label_fill (GtkExpander *expander,
1981 gboolean label_fill)
1983 GtkExpanderPrivate *priv;
1985 g_return_if_fail (GTK_IS_EXPANDER (expander));
1987 priv = expander->priv;
1989 label_fill = label_fill != FALSE;
1991 if (priv->label_fill != label_fill)
1993 priv->label_fill = label_fill;
1995 if (priv->label_widget != NULL)
1996 gtk_widget_queue_resize (GTK_WIDGET (expander));
1998 g_object_notify (G_OBJECT (expander), "label-fill");
2003 * gtk_expander_get_label_fill:
2004 * @expander: a #GtkExpander
2006 * Returns whether the label widget will fill all available horizontal
2007 * space allocated to @expander.
2009 * Return value: %TRUE if the label widget will fill all available horizontal
2015 gtk_expander_get_label_fill (GtkExpander *expander)
2017 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
2019 return expander->priv->label_fill;