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);
974 if (event->window == expander->priv->event_window &&
975 event->detail != GDK_NOTIFY_INFERIOR)
977 expander->priv->prelight = TRUE;
979 if (expander->priv->label_widget)
980 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_PRELIGHT);
982 gtk_expander_redraw_expander (expander);
989 gtk_expander_leave_notify (GtkWidget *widget,
990 GdkEventCrossing *event)
992 GtkExpander *expander = GTK_EXPANDER (widget);
994 if (event->window == expander->priv->event_window &&
995 event->detail != GDK_NOTIFY_INFERIOR)
997 expander->priv->prelight = FALSE;
999 if (expander->priv->label_widget)
1000 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_NORMAL);
1002 gtk_expander_redraw_expander (expander);
1009 expand_timeout (gpointer data)
1011 GtkExpander *expander = GTK_EXPANDER (data);
1012 GtkExpanderPrivate *priv = expander->priv;
1014 priv->expand_timer = 0;
1015 gtk_expander_set_expanded (expander, TRUE);
1021 gtk_expander_drag_motion (GtkWidget *widget,
1022 GdkDragContext *context,
1027 GtkExpander *expander = GTK_EXPANDER (widget);
1028 GtkExpanderPrivate *priv = expander->priv;
1030 if (!priv->expanded && !priv->expand_timer)
1032 GtkSettings *settings;
1035 settings = gtk_widget_get_settings (widget);
1036 g_object_get (settings, "gtk-timeout-expand", &timeout, NULL);
1038 priv->expand_timer = gdk_threads_add_timeout (timeout, (GSourceFunc) expand_timeout, expander);
1045 gtk_expander_drag_leave (GtkWidget *widget,
1046 GdkDragContext *context,
1049 GtkExpander *expander = GTK_EXPANDER (widget);
1050 GtkExpanderPrivate *priv = expander->priv;
1052 if (priv->expand_timer)
1054 g_source_remove (priv->expand_timer);
1055 priv->expand_timer = 0;
1068 focus_current_site (GtkExpander *expander,
1069 GtkDirectionType direction)
1071 GtkWidget *current_focus;
1073 current_focus = gtk_container_get_focus_child (GTK_CONTAINER (expander));
1078 return gtk_widget_child_focus (current_focus, direction);
1082 focus_in_site (GtkExpander *expander,
1084 GtkDirectionType direction)
1089 gtk_widget_grab_focus (GTK_WIDGET (expander));
1092 if (expander->priv->label_widget)
1093 return gtk_widget_child_focus (expander->priv->label_widget, direction);
1098 GtkWidget *child = gtk_bin_get_child (GTK_BIN (expander));
1100 if (child && gtk_widget_get_child_visible (child))
1101 return gtk_widget_child_focus (child, direction);
1109 g_assert_not_reached ();
1114 get_next_site (GtkExpander *expander,
1116 GtkDirectionType direction)
1120 ltr = gtk_widget_get_direction (GTK_WIDGET (expander)) != GTK_TEXT_DIR_RTL;
1127 case GTK_DIR_TAB_BACKWARD:
1131 case GTK_DIR_TAB_FORWARD:
1134 return FOCUS_WIDGET;
1139 case GTK_DIR_TAB_BACKWARD:
1143 return ltr ? FOCUS_NONE : FOCUS_LABEL;
1144 case GTK_DIR_TAB_FORWARD:
1148 return ltr ? FOCUS_LABEL : FOCUS_NONE;
1154 case GTK_DIR_TAB_BACKWARD:
1156 return FOCUS_WIDGET;
1158 return ltr ? FOCUS_WIDGET : FOCUS_CHILD;
1159 case GTK_DIR_TAB_FORWARD:
1163 return ltr ? FOCUS_CHILD : FOCUS_WIDGET;
1169 case GTK_DIR_TAB_BACKWARD:
1173 case GTK_DIR_TAB_FORWARD:
1180 g_assert_not_reached ();
1185 gtk_expander_focus (GtkWidget *widget,
1186 GtkDirectionType direction)
1188 GtkExpander *expander = GTK_EXPANDER (widget);
1190 if (!focus_current_site (expander, direction))
1192 GtkWidget *old_focus_child;
1193 gboolean widget_is_focus;
1194 FocusSite site = FOCUS_NONE;
1196 widget_is_focus = gtk_widget_is_focus (widget);
1197 old_focus_child = gtk_container_get_focus_child (GTK_CONTAINER (widget));
1199 if (old_focus_child && old_focus_child == expander->priv->label_widget)
1201 else if (old_focus_child)
1203 else if (widget_is_focus)
1204 site = FOCUS_WIDGET;
1206 while ((site = get_next_site (expander, site, direction)) != FOCUS_NONE)
1208 if (focus_in_site (expander, site, direction))
1219 gtk_expander_add (GtkContainer *container,
1222 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->add (container, widget);
1224 gtk_widget_set_child_visible (widget, GTK_EXPANDER (container)->priv->expanded);
1225 gtk_widget_queue_resize (GTK_WIDGET (container));
1229 gtk_expander_remove (GtkContainer *container,
1232 GtkExpander *expander = GTK_EXPANDER (container);
1234 if (GTK_EXPANDER (expander)->priv->label_widget == widget)
1235 gtk_expander_set_label_widget (expander, NULL);
1237 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->remove (container, widget);
1241 gtk_expander_forall (GtkContainer *container,
1242 gboolean include_internals,
1243 GtkCallback callback,
1244 gpointer callback_data)
1246 GtkBin *bin = GTK_BIN (container);
1247 GtkExpanderPrivate *priv = GTK_EXPANDER (container)->priv;
1250 child = gtk_bin_get_child (bin);
1252 (* callback) (child, callback_data);
1254 if (priv->label_widget)
1255 (* callback) (priv->label_widget, callback_data);
1259 gtk_expander_activate (GtkExpander *expander)
1261 gtk_expander_set_expanded (expander, !expander->priv->expanded);
1266 gtk_expander_get_preferred_width (GtkWidget *widget,
1270 GtkExpander *expander;
1272 GtkExpanderPrivate *priv;
1275 gint expander_spacing;
1276 gboolean interior_focus;
1280 child = gtk_bin_get_child (GTK_BIN (widget));
1281 expander = GTK_EXPANDER (widget);
1282 priv = expander->priv;
1284 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1286 gtk_widget_style_get (GTK_WIDGET (widget),
1287 "interior-focus", &interior_focus,
1288 "focus-line-width", &focus_width,
1289 "focus-padding", &focus_pad,
1290 "expander-size", &expander_size,
1291 "expander-spacing", &expander_spacing,
1294 *minimum_size = *natural_size =
1295 expander_size + 2 * expander_spacing +
1296 2 * focus_width + 2 * focus_pad;
1298 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1300 gint label_min, label_nat;
1302 gtk_widget_get_preferred_width (priv->label_widget,
1303 &label_min, &label_nat);
1305 *minimum_size += label_min;
1306 *natural_size += label_nat;
1309 if (child && gtk_widget_get_child_visible (child))
1311 gint child_min, child_nat;
1313 gtk_widget_get_preferred_width (child,
1314 &child_min, &child_nat);
1316 *minimum_size = MAX (*minimum_size, child_min);
1317 *natural_size = MAX (*natural_size, child_nat);
1321 *minimum_size += 2 * border_width;
1322 *natural_size += 2 * border_width;
1326 gtk_expander_get_preferred_height (GtkWidget *widget,
1330 GtkExpander *expander;
1332 GtkExpanderPrivate *priv;
1335 gint expander_spacing;
1336 gboolean interior_focus;
1340 child = gtk_bin_get_child (GTK_BIN (widget));
1341 expander = GTK_EXPANDER (widget);
1342 priv = expander->priv;
1344 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1346 gtk_widget_style_get (GTK_WIDGET (widget),
1347 "interior-focus", &interior_focus,
1348 "focus-line-width", &focus_width,
1349 "focus-padding", &focus_pad,
1350 "expander-size", &expander_size,
1351 "expander-spacing", &expander_spacing,
1354 *minimum_size = *natural_size =
1355 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1358 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1360 gint label_min, label_nat;
1362 gtk_widget_get_preferred_height (priv->label_widget,
1363 &label_min, &label_nat);
1365 *minimum_size += label_min;
1366 *natural_size += label_nat;
1369 *minimum_size = MAX (*minimum_size, expander_size + 2 * expander_spacing);
1370 *natural_size = MAX (*natural_size, *minimum_size);
1372 if (!interior_focus)
1374 gint extra = 2 * focus_width + 2 * focus_pad;
1375 *minimum_size += extra;
1376 *natural_size += extra;
1379 if (child && gtk_widget_get_child_visible (child))
1381 gint child_min, child_nat;
1383 gtk_widget_get_preferred_height (child,
1384 &child_min, &child_nat);
1386 *minimum_size += child_min + priv->spacing;
1387 *natural_size += child_nat + priv->spacing;
1391 *minimum_size += 2 * border_width;
1392 *natural_size += 2 * border_width;
1396 gtk_expander_get_preferred_height_for_width (GtkWidget *widget,
1398 gint *minimum_height,
1399 gint *natural_height)
1401 GtkExpander *expander;
1403 GtkExpanderPrivate *priv;
1406 gint expander_spacing;
1407 gboolean interior_focus;
1412 child = gtk_bin_get_child (GTK_BIN (widget));
1413 expander = GTK_EXPANDER (widget);
1414 priv = expander->priv;
1416 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1418 gtk_widget_style_get (GTK_WIDGET (widget),
1419 "interior-focus", &interior_focus,
1420 "focus-line-width", &focus_width,
1421 "focus-padding", &focus_pad,
1422 "expander-size", &expander_size,
1423 "expander-spacing", &expander_spacing,
1426 label_xpad = 2 * border_width + expander_size + 2 * expander_spacing - 2 * focus_width + 2 * focus_pad;
1428 *minimum_height = *natural_height =
1429 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1432 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1434 gint label_min, label_nat;
1436 gtk_widget_get_preferred_height_for_width (priv->label_widget,
1437 MAX (width - label_xpad, 1),
1438 &label_min, &label_nat);
1440 *minimum_height += label_min;
1441 *natural_height += label_nat;
1444 *minimum_height = MAX (*minimum_height, expander_size + 2 * expander_spacing);
1445 *natural_height = MAX (*natural_height, *minimum_height);
1447 if (!interior_focus)
1449 gint extra = 2 * focus_width + 2 * focus_pad;
1450 *minimum_height += extra;
1451 *natural_height += extra;
1454 if (child && gtk_widget_get_child_visible (child))
1456 gint child_min, child_nat;
1458 gtk_widget_get_preferred_height_for_width (child,
1459 MAX (width - 2 * border_width, 1),
1460 &child_min, &child_nat);
1462 *minimum_height += child_min + priv->spacing;
1463 *natural_height += child_nat + priv->spacing;
1466 *minimum_height += 2 * border_width;
1467 *natural_height += 2 * border_width;
1471 gtk_expander_get_preferred_width_for_height (GtkWidget *widget,
1473 gint *minimum_width,
1474 gint *natural_width)
1476 GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
1483 * @label: the text of the label
1485 * Creates a new expander using @label as the text of the label.
1487 * Return value: a new #GtkExpander widget.
1492 gtk_expander_new (const gchar *label)
1494 return g_object_new (GTK_TYPE_EXPANDER, "label", label, NULL);
1498 * gtk_expander_new_with_mnemonic:
1499 * @label: (allow-none): the text of the label with an underscore in front of the
1500 * mnemonic character
1502 * Creates a new expander using @label as the text of the label.
1503 * If characters in @label are preceded by an underscore, they are underlined.
1504 * If you need a literal underscore character in a label, use '__' (two
1505 * underscores). The first underlined character represents a keyboard
1506 * accelerator called a mnemonic.
1507 * Pressing Alt and that key activates the button.
1509 * Return value: a new #GtkExpander widget.
1514 gtk_expander_new_with_mnemonic (const gchar *label)
1516 return g_object_new (GTK_TYPE_EXPANDER,
1518 "use-underline", TRUE,
1523 gtk_expander_animation_timeout (GtkExpander *expander)
1525 GtkExpanderPrivate *priv = expander->priv;
1526 GtkWidget *widget = GTK_WIDGET (expander);
1529 gboolean finish = FALSE;
1531 if (gtk_widget_get_realized (widget))
1533 get_expander_bounds (expander, &area);
1534 gdk_window_invalidate_rect (gtk_widget_get_window (widget), &area, TRUE);
1539 if (priv->expander_style == GTK_EXPANDER_COLLAPSED)
1541 priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
1545 priv->expander_style = GTK_EXPANDER_EXPANDED;
1551 if (priv->expander_style == GTK_EXPANDER_EXPANDED)
1553 priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
1557 priv->expander_style = GTK_EXPANDER_COLLAPSED;
1564 priv->animation_timeout = 0;
1566 child = gtk_bin_get_child (GTK_BIN (expander));
1568 gtk_widget_set_child_visible (child, priv->expanded);
1569 gtk_widget_queue_resize (widget);
1576 gtk_expander_start_animation (GtkExpander *expander)
1578 GtkExpanderPrivate *priv = expander->priv;
1580 if (priv->animation_timeout)
1581 g_source_remove (priv->animation_timeout);
1583 priv->animation_timeout =
1584 gdk_threads_add_timeout (50,
1585 (GSourceFunc) gtk_expander_animation_timeout,
1590 * gtk_expander_set_expanded:
1591 * @expander: a #GtkExpander
1592 * @expanded: whether the child widget is revealed
1594 * Sets the state of the expander. Set to %TRUE, if you want
1595 * the child widget to be revealed, and %FALSE if you want the
1596 * child widget to be hidden.
1601 gtk_expander_set_expanded (GtkExpander *expander,
1604 GtkExpanderPrivate *priv;
1607 g_return_if_fail (GTK_IS_EXPANDER (expander));
1609 priv = expander->priv;
1611 expanded = expanded != FALSE;
1613 if (priv->expanded != expanded)
1615 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (expander));
1616 gboolean enable_animations;
1618 priv->expanded = expanded;
1620 g_object_get (settings, "gtk-enable-animations", &enable_animations, NULL);
1622 if (enable_animations && gtk_widget_get_realized (GTK_WIDGET (expander)))
1624 gtk_expander_start_animation (expander);
1628 priv->expander_style = expanded ? GTK_EXPANDER_EXPANDED :
1629 GTK_EXPANDER_COLLAPSED;
1631 child = gtk_bin_get_child (GTK_BIN (expander));
1634 gtk_widget_set_child_visible (child, priv->expanded);
1635 gtk_widget_queue_resize (GTK_WIDGET (expander));
1639 g_object_notify (G_OBJECT (expander), "expanded");
1644 * gtk_expander_get_expanded:
1645 * @expander:a #GtkExpander
1647 * Queries a #GtkExpander and returns its current state. Returns %TRUE
1648 * if the child widget is revealed.
1650 * See gtk_expander_set_expanded().
1652 * Return value: the current state of the expander.
1657 gtk_expander_get_expanded (GtkExpander *expander)
1659 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1661 return expander->priv->expanded;
1665 * gtk_expander_set_spacing:
1666 * @expander: a #GtkExpander
1667 * @spacing: distance between the expander and child in pixels.
1669 * Sets the spacing field of @expander, which is the number of pixels to
1670 * place between expander and the child.
1675 gtk_expander_set_spacing (GtkExpander *expander,
1678 g_return_if_fail (GTK_IS_EXPANDER (expander));
1679 g_return_if_fail (spacing >= 0);
1681 if (expander->priv->spacing != spacing)
1683 expander->priv->spacing = spacing;
1685 gtk_widget_queue_resize (GTK_WIDGET (expander));
1687 g_object_notify (G_OBJECT (expander), "spacing");
1692 * gtk_expander_get_spacing:
1693 * @expander: a #GtkExpander
1695 * Gets the value set by gtk_expander_set_spacing().
1697 * Return value: spacing between the expander and child.
1702 gtk_expander_get_spacing (GtkExpander *expander)
1704 g_return_val_if_fail (GTK_IS_EXPANDER (expander), 0);
1706 return expander->priv->spacing;
1710 * gtk_expander_set_label:
1711 * @expander: a #GtkExpander
1712 * @label: (allow-none): a string
1714 * Sets the text of the label of the expander to @label.
1716 * This will also clear any previously set labels.
1721 gtk_expander_set_label (GtkExpander *expander,
1724 g_return_if_fail (GTK_IS_EXPANDER (expander));
1728 gtk_expander_set_label_widget (expander, NULL);
1734 child = gtk_label_new (label);
1735 gtk_label_set_use_underline (GTK_LABEL (child), expander->priv->use_underline);
1736 gtk_label_set_use_markup (GTK_LABEL (child), expander->priv->use_markup);
1737 gtk_widget_show (child);
1739 gtk_expander_set_label_widget (expander, child);
1742 g_object_notify (G_OBJECT (expander), "label");
1746 * gtk_expander_get_label:
1747 * @expander: a #GtkExpander
1749 * Fetches the text from a label widget including any embedded
1750 * underlines indicating mnemonics and Pango markup, as set by
1751 * gtk_expander_set_label(). If the label text has not been set the
1752 * return value will be %NULL. This will be the case if you create an
1753 * empty button with gtk_button_new() to use as a container.
1755 * Note that this function behaved differently in versions prior to
1756 * 2.14 and used to return the label text stripped of embedded
1757 * underlines indicating mnemonics and Pango markup. This problem can
1758 * be avoided by fetching the label text directly from the label
1761 * Return value: The text of the label widget. This string is owned
1762 * by the widget and must not be modified or freed.
1766 G_CONST_RETURN char *
1767 gtk_expander_get_label (GtkExpander *expander)
1769 GtkExpanderPrivate *priv;
1771 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1773 priv = expander->priv;
1775 if (GTK_IS_LABEL (priv->label_widget))
1776 return gtk_label_get_label (GTK_LABEL (priv->label_widget));
1782 * gtk_expander_set_use_underline:
1783 * @expander: a #GtkExpander
1784 * @use_underline: %TRUE if underlines in the text indicate mnemonics
1786 * If true, an underline in the text of the expander label indicates
1787 * the next character should be used for the mnemonic accelerator key.
1792 gtk_expander_set_use_underline (GtkExpander *expander,
1793 gboolean use_underline)
1795 GtkExpanderPrivate *priv;
1797 g_return_if_fail (GTK_IS_EXPANDER (expander));
1799 priv = expander->priv;
1801 use_underline = use_underline != FALSE;
1803 if (priv->use_underline != use_underline)
1805 priv->use_underline = use_underline;
1807 if (GTK_IS_LABEL (priv->label_widget))
1808 gtk_label_set_use_underline (GTK_LABEL (priv->label_widget), use_underline);
1810 g_object_notify (G_OBJECT (expander), "use-underline");
1815 * gtk_expander_get_use_underline:
1816 * @expander: a #GtkExpander
1818 * Returns whether an embedded underline in the expander label indicates a
1819 * mnemonic. See gtk_expander_set_use_underline().
1821 * Return value: %TRUE if an embedded underline in the expander label
1822 * indicates the mnemonic accelerator keys.
1827 gtk_expander_get_use_underline (GtkExpander *expander)
1829 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1831 return expander->priv->use_underline;
1835 * gtk_expander_set_use_markup:
1836 * @expander: a #GtkExpander
1837 * @use_markup: %TRUE if the label's text should be parsed for markup
1839 * Sets whether the text of the label contains markup in <link
1840 * linkend="PangoMarkupFormat">Pango's text markup
1841 * language</link>. See gtk_label_set_markup().
1846 gtk_expander_set_use_markup (GtkExpander *expander,
1847 gboolean use_markup)
1849 GtkExpanderPrivate *priv;
1851 g_return_if_fail (GTK_IS_EXPANDER (expander));
1853 priv = expander->priv;
1855 use_markup = use_markup != FALSE;
1857 if (priv->use_markup != use_markup)
1859 priv->use_markup = use_markup;
1861 if (GTK_IS_LABEL (priv->label_widget))
1862 gtk_label_set_use_markup (GTK_LABEL (priv->label_widget), use_markup);
1864 g_object_notify (G_OBJECT (expander), "use-markup");
1869 * gtk_expander_get_use_markup:
1870 * @expander: a #GtkExpander
1872 * Returns whether the label's text is interpreted as marked up with
1873 * the <link linkend="PangoMarkupFormat">Pango text markup
1874 * language</link>. See gtk_expander_set_use_markup ().
1876 * Return value: %TRUE if the label's text will be parsed for markup
1881 gtk_expander_get_use_markup (GtkExpander *expander)
1883 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1885 return expander->priv->use_markup;
1889 * gtk_expander_set_label_widget:
1890 * @expander: a #GtkExpander
1891 * @label_widget: (allow-none): the new label widget
1893 * Set the label widget for the expander. This is the widget
1894 * that will appear embedded alongside the expander arrow.
1899 gtk_expander_set_label_widget (GtkExpander *expander,
1900 GtkWidget *label_widget)
1902 GtkExpanderPrivate *priv;
1905 g_return_if_fail (GTK_IS_EXPANDER (expander));
1906 g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
1907 g_return_if_fail (label_widget == NULL || gtk_widget_get_parent (label_widget) == NULL);
1909 priv = expander->priv;
1911 if (priv->label_widget == label_widget)
1914 if (priv->label_widget)
1916 gtk_widget_set_state (priv->label_widget, GTK_STATE_NORMAL);
1917 gtk_widget_unparent (priv->label_widget);
1920 priv->label_widget = label_widget;
1921 widget = GTK_WIDGET (expander);
1925 priv->label_widget = label_widget;
1927 gtk_widget_set_parent (label_widget, widget);
1930 gtk_widget_set_state (label_widget, GTK_STATE_PRELIGHT);
1933 if (gtk_widget_get_visible (widget))
1934 gtk_widget_queue_resize (widget);
1936 g_object_freeze_notify (G_OBJECT (expander));
1937 g_object_notify (G_OBJECT (expander), "label-widget");
1938 g_object_notify (G_OBJECT (expander), "label");
1939 g_object_thaw_notify (G_OBJECT (expander));
1943 * gtk_expander_get_label_widget:
1944 * @expander: a #GtkExpander
1946 * Retrieves the label widget for the frame. See
1947 * gtk_expander_set_label_widget().
1949 * Return value: (transfer none): the label widget,
1950 * or %NULL if there is none.
1955 gtk_expander_get_label_widget (GtkExpander *expander)
1957 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1959 return expander->priv->label_widget;
1963 * gtk_expander_set_label_fill:
1964 * @expander: a #GtkExpander
1965 * @label_fill: %TRUE if the label should should fill all available horizontal
1968 * Sets whether the label widget should fill all available horizontal space
1969 * allocated to @expander.
1974 gtk_expander_set_label_fill (GtkExpander *expander,
1975 gboolean label_fill)
1977 GtkExpanderPrivate *priv;
1979 g_return_if_fail (GTK_IS_EXPANDER (expander));
1981 priv = expander->priv;
1983 label_fill = label_fill != FALSE;
1985 if (priv->label_fill != label_fill)
1987 priv->label_fill = label_fill;
1989 if (priv->label_widget != NULL)
1990 gtk_widget_queue_resize (GTK_WIDGET (expander));
1992 g_object_notify (G_OBJECT (expander), "label-fill");
1997 * gtk_expander_get_label_fill:
1998 * @expander: a #GtkExpander
2000 * Returns whether the label widget will fill all available horizontal
2001 * space allocated to @expander.
2003 * Return value: %TRUE if the label widget will fill all available horizontal
2009 gtk_expander_get_label_fill (GtkExpander *expander)
2011 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
2013 return expander->priv->label_fill;