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 GtkAllocation allocation;
434 GtkExpanderPrivate *priv;
436 GdkWindowAttr attributes;
437 gint attributes_mask;
439 GdkRectangle expander_rect;
442 priv = GTK_EXPANDER (widget)->priv;
444 gtk_widget_set_realized (widget, TRUE);
446 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
448 get_expander_bounds (GTK_EXPANDER (widget), &expander_rect);
450 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
452 GtkRequisition label_requisition;
454 gtk_widget_get_child_requisition (priv->label_widget, &label_requisition);
455 label_height = label_requisition.height;
460 gtk_widget_get_allocation (widget, &allocation);
462 attributes.window_type = GDK_WINDOW_CHILD;
463 attributes.x = allocation.x + border_width;
464 attributes.y = allocation.y + border_width;
465 attributes.width = MAX (allocation.width - 2 * border_width, 1);
466 attributes.height = MAX (expander_rect.height, label_height - 2 * border_width);
467 attributes.wclass = GDK_INPUT_ONLY;
468 attributes.event_mask = gtk_widget_get_events (widget) |
469 GDK_BUTTON_PRESS_MASK |
470 GDK_BUTTON_RELEASE_MASK |
471 GDK_ENTER_NOTIFY_MASK |
472 GDK_LEAVE_NOTIFY_MASK;
474 attributes_mask = GDK_WA_X | GDK_WA_Y;
476 window = gtk_widget_get_parent_window (widget);
477 gtk_widget_set_window (widget, window);
478 g_object_ref (window);
480 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
481 &attributes, attributes_mask);
482 gdk_window_set_user_data (priv->event_window, widget);
484 gtk_widget_style_attach (widget);
488 gtk_expander_unrealize (GtkWidget *widget)
490 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
492 if (priv->event_window)
494 gdk_window_set_user_data (priv->event_window, NULL);
495 gdk_window_destroy (priv->event_window);
496 priv->event_window = NULL;
499 GTK_WIDGET_CLASS (gtk_expander_parent_class)->unrealize (widget);
503 get_expander_bounds (GtkExpander *expander,
506 GtkAllocation allocation;
508 GtkExpanderPrivate *priv;
511 gint expander_spacing;
512 gboolean interior_focus;
517 widget = GTK_WIDGET (expander);
518 priv = expander->priv;
520 gtk_widget_get_allocation (widget, &allocation);
522 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
524 gtk_widget_style_get (widget,
525 "interior-focus", &interior_focus,
526 "focus-line-width", &focus_width,
527 "focus-padding", &focus_pad,
528 "expander-size", &expander_size,
529 "expander-spacing", &expander_spacing,
532 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
534 rect->x = allocation.x + border_width;
535 rect->y = allocation.y + border_width;
538 rect->x += expander_spacing;
540 rect->x += allocation.width - 2 * border_width -
541 expander_spacing - expander_size;
543 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
545 GtkAllocation label_allocation;
547 gtk_widget_get_allocation (priv->label_widget, &label_allocation);
549 if (expander_size < label_allocation.height)
550 rect->y += focus_width + focus_pad + (label_allocation.height - expander_size) / 2;
552 rect->y += expander_spacing;
556 rect->y += expander_spacing;
562 rect->x += focus_width + focus_pad;
564 rect->x -= focus_width + focus_pad;
565 rect->y += focus_width + focus_pad;
568 rect->width = rect->height = expander_size;
572 gtk_expander_size_allocate (GtkWidget *widget,
573 GtkAllocation *allocation)
575 GtkExpander *expander;
577 GtkExpanderPrivate *priv;
578 gboolean child_visible = FALSE;
581 gint expander_spacing;
582 gboolean interior_focus;
585 gint label_height, top_min_height;
586 gint label_xpad, label_xoffset;
587 gint child_ypad, child_yoffset;
589 expander = GTK_EXPANDER (widget);
590 child = gtk_bin_get_child (GTK_BIN (widget));
591 priv = expander->priv;
593 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
595 gtk_widget_set_allocation (widget, allocation);
597 gtk_widget_style_get (widget,
598 "interior-focus", &interior_focus,
599 "focus-line-width", &focus_width,
600 "focus-padding", &focus_pad,
601 "expander-size", &expander_size,
602 "expander-spacing", &expander_spacing,
606 /* Calculate some offsets/padding first */
607 label_xoffset = border_width + expander_size + focus_width + 2 * expander_spacing + focus_pad;
608 label_xpad = 2 * border_width + expander_size + 2 * focus_width + 2 * expander_spacing + 2 * focus_pad;
610 child_yoffset = border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
611 child_ypad = 2 * border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
612 top_min_height = 2 * expander_spacing + expander_size;
614 child_visible = (child && GTK_WIDGET_CHILD_VISIBLE (child));
616 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
618 GtkAllocation label_allocation;
619 gint natural_label_width;
622 gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget), NULL, &natural_label_width);
624 if (priv->label_fill)
625 label_allocation.width = allocation->width - label_xpad;
627 label_allocation.width = MIN (natural_label_width, allocation->width - label_xpad);
628 label_allocation.width = MAX (label_allocation.width, 1);
630 /* We distribute the minimum height to the label widget and prioritize
631 * the child widget giving it the remaining height */
632 gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
633 label_allocation.width, &label_height, NULL);
635 ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
637 if (priv->label_fill)
638 label_allocation.x = allocation->x + label_xoffset;
640 label_allocation.x = allocation->x + label_xoffset;
642 label_allocation.x = allocation->x + allocation->width -
643 (label_allocation.width + label_xoffset);
645 label_allocation.y = allocation->y + border_width + focus_width + focus_pad;
646 label_allocation.height = MIN (label_height,
647 allocation->height - 2 * border_width -
648 2 * focus_width - 2 * focus_pad -
649 (child_visible ? priv->spacing : 0));
650 label_allocation.height = MAX (label_allocation.height, 1);
652 gtk_widget_size_allocate (priv->label_widget, &label_allocation);
654 label_height = label_allocation.height;
661 if (gtk_widget_get_realized (widget))
665 get_expander_bounds (expander, &rect);
667 gdk_window_move_resize (priv->event_window,
668 allocation->x + border_width,
669 allocation->y + border_width,
670 MAX (allocation->width - 2 * border_width, 1),
671 MAX (rect.height, label_height - 2 * border_width));
676 GtkAllocation child_allocation;
679 top_height = MAX (top_min_height,
680 label_height + (interior_focus ? 2 * focus_width + 2 * focus_pad : 0));
682 child_allocation.x = allocation->x + border_width;
683 child_allocation.y = allocation->y + top_height + child_yoffset;
685 child_allocation.width = MAX (allocation->width - 2 * border_width, 1);
686 child_allocation.height = allocation->height - top_height - child_ypad;
687 child_allocation.height = MAX (child_allocation.height, 1);
689 gtk_widget_size_allocate (child, &child_allocation);
694 gtk_expander_map (GtkWidget *widget)
696 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
698 if (priv->label_widget)
699 gtk_widget_map (priv->label_widget);
701 GTK_WIDGET_CLASS (gtk_expander_parent_class)->map (widget);
703 if (priv->event_window)
704 gdk_window_show (priv->event_window);
708 gtk_expander_unmap (GtkWidget *widget)
710 GtkExpanderPrivate *priv = GTK_EXPANDER (widget)->priv;
712 if (priv->event_window)
713 gdk_window_hide (priv->event_window);
715 GTK_WIDGET_CLASS (gtk_expander_parent_class)->unmap (widget);
717 if (priv->label_widget)
718 gtk_widget_unmap (priv->label_widget);
722 gtk_expander_paint_prelight (GtkExpander *expander)
724 GtkAllocation allocation;
726 GtkContainer *container;
727 GtkExpanderPrivate *priv;
729 gboolean interior_focus;
733 int expander_spacing;
736 priv = expander->priv;
737 widget = GTK_WIDGET (expander);
738 container = GTK_CONTAINER (expander);
740 gtk_widget_style_get (widget,
741 "interior-focus", &interior_focus,
742 "focus-line-width", &focus_width,
743 "focus-padding", &focus_pad,
744 "expander-size", &expander_size,
745 "expander-spacing", &expander_spacing,
748 gtk_widget_get_allocation (widget, &allocation);
750 border_width = gtk_container_get_border_width (container);
751 area.x = allocation.x + border_width;
752 area.y = allocation.y + border_width;
753 area.width = allocation.width - (2 * border_width);
755 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
757 GtkAllocation label_widget_allocation;
759 gtk_widget_get_allocation (priv->label_widget, &label_widget_allocation);
760 area.height = label_widget_allocation.height;
765 area.height += interior_focus ? (focus_width + focus_pad) * 2 : 0;
766 area.height = MAX (area.height, expander_size + 2 * expander_spacing);
767 area.height += !interior_focus ? (focus_width + focus_pad) * 2 : 0;
769 gtk_paint_flat_box (gtk_widget_get_style (widget),
770 gtk_widget_get_window (widget),
772 GTK_SHADOW_ETCHED_OUT,
773 &area, widget, "expander",
775 area.width, area.height);
779 gtk_expander_paint (GtkExpander *expander)
785 widget = GTK_WIDGET (expander);
787 get_expander_bounds (expander, &clip);
789 state = gtk_widget_get_state (widget);
790 if (expander->priv->prelight)
792 state = GTK_STATE_PRELIGHT;
794 gtk_expander_paint_prelight (expander);
797 gtk_paint_expander (gtk_widget_get_style (widget),
798 gtk_widget_get_window (widget),
803 clip.x + clip.width / 2,
804 clip.y + clip.height / 2,
805 expander->priv->expander_style);
809 gtk_expander_paint_focus (GtkExpander *expander,
813 GtkExpanderPrivate *priv;
815 gint x, y, width, height;
816 gboolean interior_focus;
821 gint expander_spacing;
824 widget = GTK_WIDGET (expander);
825 priv = expander->priv;
827 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
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 GtkAllocation allocation;
845 gtk_widget_get_allocation (widget, &allocation);
847 if (gtk_widget_get_visible (priv->label_widget))
849 GtkAllocation label_allocation;
851 gtk_widget_get_allocation (priv->label_widget, &label_allocation);
852 width = label_allocation.width;
853 height = label_allocation.height;
856 width += 2 * focus_pad + 2 * focus_width;
857 height += 2 * focus_pad + 2 * focus_width;
859 x = allocation.x + border_width;
860 y = allocation.y + border_width;
865 x += expander_spacing * 2 + expander_size;
869 x += allocation.width - 2 * border_width
870 - expander_spacing * 2 - expander_size - width;
875 width += expander_size + 2 * expander_spacing;
876 height = MAX (height, expander_size + 2 * expander_spacing);
881 get_expander_bounds (expander, &rect);
883 x = rect.x - focus_pad;
884 y = rect.y - focus_pad;
885 width = rect.width + 2 * focus_pad;
886 height = rect.height + 2 * focus_pad;
889 gtk_paint_focus (gtk_widget_get_style (widget),
890 gtk_widget_get_window (widget),
891 gtk_widget_get_state (widget),
892 area, widget, "expander",
893 x, y, width, height);
897 gtk_expander_expose (GtkWidget *widget,
898 GdkEventExpose *event)
900 if (gtk_widget_is_drawable (widget))
902 GtkExpander *expander = GTK_EXPANDER (widget);
904 gtk_expander_paint (expander);
906 if (gtk_widget_has_focus (widget))
907 gtk_expander_paint_focus (expander, &event->area);
909 GTK_WIDGET_CLASS (gtk_expander_parent_class)->expose_event (widget, event);
916 gtk_expander_button_press (GtkWidget *widget,
917 GdkEventButton *event)
919 GtkExpander *expander = GTK_EXPANDER (widget);
921 if (event->button == 1 && event->window == expander->priv->event_window)
923 expander->priv->button_down = TRUE;
931 gtk_expander_button_release (GtkWidget *widget,
932 GdkEventButton *event)
934 GtkExpander *expander = GTK_EXPANDER (widget);
936 if (event->button == 1 && expander->priv->button_down)
938 gtk_widget_activate (widget);
939 expander->priv->button_down = FALSE;
947 gtk_expander_grab_notify (GtkWidget *widget,
948 gboolean was_grabbed)
951 GTK_EXPANDER (widget)->priv->button_down = FALSE;
955 gtk_expander_state_changed (GtkWidget *widget,
956 GtkStateType previous_state)
958 if (!gtk_widget_is_sensitive (widget))
959 GTK_EXPANDER (widget)->priv->button_down = FALSE;
963 gtk_expander_redraw_expander (GtkExpander *expander)
965 GtkAllocation allocation;
966 GtkWidget *widget = GTK_WIDGET (expander);
968 if (gtk_widget_get_realized (widget))
970 gtk_widget_get_allocation (widget, &allocation);
971 gdk_window_invalidate_rect (gtk_widget_get_window (widget), &allocation, FALSE);
976 gtk_expander_enter_notify (GtkWidget *widget,
977 GdkEventCrossing *event)
979 GtkExpander *expander = GTK_EXPANDER (widget);
980 GtkWidget *event_widget;
982 event_widget = gtk_get_event_widget ((GdkEvent *) event);
984 if (event_widget == widget &&
985 event->detail != GDK_NOTIFY_INFERIOR)
987 expander->priv->prelight = TRUE;
989 if (expander->priv->label_widget)
990 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_PRELIGHT);
992 gtk_expander_redraw_expander (expander);
999 gtk_expander_leave_notify (GtkWidget *widget,
1000 GdkEventCrossing *event)
1002 GtkExpander *expander = GTK_EXPANDER (widget);
1003 GtkWidget *event_widget;
1005 event_widget = gtk_get_event_widget ((GdkEvent *) event);
1007 if (event_widget == widget &&
1008 event->detail != GDK_NOTIFY_INFERIOR)
1010 expander->priv->prelight = FALSE;
1012 if (expander->priv->label_widget)
1013 gtk_widget_set_state (expander->priv->label_widget, GTK_STATE_NORMAL);
1015 gtk_expander_redraw_expander (expander);
1022 expand_timeout (gpointer data)
1024 GtkExpander *expander = GTK_EXPANDER (data);
1025 GtkExpanderPrivate *priv = expander->priv;
1027 priv->expand_timer = 0;
1028 gtk_expander_set_expanded (expander, TRUE);
1034 gtk_expander_drag_motion (GtkWidget *widget,
1035 GdkDragContext *context,
1040 GtkExpander *expander = GTK_EXPANDER (widget);
1041 GtkExpanderPrivate *priv = expander->priv;
1043 if (!priv->expanded && !priv->expand_timer)
1045 GtkSettings *settings;
1048 settings = gtk_widget_get_settings (widget);
1049 g_object_get (settings, "gtk-timeout-expand", &timeout, NULL);
1051 priv->expand_timer = gdk_threads_add_timeout (timeout, (GSourceFunc) expand_timeout, expander);
1058 gtk_expander_drag_leave (GtkWidget *widget,
1059 GdkDragContext *context,
1062 GtkExpander *expander = GTK_EXPANDER (widget);
1063 GtkExpanderPrivate *priv = expander->priv;
1065 if (priv->expand_timer)
1067 g_source_remove (priv->expand_timer);
1068 priv->expand_timer = 0;
1081 focus_current_site (GtkExpander *expander,
1082 GtkDirectionType direction)
1084 GtkWidget *current_focus;
1086 current_focus = gtk_container_get_focus_child (GTK_CONTAINER (expander));
1091 return gtk_widget_child_focus (current_focus, direction);
1095 focus_in_site (GtkExpander *expander,
1097 GtkDirectionType direction)
1102 gtk_widget_grab_focus (GTK_WIDGET (expander));
1105 if (expander->priv->label_widget)
1106 return gtk_widget_child_focus (expander->priv->label_widget, direction);
1111 GtkWidget *child = gtk_bin_get_child (GTK_BIN (expander));
1113 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1114 return gtk_widget_child_focus (child, direction);
1122 g_assert_not_reached ();
1127 get_next_site (GtkExpander *expander,
1129 GtkDirectionType direction)
1133 ltr = gtk_widget_get_direction (GTK_WIDGET (expander)) != GTK_TEXT_DIR_RTL;
1140 case GTK_DIR_TAB_BACKWARD:
1144 case GTK_DIR_TAB_FORWARD:
1147 return FOCUS_WIDGET;
1152 case GTK_DIR_TAB_BACKWARD:
1156 return ltr ? FOCUS_NONE : FOCUS_LABEL;
1157 case GTK_DIR_TAB_FORWARD:
1161 return ltr ? FOCUS_LABEL : FOCUS_NONE;
1167 case GTK_DIR_TAB_BACKWARD:
1169 return FOCUS_WIDGET;
1171 return ltr ? FOCUS_WIDGET : FOCUS_CHILD;
1172 case GTK_DIR_TAB_FORWARD:
1176 return ltr ? FOCUS_CHILD : FOCUS_WIDGET;
1182 case GTK_DIR_TAB_BACKWARD:
1186 case GTK_DIR_TAB_FORWARD:
1193 g_assert_not_reached ();
1198 gtk_expander_focus (GtkWidget *widget,
1199 GtkDirectionType direction)
1201 GtkExpander *expander = GTK_EXPANDER (widget);
1203 if (!focus_current_site (expander, direction))
1205 GtkWidget *old_focus_child;
1206 gboolean widget_is_focus;
1207 FocusSite site = FOCUS_NONE;
1209 widget_is_focus = gtk_widget_is_focus (widget);
1210 old_focus_child = gtk_container_get_focus_child (GTK_CONTAINER (widget));
1212 if (old_focus_child && old_focus_child == expander->priv->label_widget)
1214 else if (old_focus_child)
1216 else if (widget_is_focus)
1217 site = FOCUS_WIDGET;
1219 while ((site = get_next_site (expander, site, direction)) != FOCUS_NONE)
1221 if (focus_in_site (expander, site, direction))
1232 gtk_expander_add (GtkContainer *container,
1235 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->add (container, widget);
1237 gtk_widget_set_child_visible (widget, GTK_EXPANDER (container)->priv->expanded);
1238 gtk_widget_queue_resize (GTK_WIDGET (container));
1242 gtk_expander_remove (GtkContainer *container,
1245 GtkExpander *expander = GTK_EXPANDER (container);
1247 if (GTK_EXPANDER (expander)->priv->label_widget == widget)
1248 gtk_expander_set_label_widget (expander, NULL);
1250 GTK_CONTAINER_CLASS (gtk_expander_parent_class)->remove (container, widget);
1254 gtk_expander_forall (GtkContainer *container,
1255 gboolean include_internals,
1256 GtkCallback callback,
1257 gpointer callback_data)
1259 GtkBin *bin = GTK_BIN (container);
1260 GtkExpanderPrivate *priv = GTK_EXPANDER (container)->priv;
1263 child = gtk_bin_get_child (bin);
1265 (* callback) (child, callback_data);
1267 if (priv->label_widget)
1268 (* callback) (priv->label_widget, callback_data);
1272 gtk_expander_activate (GtkExpander *expander)
1274 gtk_expander_set_expanded (expander, !expander->priv->expanded);
1279 gtk_expander_size_request_init (GtkSizeRequestIface *iface)
1281 iface->get_width = gtk_expander_get_width;
1282 iface->get_height = gtk_expander_get_height;
1283 iface->get_height_for_width = gtk_expander_get_height_for_width;
1284 iface->get_width_for_height = gtk_expander_get_width_for_height;
1288 gtk_expander_get_width (GtkSizeRequest *widget,
1292 GtkExpander *expander;
1294 GtkExpanderPrivate *priv;
1297 gint expander_spacing;
1298 gboolean interior_focus;
1302 child = gtk_bin_get_child (GTK_BIN (widget));
1303 expander = GTK_EXPANDER (widget);
1304 priv = expander->priv;
1306 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1308 gtk_widget_style_get (GTK_WIDGET (widget),
1309 "interior-focus", &interior_focus,
1310 "focus-line-width", &focus_width,
1311 "focus-padding", &focus_pad,
1312 "expander-size", &expander_size,
1313 "expander-spacing", &expander_spacing,
1316 *minimum_size = *natural_size =
1317 expander_size + 2 * expander_spacing +
1318 2 * focus_width + 2 * focus_pad;
1320 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1322 gint label_min, label_nat;
1324 gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget),
1325 &label_min, &label_nat);
1327 *minimum_size += label_min;
1328 *natural_size += label_nat;
1331 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1333 gint child_min, child_nat;
1335 gtk_size_request_get_width (GTK_SIZE_REQUEST (child),
1336 &child_min, &child_nat);
1338 *minimum_size = MAX (*minimum_size, child_min);
1339 *natural_size = MAX (*natural_size, child_nat);
1343 *minimum_size += 2 * border_width;
1344 *natural_size += 2 * border_width;
1348 gtk_expander_get_height (GtkSizeRequest *widget,
1352 GtkExpander *expander;
1354 GtkExpanderPrivate *priv;
1357 gint expander_spacing;
1358 gboolean interior_focus;
1362 child = gtk_bin_get_child (GTK_BIN (widget));
1363 expander = GTK_EXPANDER (widget);
1364 priv = expander->priv;
1366 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1368 gtk_widget_style_get (GTK_WIDGET (widget),
1369 "interior-focus", &interior_focus,
1370 "focus-line-width", &focus_width,
1371 "focus-padding", &focus_pad,
1372 "expander-size", &expander_size,
1373 "expander-spacing", &expander_spacing,
1376 *minimum_size = *natural_size =
1377 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1380 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1382 gint label_min, label_nat;
1384 gtk_size_request_get_height (GTK_SIZE_REQUEST (priv->label_widget),
1385 &label_min, &label_nat);
1387 *minimum_size += label_min;
1388 *natural_size += label_nat;
1391 *minimum_size = MAX (*minimum_size, expander_size + 2 * expander_spacing);
1392 *natural_size = MAX (*natural_size, *minimum_size);
1394 if (!interior_focus)
1396 gint extra = 2 * focus_width + 2 * focus_pad;
1397 *minimum_size += extra;
1398 *natural_size += extra;
1401 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1403 gint child_min, child_nat;
1405 gtk_size_request_get_height (GTK_SIZE_REQUEST (child),
1406 &child_min, &child_nat);
1408 *minimum_size += child_min + priv->spacing;
1409 *natural_size += child_nat + priv->spacing;
1413 *minimum_size += 2 * border_width;
1414 *natural_size += 2 * border_width;
1418 gtk_expander_get_height_for_width (GtkSizeRequest *widget,
1420 gint *minimum_height,
1421 gint *natural_height)
1423 GtkExpander *expander;
1425 GtkExpanderPrivate *priv;
1428 gint expander_spacing;
1429 gboolean interior_focus;
1434 child = gtk_bin_get_child (GTK_BIN (widget));
1435 expander = GTK_EXPANDER (widget);
1436 priv = expander->priv;
1438 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1440 gtk_widget_style_get (GTK_WIDGET (widget),
1441 "interior-focus", &interior_focus,
1442 "focus-line-width", &focus_width,
1443 "focus-padding", &focus_pad,
1444 "expander-size", &expander_size,
1445 "expander-spacing", &expander_spacing,
1448 label_xpad = 2 * border_width + expander_size + 2 * expander_spacing - 2 * focus_width + 2 * focus_pad;
1450 *minimum_height = *natural_height =
1451 interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
1454 if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
1456 gint label_min, label_nat;
1458 gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
1459 MAX (width - label_xpad, 1),
1460 &label_min, &label_nat);
1462 *minimum_height += label_min;
1463 *natural_height += label_nat;
1466 *minimum_height = MAX (*minimum_height, expander_size + 2 * expander_spacing);
1467 *natural_height = MAX (*natural_height, *minimum_height);
1469 if (!interior_focus)
1471 gint extra = 2 * focus_width + 2 * focus_pad;
1472 *minimum_height += extra;
1473 *natural_height += extra;
1476 if (child && GTK_WIDGET_CHILD_VISIBLE (child))
1478 gint child_min, child_nat;
1480 gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (child),
1481 MAX (width - 2 * border_width, 1),
1482 &child_min, &child_nat);
1484 *minimum_height += child_min + priv->spacing;
1485 *natural_height += child_nat + priv->spacing;
1488 *minimum_height += 2 * border_width;
1489 *natural_height += 2 * border_width;
1493 gtk_expander_get_width_for_height (GtkSizeRequest *widget,
1495 gint *minimum_width,
1496 gint *natural_width)
1498 GTK_SIZE_REQUEST_GET_IFACE (widget)->get_width (widget, minimum_width, natural_width);
1505 * @label: the text of the label
1507 * Creates a new expander using @label as the text of the label.
1509 * Return value: a new #GtkExpander widget.
1514 gtk_expander_new (const gchar *label)
1516 return g_object_new (GTK_TYPE_EXPANDER, "label", label, NULL);
1520 * gtk_expander_new_with_mnemonic:
1521 * @label: (allow-none): the text of the label with an underscore in front of the
1522 * mnemonic character
1524 * Creates a new expander using @label as the text of the label.
1525 * If characters in @label are preceded by an underscore, they are underlined.
1526 * If you need a literal underscore character in a label, use '__' (two
1527 * underscores). The first underlined character represents a keyboard
1528 * accelerator called a mnemonic.
1529 * Pressing Alt and that key activates the button.
1531 * Return value: a new #GtkExpander widget.
1536 gtk_expander_new_with_mnemonic (const gchar *label)
1538 return g_object_new (GTK_TYPE_EXPANDER,
1540 "use-underline", TRUE,
1545 gtk_expander_animation_timeout (GtkExpander *expander)
1547 GtkExpanderPrivate *priv = expander->priv;
1548 GtkWidget *widget = GTK_WIDGET (expander);
1551 gboolean finish = FALSE;
1553 if (gtk_widget_get_realized (widget))
1555 get_expander_bounds (expander, &area);
1556 gdk_window_invalidate_rect (gtk_widget_get_window (widget), &area, TRUE);
1561 if (priv->expander_style == GTK_EXPANDER_COLLAPSED)
1563 priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
1567 priv->expander_style = GTK_EXPANDER_EXPANDED;
1573 if (priv->expander_style == GTK_EXPANDER_EXPANDED)
1575 priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
1579 priv->expander_style = GTK_EXPANDER_COLLAPSED;
1586 priv->animation_timeout = 0;
1588 child = gtk_bin_get_child (GTK_BIN (expander));
1590 gtk_widget_set_child_visible (child, priv->expanded);
1591 gtk_widget_queue_resize (widget);
1598 gtk_expander_start_animation (GtkExpander *expander)
1600 GtkExpanderPrivate *priv = expander->priv;
1602 if (priv->animation_timeout)
1603 g_source_remove (priv->animation_timeout);
1605 priv->animation_timeout =
1606 gdk_threads_add_timeout (50,
1607 (GSourceFunc) gtk_expander_animation_timeout,
1612 * gtk_expander_set_expanded:
1613 * @expander: a #GtkExpander
1614 * @expanded: whether the child widget is revealed
1616 * Sets the state of the expander. Set to %TRUE, if you want
1617 * the child widget to be revealed, and %FALSE if you want the
1618 * child widget to be hidden.
1623 gtk_expander_set_expanded (GtkExpander *expander,
1626 GtkExpanderPrivate *priv;
1629 g_return_if_fail (GTK_IS_EXPANDER (expander));
1631 priv = expander->priv;
1633 expanded = expanded != FALSE;
1635 if (priv->expanded != expanded)
1637 GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (expander));
1638 gboolean enable_animations;
1640 priv->expanded = expanded;
1642 g_object_get (settings, "gtk-enable-animations", &enable_animations, NULL);
1644 if (enable_animations && gtk_widget_get_realized (GTK_WIDGET (expander)))
1646 gtk_expander_start_animation (expander);
1650 priv->expander_style = expanded ? GTK_EXPANDER_EXPANDED :
1651 GTK_EXPANDER_COLLAPSED;
1653 child = gtk_bin_get_child (GTK_BIN (expander));
1656 gtk_widget_set_child_visible (child, priv->expanded);
1657 gtk_widget_queue_resize (GTK_WIDGET (expander));
1661 g_object_notify (G_OBJECT (expander), "expanded");
1666 * gtk_expander_get_expanded:
1667 * @expander:a #GtkExpander
1669 * Queries a #GtkExpander and returns its current state. Returns %TRUE
1670 * if the child widget is revealed.
1672 * See gtk_expander_set_expanded().
1674 * Return value: the current state of the expander.
1679 gtk_expander_get_expanded (GtkExpander *expander)
1681 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1683 return expander->priv->expanded;
1687 * gtk_expander_set_spacing:
1688 * @expander: a #GtkExpander
1689 * @spacing: distance between the expander and child in pixels.
1691 * Sets the spacing field of @expander, which is the number of pixels to
1692 * place between expander and the child.
1697 gtk_expander_set_spacing (GtkExpander *expander,
1700 g_return_if_fail (GTK_IS_EXPANDER (expander));
1701 g_return_if_fail (spacing >= 0);
1703 if (expander->priv->spacing != spacing)
1705 expander->priv->spacing = spacing;
1707 gtk_widget_queue_resize (GTK_WIDGET (expander));
1709 g_object_notify (G_OBJECT (expander), "spacing");
1714 * gtk_expander_get_spacing:
1715 * @expander: a #GtkExpander
1717 * Gets the value set by gtk_expander_set_spacing().
1719 * Return value: spacing between the expander and child.
1724 gtk_expander_get_spacing (GtkExpander *expander)
1726 g_return_val_if_fail (GTK_IS_EXPANDER (expander), 0);
1728 return expander->priv->spacing;
1732 * gtk_expander_set_label:
1733 * @expander: a #GtkExpander
1734 * @label: (allow-none): a string
1736 * Sets the text of the label of the expander to @label.
1738 * This will also clear any previously set labels.
1743 gtk_expander_set_label (GtkExpander *expander,
1746 g_return_if_fail (GTK_IS_EXPANDER (expander));
1750 gtk_expander_set_label_widget (expander, NULL);
1756 child = gtk_label_new (label);
1757 gtk_label_set_use_underline (GTK_LABEL (child), expander->priv->use_underline);
1758 gtk_label_set_use_markup (GTK_LABEL (child), expander->priv->use_markup);
1759 gtk_widget_show (child);
1761 gtk_expander_set_label_widget (expander, child);
1764 g_object_notify (G_OBJECT (expander), "label");
1768 * gtk_expander_get_label:
1769 * @expander: a #GtkExpander
1771 * Fetches the text from a label widget including any embedded
1772 * underlines indicating mnemonics and Pango markup, as set by
1773 * gtk_expander_set_label(). If the label text has not been set the
1774 * return value will be %NULL. This will be the case if you create an
1775 * empty button with gtk_button_new() to use as a container.
1777 * Note that this function behaved differently in versions prior to
1778 * 2.14 and used to return the label text stripped of embedded
1779 * underlines indicating mnemonics and Pango markup. This problem can
1780 * be avoided by fetching the label text directly from the label
1783 * Return value: The text of the label widget. This string is owned
1784 * by the widget and must not be modified or freed.
1788 G_CONST_RETURN char *
1789 gtk_expander_get_label (GtkExpander *expander)
1791 GtkExpanderPrivate *priv;
1793 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1795 priv = expander->priv;
1797 if (GTK_IS_LABEL (priv->label_widget))
1798 return gtk_label_get_label (GTK_LABEL (priv->label_widget));
1804 * gtk_expander_set_use_underline:
1805 * @expander: a #GtkExpander
1806 * @use_underline: %TRUE if underlines in the text indicate mnemonics
1808 * If true, an underline in the text of the expander label indicates
1809 * the next character should be used for the mnemonic accelerator key.
1814 gtk_expander_set_use_underline (GtkExpander *expander,
1815 gboolean use_underline)
1817 GtkExpanderPrivate *priv;
1819 g_return_if_fail (GTK_IS_EXPANDER (expander));
1821 priv = expander->priv;
1823 use_underline = use_underline != FALSE;
1825 if (priv->use_underline != use_underline)
1827 priv->use_underline = use_underline;
1829 if (GTK_IS_LABEL (priv->label_widget))
1830 gtk_label_set_use_underline (GTK_LABEL (priv->label_widget), use_underline);
1832 g_object_notify (G_OBJECT (expander), "use-underline");
1837 * gtk_expander_get_use_underline:
1838 * @expander: a #GtkExpander
1840 * Returns whether an embedded underline in the expander label indicates a
1841 * mnemonic. See gtk_expander_set_use_underline().
1843 * Return value: %TRUE if an embedded underline in the expander label
1844 * indicates the mnemonic accelerator keys.
1849 gtk_expander_get_use_underline (GtkExpander *expander)
1851 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1853 return expander->priv->use_underline;
1857 * gtk_expander_set_use_markup:
1858 * @expander: a #GtkExpander
1859 * @use_markup: %TRUE if the label's text should be parsed for markup
1861 * Sets whether the text of the label contains markup in <link
1862 * linkend="PangoMarkupFormat">Pango's text markup
1863 * language</link>. See gtk_label_set_markup().
1868 gtk_expander_set_use_markup (GtkExpander *expander,
1869 gboolean use_markup)
1871 GtkExpanderPrivate *priv;
1873 g_return_if_fail (GTK_IS_EXPANDER (expander));
1875 priv = expander->priv;
1877 use_markup = use_markup != FALSE;
1879 if (priv->use_markup != use_markup)
1881 priv->use_markup = use_markup;
1883 if (GTK_IS_LABEL (priv->label_widget))
1884 gtk_label_set_use_markup (GTK_LABEL (priv->label_widget), use_markup);
1886 g_object_notify (G_OBJECT (expander), "use-markup");
1891 * gtk_expander_get_use_markup:
1892 * @expander: a #GtkExpander
1894 * Returns whether the label's text is interpreted as marked up with
1895 * the <link linkend="PangoMarkupFormat">Pango text markup
1896 * language</link>. See gtk_expander_set_use_markup ().
1898 * Return value: %TRUE if the label's text will be parsed for markup
1903 gtk_expander_get_use_markup (GtkExpander *expander)
1905 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
1907 return expander->priv->use_markup;
1911 * gtk_expander_set_label_widget:
1912 * @expander: a #GtkExpander
1913 * @label_widget: (allow-none): the new label widget
1915 * Set the label widget for the expander. This is the widget
1916 * that will appear embedded alongside the expander arrow.
1921 gtk_expander_set_label_widget (GtkExpander *expander,
1922 GtkWidget *label_widget)
1924 GtkExpanderPrivate *priv;
1927 g_return_if_fail (GTK_IS_EXPANDER (expander));
1928 g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
1929 g_return_if_fail (label_widget == NULL || gtk_widget_get_parent (label_widget) == NULL);
1931 priv = expander->priv;
1933 if (priv->label_widget == label_widget)
1936 if (priv->label_widget)
1938 gtk_widget_set_state (priv->label_widget, GTK_STATE_NORMAL);
1939 gtk_widget_unparent (priv->label_widget);
1942 priv->label_widget = label_widget;
1943 widget = GTK_WIDGET (expander);
1947 priv->label_widget = label_widget;
1949 gtk_widget_set_parent (label_widget, widget);
1952 gtk_widget_set_state (label_widget, GTK_STATE_PRELIGHT);
1955 if (gtk_widget_get_visible (widget))
1956 gtk_widget_queue_resize (widget);
1958 g_object_freeze_notify (G_OBJECT (expander));
1959 g_object_notify (G_OBJECT (expander), "label-widget");
1960 g_object_notify (G_OBJECT (expander), "label");
1961 g_object_thaw_notify (G_OBJECT (expander));
1965 * gtk_expander_get_label_widget:
1966 * @expander: a #GtkExpander
1968 * Retrieves the label widget for the frame. See
1969 * gtk_expander_set_label_widget().
1971 * Return value: the label widget, or %NULL if there is none.
1976 gtk_expander_get_label_widget (GtkExpander *expander)
1978 g_return_val_if_fail (GTK_IS_EXPANDER (expander), NULL);
1980 return expander->priv->label_widget;
1984 * gtk_expander_set_label_fill:
1985 * @expander: a #GtkExpander
1986 * @label_fill: %TRUE if the label should should fill all available horizontal
1989 * Sets whether the label widget should fill all available horizontal space
1990 * allocated to @expander.
1995 gtk_expander_set_label_fill (GtkExpander *expander,
1996 gboolean label_fill)
1998 GtkExpanderPrivate *priv;
2000 g_return_if_fail (GTK_IS_EXPANDER (expander));
2002 priv = expander->priv;
2004 label_fill = label_fill != FALSE;
2006 if (priv->label_fill != label_fill)
2008 priv->label_fill = label_fill;
2010 if (priv->label_widget != NULL)
2011 gtk_widget_queue_resize (GTK_WIDGET (expander));
2013 g_object_notify (G_OBJECT (expander), "label-fill");
2018 * gtk_expander_get_label_fill:
2019 * @expander: a #GtkExpander
2021 * Returns whether the label widget will fill all available horizontal
2022 * space allocated to @expander.
2024 * Return value: %TRUE if the label widget will fill all available horizontal
2030 gtk_expander_get_label_fill (GtkExpander *expander)
2032 g_return_val_if_fail (GTK_IS_EXPANDER (expander), FALSE);
2034 return expander->priv->label_fill;