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 "gtksizerequest.h"
31 #include "gtkcontainer.h"
32 #include "gtkmarshalers.h"
35 #include "gtkprivate.h"
36 #include <gdk/gdkkeysyms.h>
40 #define DEFAULT_EXPANDER_SIZE 10
41 #define DEFAULT_EXPANDER_SPACING 2
55 struct _GtkExpanderPrivate
57 GtkWidget *label_widget;
58 GdkWindow *event_window;
61 GtkExpanderStyle expander_style;
62 guint animation_timeout;
66 guint use_underline : 1;
68 guint button_down : 1;
73 static void gtk_expander_set_property (GObject *object,
77 static void gtk_expander_get_property (GObject *object,
82 static void gtk_expander_destroy (GtkObject *object);
84 static void gtk_expander_realize (GtkWidget *widget);
85 static void gtk_expander_unrealize (GtkWidget *widget);
86 static void gtk_expander_size_allocate (GtkWidget *widget,
87 GtkAllocation *allocation);
88 static void gtk_expander_map (GtkWidget *widget);
89 static void gtk_expander_unmap (GtkWidget *widget);
90 static gboolean gtk_expander_expose (GtkWidget *widget,
91 GdkEventExpose *event);
92 static gboolean gtk_expander_button_press (GtkWidget *widget,
93 GdkEventButton *event);
94 static gboolean gtk_expander_button_release (GtkWidget *widget,
95 GdkEventButton *event);
96 static gboolean gtk_expander_enter_notify (GtkWidget *widget,
97 GdkEventCrossing *event);
98 static gboolean gtk_expander_leave_notify (GtkWidget *widget,
99 GdkEventCrossing *event);
100 static gboolean gtk_expander_focus (GtkWidget *widget,
101 GtkDirectionType direction);
102 static void gtk_expander_grab_notify (GtkWidget *widget,
103 gboolean was_grabbed);
104 static void gtk_expander_state_changed (GtkWidget *widget,
105 GtkStateType previous_state);
106 static gboolean gtk_expander_drag_motion (GtkWidget *widget,
107 GdkDragContext *context,
111 static void gtk_expander_drag_leave (GtkWidget *widget,
112 GdkDragContext *context,
115 static void gtk_expander_add (GtkContainer *container,
117 static void gtk_expander_remove (GtkContainer *container,
119 static void gtk_expander_forall (GtkContainer *container,
120 gboolean include_internals,
121 GtkCallback callback,
122 gpointer callback_data);
124 static void gtk_expander_activate (GtkExpander *expander);
126 static void get_expander_bounds (GtkExpander *expander,
130 static void gtk_expander_buildable_init (GtkBuildableIface *iface);
131 static void gtk_expander_buildable_add_child (GtkBuildable *buildable,
138 static void gtk_expander_size_request_init (GtkSizeRequestIface *iface);
139 static void gtk_expander_get_width (GtkSizeRequest *widget,
142 static void gtk_expander_get_height (GtkSizeRequest *widget,
145 static void gtk_expander_get_height_for_width (GtkSizeRequest *layout,
147 gint *minimum_height,
148 gint *natural_height);
149 static void gtk_expander_get_width_for_height (GtkSizeRequest *layout,
151 gint *minimum_height,
152 gint *natural_height);
154 G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
155 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
156 gtk_expander_buildable_init)
157 G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
158 gtk_expander_size_request_init))
161 gtk_expander_class_init (GtkExpanderClass *klass)
163 GObjectClass *gobject_class;
164 GtkObjectClass *object_class;
165 GtkWidgetClass *widget_class;
166 GtkContainerClass *container_class;
168 gobject_class = (GObjectClass *) klass;
169 object_class = (GtkObjectClass *) klass;
170 widget_class = (GtkWidgetClass *) klass;
171 container_class = (GtkContainerClass *) klass;
173 gobject_class->set_property = gtk_expander_set_property;
174 gobject_class->get_property = gtk_expander_get_property;
176 object_class->destroy = gtk_expander_destroy;
178 widget_class->realize = gtk_expander_realize;
179 widget_class->unrealize = gtk_expander_unrealize;
180 widget_class->size_allocate = gtk_expander_size_allocate;
181 widget_class->map = gtk_expander_map;
182 widget_class->unmap = gtk_expander_unmap;
183 widget_class->expose_event = gtk_expander_expose;
184 widget_class->button_press_event = gtk_expander_button_press;
185 widget_class->button_release_event = gtk_expander_button_release;
186 widget_class->enter_notify_event = gtk_expander_enter_notify;
187 widget_class->leave_notify_event = gtk_expander_leave_notify;
188 widget_class->focus = gtk_expander_focus;
189 widget_class->grab_notify = gtk_expander_grab_notify;
190 widget_class->state_changed = gtk_expander_state_changed;
191 widget_class->drag_motion = gtk_expander_drag_motion;
192 widget_class->drag_leave = gtk_expander_drag_leave;
194 container_class->add = gtk_expander_add;
195 container_class->remove = gtk_expander_remove;
196 container_class->forall = gtk_expander_forall;
198 klass->activate = gtk_expander_activate;
200 g_type_class_add_private (klass, sizeof (GtkExpanderPrivate));
202 g_object_class_install_property (gobject_class,
204 g_param_spec_boolean ("expanded",
206 P_("Whether the expander has been opened to reveal the child widget"),
208 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
210 g_object_class_install_property (gobject_class,
212 g_param_spec_string ("label",
214 P_("Text of the expander's label"),
216 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
218 g_object_class_install_property (gobject_class,
220 g_param_spec_boolean ("use-underline",
222 P_("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
224 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
226 g_object_class_install_property (gobject_class,
228 g_param_spec_boolean ("use-markup",
230 P_("The text of the label includes XML markup. See pango_parse_markup()"),
232 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
234 g_object_class_install_property (gobject_class,
236 g_param_spec_int ("spacing",
238 P_("Space to put between the label and the child"),
242 GTK_PARAM_READWRITE));
244 g_object_class_install_property (gobject_class,
246 g_param_spec_object ("label-widget",
248 P_("A widget to display in place of the usual expander label"),
250 GTK_PARAM_READWRITE));
252 g_object_class_install_property (gobject_class,
254 g_param_spec_boolean ("label-fill",
256 P_("Whether the label widget should fill all available horizontal space"),
258 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
260 gtk_widget_class_install_style_property (widget_class,
261 g_param_spec_int ("expander-size",
263 P_("Size of the expander arrow"),
266 DEFAULT_EXPANDER_SIZE,
267 GTK_PARAM_READABLE));
269 gtk_widget_class_install_style_property (widget_class,
270 g_param_spec_int ("expander-spacing",
271 P_("Indicator Spacing"),
272 P_("Spacing around expander arrow"),
275 DEFAULT_EXPANDER_SPACING,
276 GTK_PARAM_READABLE));
278 widget_class->activate_signal =
279 g_signal_new (I_("activate"),
280 G_TYPE_FROM_CLASS (gobject_class),
281 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
282 G_STRUCT_OFFSET (GtkExpanderClass, activate),
284 _gtk_marshal_VOID__VOID,
289 gtk_expander_init (GtkExpander *expander)
291 GtkExpanderPrivate *priv;
293 expander->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (expander,
297 gtk_widget_set_can_focus (GTK_WIDGET (expander), TRUE);
298 gtk_widget_set_has_window (GTK_WIDGET (expander), FALSE);
300 priv->label_widget = NULL;
301 priv->event_window = NULL;
304 priv->expander_style = GTK_EXPANDER_COLLAPSED;
305 priv->animation_timeout = 0;
307 priv->expanded = FALSE;
308 priv->use_underline = FALSE;
309 priv->use_markup = FALSE;
310 priv->button_down = FALSE;
311 priv->prelight = FALSE;
312 priv->label_fill = FALSE;
313 priv->expand_timer = 0;
315 gtk_drag_dest_set (GTK_WIDGET (expander), 0, NULL, 0, 0);
316 gtk_drag_dest_set_track_motion (GTK_WIDGET (expander), TRUE);
320 gtk_expander_buildable_add_child (GtkBuildable *buildable,
326 gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
327 else if (strcmp (type, "label") == 0)
328 gtk_expander_set_label_widget (GTK_EXPANDER (buildable), GTK_WIDGET (child));
330 GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_EXPANDER (buildable), type);
334 gtk_expander_buildable_init (GtkBuildableIface *iface)
336 iface->add_child = gtk_expander_buildable_add_child;
340 gtk_expander_set_property (GObject *object,
345 GtkExpander *expander = GTK_EXPANDER (object);
350 gtk_expander_set_expanded (expander, g_value_get_boolean (value));
353 gtk_expander_set_label (expander, g_value_get_string (value));
355 case PROP_USE_UNDERLINE:
356 gtk_expander_set_use_underline (expander, g_value_get_boolean (value));
358 case PROP_USE_MARKUP:
359 gtk_expander_set_use_markup (expander, g_value_get_boolean (value));
362 gtk_expander_set_spacing (expander, g_value_get_int (value));
364 case PROP_LABEL_WIDGET:
365 gtk_expander_set_label_widget (expander, g_value_get_object (value));
367 case PROP_LABEL_FILL:
368 gtk_expander_set_label_fill (expander, g_value_get_boolean (value));
371 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
377 gtk_expander_get_property (GObject *object,
382 GtkExpander *expander = GTK_EXPANDER (object);
383 GtkExpanderPrivate *priv = expander->priv;
388 g_value_set_boolean (value, priv->expanded);
391 g_value_set_string (value, gtk_expander_get_label (expander));
393 case PROP_USE_UNDERLINE:
394 g_value_set_boolean (value, priv->use_underline);
396 case PROP_USE_MARKUP:
397 g_value_set_boolean (value, priv->use_markup);
400 g_value_set_int (value, priv->spacing);
402 case PROP_LABEL_WIDGET:
403 g_value_set_object (value,
405 G_OBJECT (priv->label_widget) : NULL);
407 case PROP_LABEL_FILL:
408 g_value_set_boolean (value, priv->label_fill);
411 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
417 gtk_expander_destroy (GtkObject *object)
419 GtkExpanderPrivate *priv = GTK_EXPANDER (object)->priv;
421 if (priv->animation_timeout)
423 g_source_remove (priv->animation_timeout);
424 priv->animation_timeout = 0;
427 GTK_OBJECT_CLASS (gtk_expander_parent_class)->destroy (object);
431 gtk_expander_realize (GtkWidget *widget)
433 GtkExpanderPrivate *priv;
434 GdkWindowAttr attributes;
435 gint attributes_mask;
437 GdkRectangle expander_rect;
440 priv = GTK_EXPANDER (widget)->priv;
441 gtk_widget_set_realized (widget, TRUE);
443 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
445 get_expander_bounds (GTK_EXPANDER (widget), &expander_rect);
447 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
449 GtkRequisition label_requisition;
451 gtk_widget_get_child_requisition (priv->label_widget, &label_requisition);
452 label_height = label_requisition.height;
457 attributes.window_type = GDK_WINDOW_CHILD;
458 attributes.x = widget->allocation.x + border_width;
459 attributes.y = widget->allocation.y + border_width;
460 attributes.width = MAX (widget->allocation.width - 2 * border_width, 1);
461 attributes.height = MAX (expander_rect.height, label_height - 2 * border_width);
462 attributes.wclass = GDK_INPUT_ONLY;
463 attributes.event_mask = gtk_widget_get_events (widget) |
464 GDK_BUTTON_PRESS_MASK |
465 GDK_BUTTON_RELEASE_MASK |
466 GDK_ENTER_NOTIFY_MASK |
467 GDK_LEAVE_NOTIFY_MASK;
469 attributes_mask = GDK_WA_X | GDK_WA_Y;
471 widget->window = gtk_widget_get_parent_window (widget);
472 g_object_ref (widget->window);
474 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
475 &attributes, attributes_mask);
476 gdk_window_set_user_data (priv->event_window, widget);
478 widget->style = gtk_style_attach (widget->style, widget->window);
482 gtk_expander_unrealize (GtkWidget *widget)
484 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
486 if (priv->event_window)
488 gdk_window_set_user_data (priv->event_window, NULL);
489 gdk_window_destroy (priv->event_window);
490 priv->event_window = NULL;
493 GTK_WIDGET_CLASS (gtk_expander_parent_class)->unrealize (widget);
497 get_expander_bounds (GtkExpander *expander,
501 GtkExpanderPrivate *priv;
504 gint expander_spacing;
505 gboolean interior_focus;
510 widget = GTK_WIDGET (expander);
511 priv = expander->priv;
513 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
515 gtk_widget_style_get (widget,
516 "interior-focus", &interior_focus,
517 "focus-line-width", &focus_width,
518 "focus-padding", &focus_pad,
519 "expander-size", &expander_size,
520 "expander-spacing", &expander_spacing,
523 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
525 rect->x = widget->allocation.x + border_width;
526 rect->y = widget->allocation.y + border_width;
529 rect->x += expander_spacing;
531 rect->x += widget->allocation.width - 2 * border_width -
532 expander_spacing - expander_size;
534 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
536 GtkAllocation label_allocation;
538 label_allocation = priv->label_widget->allocation;
540 if (expander_size < label_allocation.height)
541 rect->y += focus_width + focus_pad + (label_allocation.height - expander_size) / 2;
543 rect->y += expander_spacing;
547 rect->y += expander_spacing;
553 rect->x += focus_width + focus_pad;
555 rect->x -= focus_width + focus_pad;
556 rect->y += focus_width + focus_pad;
559 rect->width = rect->height = expander_size;
563 gtk_expander_size_allocate (GtkWidget *widget,
564 GtkAllocation *allocation)
566 GtkExpander *expander;
568 GtkExpanderPrivate *priv;
569 gboolean child_visible = FALSE;
572 gint expander_spacing;
573 gboolean interior_focus;
576 gint label_height, top_min_height;
577 gint label_xpad, label_xoffset;
578 gint child_ypad, child_yoffset;
580 expander = GTK_EXPANDER (widget);
581 child = gtk_bin_get_child (GTK_BIN (widget));
582 priv = expander->priv;
584 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
586 widget->allocation = *allocation;
588 gtk_widget_style_get (widget,
589 "interior-focus", &interior_focus,
590 "focus-line-width", &focus_width,
591 "focus-padding", &focus_pad,
592 "expander-size", &expander_size,
593 "expander-spacing", &expander_spacing,
597 /* Calculate some offsets/padding first */
598 label_xoffset = border_width + expander_size + focus_width + 2 * expander_spacing + focus_pad;
599 label_xpad = 2 * border_width + expander_size + 2 * focus_width + 2 * expander_spacing + 2 * focus_pad;
601 child_yoffset = border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
602 child_ypad = 2 * border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
603 top_min_height = 2 * expander_spacing + expander_size;
605 child_visible = (child && GTK_WIDGET_CHILD_VISIBLE (child));
607 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
609 GtkAllocation label_allocation;
610 gint natural_label_width;
613 gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget), NULL, &natural_label_width);
615 if (priv->label_fill)
616 label_allocation.width = allocation->width - label_xpad;
618 label_allocation.width = MIN (natural_label_width, allocation->width - label_xpad);
619 label_allocation.width = MAX (label_allocation.width, 1);
621 /* We distribute the minimum height to the label widget and prioritize
622 * the child widget giving it the remaining height */
623 gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
624 label_allocation.width, &label_height, NULL);
626 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
628 if (priv->label_fill)
629 label_allocation.x = widget->allocation.x + label_xoffset;
631 label_allocation.x = widget->allocation.x + label_xoffset;
634 widget->allocation.x + widget->allocation.width -
635 (label_allocation.width + label_xoffset);
637 label_allocation.y = widget->allocation.y + border_width + focus_width + focus_pad;
638 label_allocation.height = MIN (label_height,
639 allocation->height - 2 * border_width -
640 2 * focus_width - 2 * focus_pad -
641 (child_visible ? priv->spacing : 0));
642 label_allocation.height = MAX (label_allocation.height, 1);
644 gtk_widget_size_allocate (priv->label_widget, &label_allocation);
646 label_height = label_allocation.height;
653 if (gtk_widget_get_realized (widget))
657 get_expander_bounds (expander, &rect);
659 gdk_window_move_resize (priv->event_window,
660 allocation->x + border_width,
661 allocation->y + border_width,
662 MAX (allocation->width - 2 * border_width, 1),
663 MAX (rect.height, label_height - 2 * border_width));
668 GtkAllocation child_allocation;
671 top_height = MAX (top_min_height,
672 label_height + (interior_focus ? 2 * focus_width + 2 * focus_pad : 0));
674 child_allocation.x = widget->allocation.x + border_width;
675 child_allocation.y = widget->allocation.y + top_height + child_yoffset;
677 child_allocation.width = MAX (allocation->width - 2 * border_width, 1);
678 child_allocation.height = allocation->height - top_height - child_ypad;
679 child_allocation.height = MAX (child_allocation.height, 1);
681 gtk_widget_size_allocate (child, &child_allocation);
686 gtk_expander_map (GtkWidget *widget)
688 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
690 if (priv->label_widget)
691 gtk_widget_map (priv->label_widget);
693 GTK_WIDGET_CLASS (gtk_expander_parent_class)->map (widget);
695 if (priv->event_window)
696 gdk_window_show (priv->event_window);
700 gtk_expander_unmap (GtkWidget *widget)
702 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
704 if (priv->event_window)
705 gdk_window_hide (priv->event_window);
707 GTK_WIDGET_CLASS (gtk_expander_parent_class)->unmap (widget);
709 if (priv->label_widget)
710 gtk_widget_unmap (priv->label_widget);
714 gtk_expander_paint_prelight (GtkExpander *expander)
717 GtkContainer *container;
718 GtkExpanderPrivate *priv;
720 gboolean interior_focus;
724 int expander_spacing;
727 priv = expander->priv;
728 widget = GTK_WIDGET (expander);
729 container = GTK_CONTAINER (expander);
731 gtk_widget_style_get (widget,
732 "interior-focus", &interior_focus,
733 "focus-line-width", &focus_width,
734 "focus-padding", &focus_pad,
735 "expander-size", &expander_size,
736 "expander-spacing", &expander_spacing,
739 border_width = gtk_container_get_border_width (container);
740 area.x = widget->allocation.x + border_width;
741 area.y = widget->allocation.y + border_width;
742 area.width = widget->allocation.width - (2 * border_width);
744 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
745 area.height = priv->label_widget->allocation.height;
749 area.height += interior_focus ? (focus_width + focus_pad) * 2 : 0;
750 area.height = MAX (area.height, expander_size + 2 * expander_spacing);
751 area.height += !interior_focus ? (focus_width + focus_pad) * 2 : 0;
753 gtk_paint_flat_box (widget->style, widget->window,
755 GTK_SHADOW_ETCHED_OUT,
756 &area, widget, "expander",
758 area.width, area.height);
762 gtk_expander_paint (GtkExpander *expander)
768 widget = GTK_WIDGET (expander);
770 get_expander_bounds (expander, &clip);
772 state = widget->state;
773 if (expander->priv->prelight)
775 state = GTK_STATE_PRELIGHT;
777 gtk_expander_paint_prelight (expander);
780 gtk_paint_expander (widget->style,
786 clip.x + clip.width / 2,
787 clip.y + clip.height / 2,
788 expander->priv->expander_style);
792 gtk_expander_paint_focus (GtkExpander *expander,
796 GtkExpanderPrivate *priv;
798 gint x, y, width, height;
799 gboolean interior_focus;
804 gint expander_spacing;
807 widget = GTK_WIDGET (expander);
808 priv = expander->priv;
810 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
812 gtk_widget_style_get (widget,
813 "interior-focus", &interior_focus,
814 "focus-line-width", &focus_width,
815 "focus-padding", &focus_pad,
816 "expander-size", &expander_size,
817 "expander-spacing", &expander_spacing,
820 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
824 if (priv->label_widget)
826 if (gtk_widget_get_visible (priv->label_widget))
828 GtkAllocation label_allocation;
830 gtk_widget_get_allocation (priv->label_widget, &label_allocation);
831 width = label_allocation.width;
832 height = label_allocation.height;
835 width += 2 * focus_pad + 2 * focus_width;
836 height += 2 * focus_pad + 2 * focus_width;
838 x = widget->allocation.x + border_width;
839 y = widget->allocation.y + border_width;
844 x += expander_spacing * 2 + expander_size;
848 x += widget->allocation.width - 2 * border_width
849 - expander_spacing * 2 - expander_size - width;
854 width += expander_size + 2 * expander_spacing;
855 height = MAX (height, expander_size + 2 * expander_spacing);
860 get_expander_bounds (expander, &rect);
862 x = rect.x - focus_pad;
863 y = rect.y - focus_pad;
864 width = rect.width + 2 * focus_pad;
865 height = rect.height + 2 * focus_pad;
868 gtk_paint_focus (widget->style, widget->window, gtk_widget_get_state (widget),
869 area, widget, "expander",
870 x, y, width, height);
874 gtk_expander_expose (GtkWidget *widget,
875 GdkEventExpose *event)
877 if (gtk_widget_is_drawable (widget))
879 GtkExpander *expander = GTK_EXPANDER (widget);
881 gtk_expander_paint (expander);
883 if (gtk_widget_has_focus (widget))
884 gtk_expander_paint_focus (expander, &event->area);
886 GTK_WIDGET_CLASS (gtk_expander_parent_class)->expose_event (widget, event);
893 gtk_expander_button_press (GtkWidget *widget,
894 GdkEventButton *event)
896 GtkExpander *expander = GTK_EXPANDER (widget);
898 if (event->button == 1 && event->window == expander->priv->event_window)
900 expander->priv->button_down = TRUE;
908 gtk_expander_button_release (GtkWidget *widget,
909 GdkEventButton *event)
911 GtkExpander *expander = GTK_EXPANDER (widget);
913 if (event->button == 1 && expander->priv->button_down)
915 gtk_widget_activate (widget);
916 expander->priv->button_down = FALSE;
924 gtk_expander_grab_notify (GtkWidget *widget,
925 gboolean was_grabbed)
928 GTK_EXPANDER (widget)->priv->button_down = FALSE;
932 gtk_expander_state_changed (GtkWidget *widget,
933 GtkStateType previous_state)
935 if (!gtk_widget_is_sensitive (widget))
936 GTK_EXPANDER (widget)->priv->button_down = FALSE;
940 gtk_expander_redraw_expander (GtkExpander *expander)
944 widget = GTK_WIDGET (expander);
946 if (gtk_widget_get_realized (widget))
947 gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
951 gtk_expander_enter_notify (GtkWidget *widget,
952 GdkEventCrossing *event)
954 GtkExpander *expander = GTK_EXPANDER (widget);
955 GtkWidget *event_widget;
957 event_widget = gtk_get_event_widget ((GdkEvent *) event);
959 if (event_widget == widget &&
960 event->detail != GDK_NOTIFY_INFERIOR)
962 expander->priv->prelight = TRUE;
964 if (expander->priv->label_widget)
965 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_PRELIGHT);
967 gtk_expander_redraw_expander (expander);
974 gtk_expander_leave_notify (GtkWidget *widget,
975 GdkEventCrossing *event)
977 GtkExpander *expander = GTK_EXPANDER (widget);
978 GtkWidget *event_widget;
980 event_widget = gtk_get_event_widget ((GdkEvent *) event);
982 if (event_widget == widget &&
983 event->detail != GDK_NOTIFY_INFERIOR)
985 expander->priv->prelight = FALSE;
987 if (expander->priv->label_widget)
988 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_NORMAL);
990 gtk_expander_redraw_expander (expander);
997 expand_timeout (gpointer data)
999 GtkExpander *expander = GTK_EXPANDER (data);
1000 GtkExpanderPrivate *priv = expander->priv;
1002 priv->expand_timer = 0;
1003 gtk_expander_set_expanded (expander, TRUE);
1009 gtk_expander_drag_motion (GtkWidget *widget,
1010 GdkDragContext *context,
1015 GtkExpander *expander = GTK_EXPANDER (widget);
1016 GtkExpanderPrivate *priv = expander->priv;
1018 if (!priv->expanded && !priv->expand_timer)
1020 GtkSettings *settings;
1023 settings = gtk_widget_get_settings (widget);
1024 g_object_get (settings, "gtk-timeout-expand", &timeout, NULL);
1026 priv->expand_timer = gdk_threads_add_timeout (timeout, (GSourceFunc) expand_timeout, expander);
1033 gtk_expander_drag_leave (GtkWidget *widget,
1034 GdkDragContext *context,
1037 GtkExpander *expander = GTK_EXPANDER (widget);
1038 GtkExpanderPrivate *priv = expander->priv;
1040 if (priv->expand_timer)
1042 g_source_remove (priv->expand_timer);
1043 priv->expand_timer = 0;
1056 focus_current_site (GtkExpander *expander,
1057 GtkDirectionType direction)
1059 GtkWidget *current_focus;
1061 current_focus = gtk_container_get_focus_child (GTK_CONTAINER (expander));
1066 return gtk_widget_child_focus (current_focus, direction);
1070 focus_in_site (GtkExpander *expander,
1072 GtkDirectionType direction)
1077 gtk_widget_grab_focus (GTK_WIDGET (expander));
1080 if (expander->priv->label_widget)
1081 return gtk_widget_child_focus (expander->priv->label_widget, direction);
1086 GtkWidget *child = gtk_bin_get_child (GTK_BIN (expander));
1088 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1089 return gtk_widget_child_focus (child, direction);
1097 g_assert_not_reached ();
1102 get_next_site (GtkExpander *expander,
1104 GtkDirectionType direction)
1108 ltr = gtk_widget_get_direction (GTK_WIDGET (expander)) != GTK_TEXT_DIR_RTL;
1115 case GTK_DIR_TAB_BACKWARD:
1119 case GTK_DIR_TAB_FORWARD:
1122 return FOCUS_WIDGET;
1127 case GTK_DIR_TAB_BACKWARD:
1131 return ltr ? FOCUS_NONE : FOCUS_LABEL;
1132 case GTK_DIR_TAB_FORWARD:
1136 return ltr ? FOCUS_LABEL : FOCUS_NONE;
1142 case GTK_DIR_TAB_BACKWARD:
1144 return FOCUS_WIDGET;
1146 return ltr ? FOCUS_WIDGET : FOCUS_CHILD;
1147 case GTK_DIR_TAB_FORWARD:
1151 return ltr ? FOCUS_CHILD : FOCUS_WIDGET;
1157 case GTK_DIR_TAB_BACKWARD:
1161 case GTK_DIR_TAB_FORWARD:
1168 g_assert_not_reached ();
1173 gtk_expander_focus (GtkWidget *widget,
1174 GtkDirectionType direction)
1176 GtkExpander *expander = GTK_EXPANDER (widget);
1178 if (!focus_current_site (expander, direction))
1180 GtkWidget *old_focus_child;
1181 gboolean widget_is_focus;
1182 FocusSite site = FOCUS_NONE;
1184 widget_is_focus = gtk_widget_is_focus (widget);
1185 old_focus_child = gtk_container_get_focus_child (GTK_CONTAINER (widget));
1187 if (old_focus_child && old_focus_child == expander->priv->label_widget)
1189 else if (old_focus_child)
1191 else if (widget_is_focus)
1192 site = FOCUS_WIDGET;
1194 while ((site = get_next_site (expander, site, direction)) != FOCUS_NONE)
1196 if (focus_in_site (expander, site, direction))
1207 gtk_expander_add (GtkContainer *container,
1210 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->add (container, widget);
1212 gtk_widget_set_child_visible (widget, GTK_EXPANDER (container)->priv->expanded);
1213 gtk_widget_queue_resize (GTK_WIDGET (container));
1217 gtk_expander_remove (GtkContainer *container,
1220 GtkExpander *expander = GTK_EXPANDER (container);
1222 if (GTK_EXPANDER (expander)->priv->label_widget == widget)
1223 gtk_expander_set_label_widget (expander, NULL);
1225 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->remove (container, widget);
1229 gtk_expander_forall (GtkContainer *container,
1230 gboolean include_internals,
1231 GtkCallback callback,
1232 gpointer callback_data)
1234 GtkBin *bin = GTK_BIN (container);
1235 GtkExpanderPrivate *priv = GTK_EXPANDER (container)->priv;
1238 child = gtk_bin_get_child (bin);
1240 (* callback) (child, callback_data);
1242 if (priv->label_widget)
1243 (* callback) (priv->label_widget, callback_data);
1247 gtk_expander_activate (GtkExpander *expander)
1249 gtk_expander_set_expanded (expander, !expander->priv->expanded);
1254 gtk_expander_size_request_init (GtkSizeRequestIface *iface)
1256 iface->get_width = gtk_expander_get_width;
1257 iface->get_height = gtk_expander_get_height;
1258 iface->get_height_for_width = gtk_expander_get_height_for_width;
1259 iface->get_width_for_height = gtk_expander_get_width_for_height;
1263 gtk_expander_get_width (GtkSizeRequest *widget,
1267 GtkExpander *expander;
1269 GtkExpanderPrivate *priv;
1272 gint expander_spacing;
1273 gboolean interior_focus;
1277 child = gtk_bin_get_child (GTK_BIN (widget));
1278 expander = GTK_EXPANDER (widget);
1279 priv = expander->priv;
1281 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1283 gtk_widget_style_get (GTK_WIDGET (widget),
1284 "interior-focus", &interior_focus,
1285 "focus-line-width", &focus_width,
1286 "focus-padding", &focus_pad,
1287 "expander-size", &expander_size,
1288 "expander-spacing", &expander_spacing,
1291 *minimum_size = *natural_size =
1292 expander_size + 2 * expander_spacing +
1293 2 * focus_width + 2 * focus_pad;
1295 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1297 gint label_min, label_nat;
1299 gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget),
1300 &label_min, &label_nat);
1302 *minimum_size += label_min;
1303 *natural_size += label_nat;
1306 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1308 gint child_min, child_nat;
1310 gtk_size_request_get_width (GTK_SIZE_REQUEST (child),
1311 &child_min, &child_nat);
1313 *minimum_size = MAX (*minimum_size, child_min);
1314 *natural_size = MAX (*natural_size, child_nat);
1318 *minimum_size += 2 * border_width;
1319 *natural_size += 2 * border_width;
1323 gtk_expander_get_height (GtkSizeRequest *widget,
1327 GtkExpander *expander;
1329 GtkExpanderPrivate *priv;
1332 gint expander_spacing;
1333 gboolean interior_focus;
1337 child = gtk_bin_get_child (GTK_BIN (widget));
1338 expander = GTK_EXPANDER (widget);
1339 priv = expander->priv;
1341 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1343 gtk_widget_style_get (GTK_WIDGET (widget),
1344 "interior-focus", &interior_focus,
1345 "focus-line-width", &focus_width,
1346 "focus-padding", &focus_pad,
1347 "expander-size", &expander_size,
1348 "expander-spacing", &expander_spacing,
1351 *minimum_size = *natural_size =
1352 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1355 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1357 gint label_min, label_nat;
1359 gtk_size_request_get_height (GTK_SIZE_REQUEST (priv->label_widget),
1360 &label_min, &label_nat);
1362 *minimum_size += label_min;
1363 *natural_size += label_nat;
1366 *minimum_size = MAX (*minimum_size, expander_size + 2 * expander_spacing);
1367 *natural_size = MAX (*natural_size, *minimum_size);
1369 if (!interior_focus)
1371 gint extra = 2 * focus_width + 2 * focus_pad;
1372 *minimum_size += extra;
1373 *natural_size += extra;
1376 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1378 gint child_min, child_nat;
1380 gtk_size_request_get_height (GTK_SIZE_REQUEST (child),
1381 &child_min, &child_nat);
1383 *minimum_size += child_min + priv->spacing;
1384 *natural_size += child_nat + priv->spacing;
1388 *minimum_size += 2 * border_width;
1389 *natural_size += 2 * border_width;
1393 gtk_expander_get_height_for_width (GtkSizeRequest *widget,
1395 gint *minimum_height,
1396 gint *natural_height)
1398 GtkExpander *expander;
1400 GtkExpanderPrivate *priv;
1403 gint expander_spacing;
1404 gboolean interior_focus;
1409 child = gtk_bin_get_child (GTK_BIN (widget));
1410 expander = GTK_EXPANDER (widget);
1411 priv = expander->priv;
1413 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1415 gtk_widget_style_get (GTK_WIDGET (widget),
1416 "interior-focus", &interior_focus,
1417 "focus-line-width", &focus_width,
1418 "focus-padding", &focus_pad,
1419 "expander-size", &expander_size,
1420 "expander-spacing", &expander_spacing,
1423 label_xpad = 2 * border_width + expander_size + 2 * expander_spacing - 2 * focus_width + 2 * focus_pad;
1425 *minimum_height = *natural_height =
1426 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1429 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1431 gint label_min, label_nat;
1433 gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
1434 MAX (width - label_xpad, 1),
1435 &label_min, &label_nat);
1437 *minimum_height += label_min;
1438 *natural_height += label_nat;
1441 *minimum_height = MAX (*minimum_height, expander_size + 2 * expander_spacing);
1442 *natural_height = MAX (*natural_height, *minimum_height);
1444 if (!interior_focus)
1446 gint extra = 2 * focus_width + 2 * focus_pad;
1447 *minimum_height += extra;
1448 *natural_height += extra;
1451 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1453 gint child_min, child_nat;
1455 gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (child),
1456 MAX (width - 2 * border_width, 1),
1457 &child_min, &child_nat);
1459 *minimum_height += child_min + priv->spacing;
1460 *natural_height += child_nat + priv->spacing;
1463 *minimum_height += 2 * border_width;
1464 *natural_height += 2 * border_width;
1468 gtk_expander_get_width_for_height (GtkSizeRequest *widget,
1470 gint *minimum_width,
1471 gint *natural_width)
1473 gtk_size_request_get_width (widget, minimum_width, natural_width);
1474 //GTK_SIZE_REQUEST_GET_IFACE (widget)->get_width (widget, minimum_width, natural_width);
1481 * @label: the text of the label
1483 * Creates a new expander using @label as the text of the label.
1485 * Return value: a new #GtkExpander widget.
1490 gtk_expander_new (const gchar *label)
1492 return g_object_new (GTK_TYPE_EXPANDER, "label", label, NULL);
1496 * gtk_expander_new_with_mnemonic:
1497 * @label: (allow-none): the text of the label with an underscore in front of the
1498 * mnemonic character
1500 * Creates a new expander using @label as the text of the label.
1501 * If characters in @label are preceded by an underscore, they are underlined.
1502 * If you need a literal underscore character in a label, use '__' (two
1503 * underscores). The first underlined character represents a keyboard
1504 * accelerator called a mnemonic.
1505 * Pressing Alt and that key activates the button.
1507 * Return value: a new #GtkExpander widget.
1512 gtk_expander_new_with_mnemonic (const gchar *label)
1514 return g_object_new (GTK_TYPE_EXPANDER,
1516 "use-underline", TRUE,
1521 gtk_expander_animation_timeout (GtkExpander *expander)
1523 GtkExpanderPrivate *priv = expander->priv;
1526 gboolean finish = FALSE;
1528 if (gtk_widget_get_realized (GTK_WIDGET (expander)))
1530 get_expander_bounds (expander, &area);
1531 gdk_window_invalidate_rect (GTK_WIDGET (expander)->window, &area, TRUE);
1536 if (priv->expander_style == GTK_EXPANDER_COLLAPSED)
1538 priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
1542 priv->expander_style = GTK_EXPANDER_EXPANDED;
1548 if (priv->expander_style == GTK_EXPANDER_EXPANDED)
1550 priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
1554 priv->expander_style = GTK_EXPANDER_COLLAPSED;
1561 priv->animation_timeout = 0;
1563 child = gtk_bin_get_child (GTK_BIN (expander));
1565 gtk_widget_set_child_visible (child, priv->expanded);
1566 gtk_widget_queue_resize (GTK_WIDGET (expander));
1573 gtk_expander_start_animation (GtkExpander *expander)
1575 GtkExpanderPrivate *priv = expander->priv;
1577 if (priv->animation_timeout)
1578 g_source_remove (priv->animation_timeout);
1580 priv->animation_timeout =
1581 gdk_threads_add_timeout (50,
1582 (GSourceFunc) gtk_expander_animation_timeout,
1587 * gtk_expander_set_expanded:
1588 * @expander: a #GtkExpander
1589 * @expanded: whether the child widget is revealed
1591 * Sets the state of the expander. Set to %TRUE, if you want
1592 * the child widget to be revealed, and %FALSE if you want the
1593 * child widget to be hidden.
1598 gtk_expander_set_expanded (GtkExpander *expander,
1601 GtkExpanderPrivate *priv;
1604 g_return_if_fail (GTK_IS_EXPANDER (expander));
1606 priv = expander->priv;
1608 expanded = expanded != FALSE;
1610 if (priv->expanded != expanded)
1612 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (expander));
1613 gboolean enable_animations;
1615 priv->expanded = expanded;
1617 g_object_get (settings, "gtk-enable-animations", &enable_animations, NULL);
1619 if (enable_animations && gtk_widget_get_realized (GTK_WIDGET (expander)))
1621 gtk_expander_start_animation (expander);
1625 priv->expander_style = expanded ? GTK_EXPANDER_EXPANDED :
1626 GTK_EXPANDER_COLLAPSED;
1628 child = gtk_bin_get_child (GTK_BIN (expander));
1631 gtk_widget_set_child_visible (child, priv->expanded);
1632 gtk_widget_queue_resize (GTK_WIDGET (expander));
1636 g_object_notify (G_OBJECT (expander), "expanded");
1641 * gtk_expander_get_expanded:
1642 * @expander:a #GtkExpander
1644 * Queries a #GtkExpander and returns its current state. Returns %TRUE
1645 * if the child widget is revealed.
1647 * See gtk_expander_set_expanded().
1649 * Return value: the current state of the expander.
1654 gtk_expander_get_expanded (GtkExpander *expander)
1656 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1658 return expander->priv->expanded;
1662 * gtk_expander_set_spacing:
1663 * @expander: a #GtkExpander
1664 * @spacing: distance between the expander and child in pixels.
1666 * Sets the spacing field of @expander, which is the number of pixels to
1667 * place between expander and the child.
1672 gtk_expander_set_spacing (GtkExpander *expander,
1675 g_return_if_fail (GTK_IS_EXPANDER (expander));
1676 g_return_if_fail (spacing >= 0);
1678 if (expander->priv->spacing != spacing)
1680 expander->priv->spacing = spacing;
1682 gtk_widget_queue_resize (GTK_WIDGET (expander));
1684 g_object_notify (G_OBJECT (expander), "spacing");
1689 * gtk_expander_get_spacing:
1690 * @expander: a #GtkExpander
1692 * Gets the value set by gtk_expander_set_spacing().
1694 * Return value: spacing between the expander and child.
1699 gtk_expander_get_spacing (GtkExpander *expander)
1701 g_return_val_if_fail (GTK_IS_EXPANDER (expander), 0);
1703 return expander->priv->spacing;
1707 * gtk_expander_set_label:
1708 * @expander: a #GtkExpander
1709 * @label: (allow-none): a string
1711 * Sets the text of the label of the expander to @label.
1713 * This will also clear any previously set labels.
1718 gtk_expander_set_label (GtkExpander *expander,
1721 g_return_if_fail (GTK_IS_EXPANDER (expander));
1725 gtk_expander_set_label_widget (expander, NULL);
1731 child = gtk_label_new (label);
1732 gtk_label_set_use_underline (GTK_LABEL (child), expander->priv->use_underline);
1733 gtk_label_set_use_markup (GTK_LABEL (child), expander->priv->use_markup);
1734 gtk_widget_show (child);
1736 gtk_expander_set_label_widget (expander, child);
1739 g_object_notify (G_OBJECT (expander), "label");
1743 * gtk_expander_get_label:
1744 * @expander: a #GtkExpander
1746 * Fetches the text from a label widget including any embedded
1747 * underlines indicating mnemonics and Pango markup, as set by
1748 * gtk_expander_set_label(). If the label text has not been set the
1749 * return value will be %NULL. This will be the case if you create an
1750 * empty button with gtk_button_new() to use as a container.
1752 * Note that this function behaved differently in versions prior to
1753 * 2.14 and used to return the label text stripped of embedded
1754 * underlines indicating mnemonics and Pango markup. This problem can
1755 * be avoided by fetching the label text directly from the label
1758 * Return value: The text of the label widget. This string is owned
1759 * by the widget and must not be modified or freed.
1763 G_CONST_RETURN char *
1764 gtk_expander_get_label (GtkExpander *expander)
1766 GtkExpanderPrivate *priv;
1768 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1770 priv = expander->priv;
1772 if (GTK_IS_LABEL (priv->label_widget))
1773 return gtk_label_get_label (GTK_LABEL (priv->label_widget));
1779 * gtk_expander_set_use_underline:
1780 * @expander: a #GtkExpander
1781 * @use_underline: %TRUE if underlines in the text indicate mnemonics
1783 * If true, an underline in the text of the expander label indicates
1784 * the next character should be used for the mnemonic accelerator key.
1789 gtk_expander_set_use_underline (GtkExpander *expander,
1790 gboolean use_underline)
1792 GtkExpanderPrivate *priv;
1794 g_return_if_fail (GTK_IS_EXPANDER (expander));
1796 priv = expander->priv;
1798 use_underline = use_underline != FALSE;
1800 if (priv->use_underline != use_underline)
1802 priv->use_underline = use_underline;
1804 if (GTK_IS_LABEL (priv->label_widget))
1805 gtk_label_set_use_underline (GTK_LABEL (priv->label_widget), use_underline);
1807 g_object_notify (G_OBJECT (expander), "use-underline");
1812 * gtk_expander_get_use_underline:
1813 * @expander: a #GtkExpander
1815 * Returns whether an embedded underline in the expander label indicates a
1816 * mnemonic. See gtk_expander_set_use_underline().
1818 * Return value: %TRUE if an embedded underline in the expander label
1819 * indicates the mnemonic accelerator keys.
1824 gtk_expander_get_use_underline (GtkExpander *expander)
1826 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1828 return expander->priv->use_underline;
1832 * gtk_expander_set_use_markup:
1833 * @expander: a #GtkExpander
1834 * @use_markup: %TRUE if the label's text should be parsed for markup
1836 * Sets whether the text of the label contains markup in <link
1837 * linkend="PangoMarkupFormat">Pango's text markup
1838 * language</link>. See gtk_label_set_markup().
1843 gtk_expander_set_use_markup (GtkExpander *expander,
1844 gboolean use_markup)
1846 GtkExpanderPrivate *priv;
1848 g_return_if_fail (GTK_IS_EXPANDER (expander));
1850 priv = expander->priv;
1852 use_markup = use_markup != FALSE;
1854 if (priv->use_markup != use_markup)
1856 priv->use_markup = use_markup;
1858 if (GTK_IS_LABEL (priv->label_widget))
1859 gtk_label_set_use_markup (GTK_LABEL (priv->label_widget), use_markup);
1861 g_object_notify (G_OBJECT (expander), "use-markup");
1866 * gtk_expander_get_use_markup:
1867 * @expander: a #GtkExpander
1869 * Returns whether the label's text is interpreted as marked up with
1870 * the <link linkend="PangoMarkupFormat">Pango text markup
1871 * language</link>. See gtk_expander_set_use_markup ().
1873 * Return value: %TRUE if the label's text will be parsed for markup
1878 gtk_expander_get_use_markup (GtkExpander *expander)
1880 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1882 return expander->priv->use_markup;
1886 * gtk_expander_set_label_widget:
1887 * @expander: a #GtkExpander
1888 * @label_widget: (allow-none): the new label widget
1890 * Set the label widget for the expander. This is the widget
1891 * that will appear embedded alongside the expander arrow.
1896 gtk_expander_set_label_widget (GtkExpander *expander,
1897 GtkWidget *label_widget)
1899 GtkExpanderPrivate *priv;
1902 g_return_if_fail (GTK_IS_EXPANDER (expander));
1903 g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
1904 g_return_if_fail (label_widget == NULL || label_widget->parent == NULL);
1906 priv = expander->priv;
1908 if (priv->label_widget == label_widget)
1911 if (priv->label_widget)
1913 gtk_widget_set_state (priv->label_widget, GTK_STATE_NORMAL);
1914 gtk_widget_unparent (priv->label_widget);
1917 priv->label_widget = label_widget;
1918 widget = GTK_WIDGET (expander);
1922 priv->label_widget = label_widget;
1924 gtk_widget_set_parent (label_widget, widget);
1927 gtk_widget_set_state (label_widget, GTK_STATE_PRELIGHT);
1930 if (gtk_widget_get_visible (widget))
1931 gtk_widget_queue_resize (widget);
1933 g_object_freeze_notify (G_OBJECT (expander));
1934 g_object_notify (G_OBJECT (expander), "label-widget");
1935 g_object_notify (G_OBJECT (expander), "label");
1936 g_object_thaw_notify (G_OBJECT (expander));
1940 * gtk_expander_get_label_widget:
1941 * @expander: a #GtkExpander
1943 * Retrieves the label widget for the frame. See
1944 * gtk_expander_set_label_widget().
1946 * Return value: the label widget, or %NULL if there is none.
1951 gtk_expander_get_label_widget (GtkExpander *expander)
1953 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1955 return expander->priv->label_widget;
1959 * gtk_expander_set_label_fill:
1960 * @expander: a #GtkExpander
1961 * @label_fill: %TRUE if the label should should fill all available horizontal
1964 * Sets whether the label widget should fill all available horizontal space
1965 * allocated to @expander.
1970 gtk_expander_set_label_fill (GtkExpander *expander,
1971 gboolean label_fill)
1973 GtkExpanderPrivate *priv;
1975 g_return_if_fail (GTK_IS_EXPANDER (expander));
1977 priv = expander->priv;
1979 label_fill = label_fill != FALSE;
1981 if (priv->label_fill != label_fill)
1983 priv->label_fill = label_fill;
1985 if (priv->label_widget != NULL)
1986 gtk_widget_queue_resize (GTK_WIDGET (expander));
1988 g_object_notify (G_OBJECT (expander), "label-fill");
1993 * gtk_expander_get_label_fill:
1994 * @expander: a #GtkExpander
1996 * Returns whether the label widget will fill all available horizontal
1997 * space allocated to @expander.
1999 * Return value: %TRUE if the label widget will fill all available horizontal
2005 gtk_expander_get_label_fill (GtkExpander *expander)
2007 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
2009 return expander->priv->label_fill;