* Mark McLoughlin <mark@skynet.ie>
*/
-#include <config.h>
-
+#include "config.h"
+#include <string.h>
#include "gtkexpander.h"
#include "gtklabel.h"
+#include "gtkbuildable.h"
#include "gtkcontainer.h"
#include "gtkmarshalers.h"
#include "gtkmain.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include <gdk/gdkkeysyms.h>
-#include "gtkalias.h"
#include "gtkdnd.h"
+#include "gtkalias.h"
#define GTK_EXPANDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_EXPANDER, GtkExpanderPrivate))
guint prelight : 1;
};
-static void gtk_expander_class_init (GtkExpanderClass *klass);
-static void gtk_expander_init (GtkExpander *expander);
-
static void gtk_expander_set_property (GObject *object,
guint prop_id,
const GValue *value,
static void get_expander_bounds (GtkExpander *expander,
GdkRectangle *rect);
-static GtkBinClass *parent_class = NULL;
+/* GtkBuildable */
+static void gtk_expander_buildable_init (GtkBuildableIface *iface);
+static void gtk_expander_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type);
-GType
-gtk_expander_get_type (void)
-{
- static GType expander_type = 0;
-
- if (!expander_type)
- {
- static const GTypeInfo expander_info =
- {
- sizeof (GtkExpanderClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) gtk_expander_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (GtkExpander),
- 0, /* n_preallocs */
- (GInstanceInitFunc) gtk_expander_init,
- };
-
- expander_type = g_type_register_static (GTK_TYPE_BIN,
- I_("GtkExpander"),
- &expander_info, 0);
- }
-
- return expander_type;
-}
+G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ gtk_expander_buildable_init))
static void
gtk_expander_class_init (GtkExpanderClass *klass)
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
- parent_class = g_type_class_peek_parent (klass);
-
gobject_class = (GObjectClass *) klass;
object_class = (GtkObjectClass *) klass;
widget_class = (GtkWidgetClass *) klass;
gtk_drag_dest_set_track_motion (GTK_WIDGET (expander), TRUE);
}
+static void
+gtk_expander_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *type)
+{
+ if (!type)
+ gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
+ else if (strcmp (type, "label") == 0)
+ gtk_expander_set_label_widget (GTK_EXPANDER (buildable), GTK_WIDGET (child));
+ else
+ GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_EXPANDER (buildable), type);
+}
+
+static void
+gtk_expander_buildable_init (GtkBuildableIface *iface)
+{
+ iface->add_child = gtk_expander_buildable_add_child;
+}
+
static void
gtk_expander_set_property (GObject *object,
guint prop_id,
priv->animation_timeout = 0;
}
- GTK_OBJECT_CLASS (parent_class)->destroy (object);
+ GTK_OBJECT_CLASS (gtk_expander_parent_class)->destroy (object);
}
static void
gint attributes_mask;
gint border_width;
GdkRectangle expander_rect;
+ gint label_height;
priv = GTK_EXPANDER (widget)->priv;
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
get_expander_bounds (GTK_EXPANDER (widget), &expander_rect);
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
+ {
+ GtkRequisition label_requisition;
+
+ gtk_widget_get_child_requisition (priv->label_widget, &label_requisition);
+ label_height = label_requisition.height;
+ }
+ else
+ label_height = 0;
+
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x + border_width;
- attributes.y = expander_rect.y;
+ attributes.y = widget->allocation.y + border_width;
attributes.width = MAX (widget->allocation.width - 2 * border_width, 1);
- attributes.height = expander_rect.width;
+ attributes.height = MAX (expander_rect.height, label_height - 2 * border_width);
attributes.wclass = GDK_INPUT_ONLY;
attributes.event_mask = gtk_widget_get_events (widget) |
GDK_BUTTON_PRESS_MASK |
gdk_window_set_user_data (priv->event_window, widget);
widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}
static void
priv->event_window = NULL;
}
- GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+ GTK_WIDGET_CLASS (gtk_expander_parent_class)->unrealize (widget);
}
static void
2 * focus_width + 2 * focus_pad;
requisition->height = interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
{
GtkRequisition label_requisition;
rect->x += widget->allocation.width - 2 * border_width -
expander_spacing - expander_size;
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
{
GtkAllocation label_allocation;
widget->allocation = *allocation;
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
{
GtkAllocation label_allocation;
GtkRequisition label_requisition;
get_expander_bounds (expander, &rect);
gdk_window_move_resize (priv->event_window,
- allocation->x + border_width, rect.y,
- MAX (allocation->width - 2 * border_width, 1), rect.width);
+ allocation->x + border_width,
+ allocation->y + border_width,
+ MAX (allocation->width - 2 * border_width, 1),
+ MAX (rect.height, label_height - 2 * border_width));
}
if (child_visible)
if (priv->label_widget)
gtk_widget_map (priv->label_widget);
- GTK_WIDGET_CLASS (parent_class)->map (widget);
+ GTK_WIDGET_CLASS (gtk_expander_parent_class)->map (widget);
if (priv->event_window)
gdk_window_show (priv->event_window);
if (priv->event_window)
gdk_window_hide (priv->event_window);
- GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+ GTK_WIDGET_CLASS (gtk_expander_parent_class)->unmap (widget);
if (priv->label_widget)
gtk_widget_unmap (priv->label_widget);
area.y = widget->allocation.y + container->border_width;
area.width = widget->allocation.width - (2 * container->border_width);
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
area.height = priv->label_widget->allocation.height;
else
area.height = 0;
{
GtkWidget *widget;
GtkExpanderPrivate *priv;
+ GdkRectangle rect;
gint x, y, width, height;
gboolean interior_focus;
gint border_width;
width = height = 0;
- if (priv->label_widget && GTK_WIDGET_VISIBLE (priv->label_widget))
+ if (priv->label_widget)
{
- GtkAllocation label_allocation = priv->label_widget->allocation;
+ if (gtk_widget_get_visible (priv->label_widget))
+ {
+ GtkAllocation label_allocation = priv->label_widget->allocation;
- width = label_allocation.width;
- height = label_allocation.height;
- }
+ width = label_allocation.width;
+ height = label_allocation.height;
+ }
- width += 2 * focus_pad + 2 * focus_width;
- height += 2 * focus_pad + 2 * focus_width;
+ width += 2 * focus_pad + 2 * focus_width;
+ height += 2 * focus_pad + 2 * focus_width;
- x = widget->allocation.x + border_width;
- y = widget->allocation.y + border_width;
+ x = widget->allocation.x + border_width;
+ y = widget->allocation.y + border_width;
- if (ltr)
- {
- if (interior_focus)
- x += expander_spacing * 2 + expander_size;
+ if (ltr)
+ {
+ if (interior_focus)
+ x += expander_spacing * 2 + expander_size;
+ }
+ else
+ {
+ x += widget->allocation.width - 2 * border_width
+ - expander_spacing * 2 - expander_size - width;
+ }
+
+ if (!interior_focus)
+ {
+ width += expander_size + 2 * expander_spacing;
+ height = MAX (height, expander_size + 2 * expander_spacing);
+ }
}
else
{
- x += widget->allocation.width - 2 * border_width
- - expander_spacing * 2 - expander_size - width;
- }
+ get_expander_bounds (expander, &rect);
- if (!interior_focus)
- {
- width += expander_size + 2 * expander_spacing;
- height = MAX (height, expander_size + 2 * expander_spacing);
+ x = rect.x - focus_pad;
+ y = rect.y - focus_pad;
+ width = rect.width + 2 * focus_pad;
+ height = rect.height + 2 * focus_pad;
}
gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
gtk_expander_expose (GtkWidget *widget,
GdkEventExpose *event)
{
- if (GTK_WIDGET_DRAWABLE (widget))
+ if (gtk_widget_is_drawable (widget))
{
GtkExpander *expander = GTK_EXPANDER (widget);
gtk_expander_paint (expander);
- if (GTK_WIDGET_HAS_FOCUS (expander))
+ if (gtk_widget_has_focus (widget))
gtk_expander_paint_focus (expander, &event->area);
- GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+ GTK_WIDGET_CLASS (gtk_expander_parent_class)->expose_event (widget, event);
}
return FALSE;
gtk_expander_state_changed (GtkWidget *widget,
GtkStateType previous_state)
{
- if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ if (!gtk_widget_is_sensitive (widget))
GTK_EXPANDER (widget)->priv->button_down = FALSE;
}
settings = gtk_widget_get_settings (widget);
g_object_get (settings, "gtk-timeout-expand", &timeout, NULL);
- priv->expand_timer = g_timeout_add (timeout, (GSourceFunc) expand_timeout, expander);
+ priv->expand_timer = gdk_threads_add_timeout (timeout, (GSourceFunc) expand_timeout, expander);
}
return TRUE;
gtk_expander_add (GtkContainer *container,
GtkWidget *widget)
{
- GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
+ GTK_CONTAINER_CLASS (gtk_expander_parent_class)->add (container, widget);
gtk_widget_set_child_visible (widget, GTK_EXPANDER (container)->priv->expanded);
gtk_widget_queue_resize (GTK_WIDGET (container));
if (GTK_EXPANDER (expander)->priv->label_widget == widget)
gtk_expander_set_label_widget (expander, NULL);
else
- GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
+ GTK_CONTAINER_CLASS (gtk_expander_parent_class)->remove (container, widget);
}
static void
/**
* gtk_expander_new_with_mnemonic:
- * @label: the text of the label with an underscore in front of the
+ * @label: (allow-none): the text of the label with an underscore in front of the
* mnemonic character
- *
+ *
* Creates a new expander using @label as the text of the label.
* If characters in @label are preceded by an underscore, they are underlined.
* If you need a literal underscore character in a label, use '__' (two
GdkRectangle area;
gboolean finish = FALSE;
- GDK_THREADS_ENTER();
-
if (GTK_WIDGET_REALIZED (expander))
{
get_expander_bounds (expander, &area);
gtk_widget_queue_resize (GTK_WIDGET (expander));
}
- GDK_THREADS_LEAVE();
-
return !finish;
}
g_source_remove (priv->animation_timeout);
priv->animation_timeout =
- g_timeout_add (50,
+ gdk_threads_add_timeout (50,
(GSourceFunc) gtk_expander_animation_timeout,
expander);
}
/**
* gtk_expander_set_label:
* @expander: a #GtkExpander
- * @label: a string
+ * @label: (allow-none): a string
*
* Sets the text of the label of the expander to @label.
*
* gtk_expander_get_label:
* @expander: a #GtkExpander
*
- * Fetches the text from the label of the expander, as set by
- * gtk_expander_set_label(). If the label text has not
- * been set the return value will be %NULL. This will be the
- * case if you create an empty button with gtk_button_new() to
- * use as a container.
+ * Fetches the text from a label widget including any embedded
+ * underlines indicating mnemonics and Pango markup, as set by
+ * gtk_expander_set_label(). If the label text has not been set the
+ * return value will be %NULL. This will be the case if you create an
+ * empty button with gtk_button_new() to use as a container.
+ *
+ * Note that this function behaved differently in versions prior to
+ * 2.14 and used to return the label text stripped of embedded
+ * underlines indicating mnemonics and Pango markup. This problem can
+ * be avoided by fetching the label text directly from the label
+ * widget.
*
* Return value: The text of the label widget. This string is owned
* by the widget and must not be modified or freed.
priv = expander->priv;
- if (priv->label_widget && GTK_IS_LABEL (priv->label_widget))
- return gtk_label_get_text (GTK_LABEL (priv->label_widget));
+ if (GTK_IS_LABEL (priv->label_widget))
+ return gtk_label_get_label (GTK_LABEL (priv->label_widget));
else
return NULL;
}
{
priv->use_underline = use_underline;
- if (priv->label_widget && GTK_IS_LABEL (priv->label_widget))
+ if (GTK_IS_LABEL (priv->label_widget))
gtk_label_set_use_underline (GTK_LABEL (priv->label_widget), use_underline);
g_object_notify (G_OBJECT (expander), "use-underline");
{
priv->use_markup = use_markup;
- if (priv->label_widget && GTK_IS_LABEL (priv->label_widget))
+ if (GTK_IS_LABEL (priv->label_widget))
gtk_label_set_use_markup (GTK_LABEL (priv->label_widget), use_markup);
g_object_notify (G_OBJECT (expander), "use-markup");
/**
* gtk_expander_set_label_widget:
* @expander: a #GtkExpander
- * @label_widget: the new label widget
+ * @label_widget: (allow-none): the new label widget
*
* Set the label widget for the expander. This is the widget
* that will appear embedded alongside the expander arrow.
GtkWidget *label_widget)
{
GtkExpanderPrivate *priv;
+ GtkWidget *widget;
g_return_if_fail (GTK_IS_EXPANDER (expander));
g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
}
priv->label_widget = label_widget;
+ widget = GTK_WIDGET (expander);
if (label_widget)
{
priv->label_widget = label_widget;
- gtk_widget_set_parent (label_widget, GTK_WIDGET (expander));
+ gtk_widget_set_parent (label_widget, widget);
if (priv->prelight)
gtk_widget_set_state (label_widget, GTK_STATE_PRELIGHT);
}
- if (GTK_WIDGET_VISIBLE (expander))
- gtk_widget_queue_resize (GTK_WIDGET (expander));
+ if (gtk_widget_get_visible (widget))
+ gtk_widget_queue_resize (widget);
g_object_freeze_notify (G_OBJECT (expander));
g_object_notify (G_OBJECT (expander), "label-widget");