X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcontainer.c;h=6563af965fdd509920b0d7541e8e959a6af725e3;hb=becb5057fc26e721e49d16b2cd1edc4834d65ce3;hp=84a814e08c63dc2599eced028b994c6ef8053550;hpb=74db59e9d19883e053464b9aaeaa15efa28738a5;p=~andy%2Fgtk diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index 84a814e08..6563af965 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -24,19 +24,23 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +#include "config.h" #include #include #include #include "gtkcontainer.h" +#include "gtkbuildable.h" +#include "gtkbuilderprivate.h" #include "gtkprivate.h" -#include "gtksignal.h" #include "gtkmain.h" #include "gtkmarshalers.h" #include "gtkwindow.h" #include "gtkintl.h" +#include "gtktoolbar.h" #include #include +#include "gtkalias.h" enum { @@ -51,7 +55,7 @@ enum { PROP_0, PROP_BORDER_WIDTH, PROP_RESIZE_MODE, - PROP_CHILD, + PROP_CHILD }; #define PARAM_SPEC_PARAM_ID(pspec) ((pspec)->param_id) @@ -81,9 +85,6 @@ static gboolean gtk_container_focus (GtkWidget *widget, GtkDirectionType direction); static void gtk_container_real_set_focus_child (GtkContainer *container, GtkWidget *widget); -static GList * gtk_container_focus_sort (GtkContainer *container, - GList *children, - GtkDirectionType direction); static gboolean gtk_container_focus_move (GtkContainer *container, GList *children, @@ -100,33 +101,53 @@ static void gtk_container_unmap (GtkWidget *widget); static gchar* gtk_container_child_default_composite_name (GtkContainer *container, GtkWidget *child); +/* GtkBuildable */ +static void gtk_container_buildable_init (GtkBuildableIface *iface); +static void gtk_container_buildable_add_child (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *type); +static gboolean gtk_container_buildable_custom_tag_start (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + GMarkupParser *parser, + gpointer *data); +static void gtk_container_buildable_custom_tag_end (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer *data); + /* --- variables --- */ -static const gchar *vadjustment_key = "gtk-vadjustment"; +static const gchar vadjustment_key[] = "gtk-vadjustment"; static guint vadjustment_key_id = 0; -static const gchar *hadjustment_key = "gtk-hadjustment"; +static const gchar hadjustment_key[] = "gtk-hadjustment"; static guint hadjustment_key_id = 0; static GSList *container_resize_queue = NULL; static guint container_signals[LAST_SIGNAL] = { 0 }; static GtkWidgetClass *parent_class = NULL; extern GParamSpecPool *_gtk_widget_child_property_pool; extern GObjectNotifyContext *_gtk_widget_child_property_notify_context; +static GtkBuildableIface *parent_buildable_iface; /* --- functions --- */ -GtkType +GType gtk_container_get_type (void) { - static GtkType container_type = 0; + static GType container_type = 0; if (!container_type) { - static GTypeInfo container_info = { + const GTypeInfo container_info = + { sizeof (GtkContainerClass), (GBaseInitFunc) gtk_container_base_class_init, (GBaseFinalizeFunc) gtk_container_base_class_finalize, (GClassInitFunc) gtk_container_class_init, - NULL /* class_destroy */, + NULL /* class_finalize */, NULL /* class_data */, sizeof (GtkContainer), 0 /* n_preallocs */, @@ -134,7 +155,21 @@ gtk_container_get_type (void) NULL, /* value_table */ }; - container_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkContainer", &container_info, 0); + static const GInterfaceInfo buildable_info = + { + (GInterfaceInitFunc) gtk_container_buildable_init, + NULL, + NULL + }; + + container_type = + g_type_register_static (GTK_TYPE_WIDGET, I_("GtkContainer"), + &container_info, G_TYPE_FLAG_ABSTRACT); + + g_type_add_interface_static (container_type, + GTK_TYPE_BUILDABLE, + &buildable_info); + } return container_type; @@ -199,77 +234,289 @@ gtk_container_class_init (GtkContainerClass *class) g_object_class_install_property (gobject_class, PROP_RESIZE_MODE, - g_param_spec_enum ("resize_mode", - _("Resize mode"), - _("Specify how resize events are handled"), + g_param_spec_enum ("resize-mode", + P_("Resize mode"), + P_("Specify how resize events are handled"), GTK_TYPE_RESIZE_MODE, GTK_RESIZE_PARENT, - G_PARAM_READWRITE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_BORDER_WIDTH, - g_param_spec_uint ("border_width", - _("Border width"), - _("The width of the empty border outside the containers children."), + g_param_spec_uint ("border-width", + P_("Border width"), + P_("The width of the empty border outside the containers children"), 0, G_MAXINT, 0, - G_PARAM_READWRITE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_CHILD, g_param_spec_object ("child", - _("Child"), - _("Can be used to add a new child to the container."), + P_("Child"), + P_("Can be used to add a new child to the container"), GTK_TYPE_WIDGET, - G_PARAM_WRITABLE)); + GTK_PARAM_WRITABLE)); container_signals[ADD] = - gtk_signal_new ("add", - GTK_RUN_FIRST, - GTK_CLASS_TYPE (object_class), - GTK_SIGNAL_OFFSET (GtkContainerClass, add), - _gtk_marshal_VOID__OBJECT, - GTK_TYPE_NONE, 1, - GTK_TYPE_WIDGET); + g_signal_new (I_("add"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkContainerClass, add), + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_WIDGET); container_signals[REMOVE] = - gtk_signal_new ("remove", - GTK_RUN_FIRST, - GTK_CLASS_TYPE (object_class), - GTK_SIGNAL_OFFSET (GtkContainerClass, remove), - _gtk_marshal_VOID__OBJECT, - GTK_TYPE_NONE, 1, - GTK_TYPE_WIDGET); + g_signal_new (I_("remove"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkContainerClass, remove), + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_WIDGET); container_signals[CHECK_RESIZE] = - gtk_signal_new ("check_resize", - GTK_RUN_LAST, - GTK_CLASS_TYPE (object_class), - GTK_SIGNAL_OFFSET (GtkContainerClass, check_resize), - _gtk_marshal_VOID__VOID, - GTK_TYPE_NONE, 0); + g_signal_new (I_("check-resize"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkContainerClass, check_resize), + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); container_signals[SET_FOCUS_CHILD] = - gtk_signal_new ("set-focus-child", - GTK_RUN_FIRST, - GTK_CLASS_TYPE (object_class), - GTK_SIGNAL_OFFSET (GtkContainerClass, set_focus_child), - _gtk_marshal_VOID__OBJECT, - GTK_TYPE_NONE, 1, - GTK_TYPE_WIDGET); + g_signal_new (I_("set-focus-child"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkContainerClass, set_focus_child), + NULL, NULL, + _gtk_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_WIDGET); +} + +static void +gtk_container_buildable_init (GtkBuildableIface *iface) +{ + parent_buildable_iface = g_type_interface_peek_parent (iface); + iface->add_child = gtk_container_buildable_add_child; + iface->custom_tag_start = gtk_container_buildable_custom_tag_start; + iface->custom_tag_end = gtk_container_buildable_custom_tag_end; +} + +static void +gtk_container_buildable_add_child (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *type) +{ + if (type) + { + GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type); + } + else if (GTK_IS_WIDGET (child) && GTK_WIDGET (child)->parent == NULL) + { + gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child)); + } + else + g_warning ("Cannot add an object of type %s to a container of type %s", + g_type_name (G_OBJECT_TYPE (child)), g_type_name (G_OBJECT_TYPE (buildable))); +} + +static void +gtk_container_buildable_set_child_property (GtkContainer *container, + GtkBuilder *builder, + GtkWidget *child, + gchar *name, + const gchar *value) +{ + GParamSpec *pspec; + GValue gvalue = { 0, }; + GError *error = NULL; + + pspec = gtk_container_class_find_child_property + (G_OBJECT_GET_CLASS (container), name); + if (!pspec) + { + g_warning ("%s does not have a property called %s", + g_type_name (G_OBJECT_TYPE (container)), name); + return; + } + + if (!gtk_builder_value_from_string (builder, pspec, value, &gvalue, &error)) + { + g_warning ("Could not read property %s:%s with value %s of type %s: %s", + g_type_name (G_OBJECT_TYPE (container)), + name, + value, + g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)), + error->message); + g_error_free (error); + return; + } + + gtk_container_child_set_property (container, child, name, &gvalue); + g_value_unset (&gvalue); +} + +typedef struct { + GtkBuilder *builder; + GtkContainer *container; + GtkWidget *child; + gchar *child_prop_name; + gchar *context; + gboolean translatable; +} PackingPropertiesData; + +static void +attributes_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **names, + const gchar **values, + gpointer user_data, + GError **error) +{ + PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data; + guint i; + + if (strcmp (element_name, "property") == 0) + { + for (i = 0; names[i]; i++) + if (strcmp (names[i], "name") == 0) + parser_data->child_prop_name = g_strdup (values[i]); + else if (strcmp (names[i], "translatable") == 0) + { + if (!_gtk_builder_boolean_from_string (values[1], + &parser_data->translatable, + error)) + return; + } + else if (strcmp (names[i], "comments") == 0) + ; /* for translators */ + else if (strcmp (names[i], "context") == 0) + parser_data->context = g_strdup (values[1]); + else + g_warning ("Unsupported attribute for GtkContainer Child " + "property: %s\n", names[i]); + } + else if (strcmp (element_name, "packing") == 0) + return; + else + g_warning ("Unsupported tag for GtkContainer: %s\n", element_name); +} + +static void +attributes_text_element (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + PackingPropertiesData *parser_data = (PackingPropertiesData*)user_data; + gchar* value; + + if (!parser_data->child_prop_name) + return; + + if (parser_data->translatable && text_len) + { + const gchar* domain; + domain = gtk_builder_get_translation_domain (parser_data->builder); + + value = _gtk_builder_parser_translate (domain, + parser_data->context, + text); + } + else + { + value = g_strdup (text); + } + + gtk_container_buildable_set_child_property (parser_data->container, + parser_data->builder, + parser_data->child, + parser_data->child_prop_name, + value); + + g_free (parser_data->child_prop_name); + g_free (parser_data->context); + g_free (value); + parser_data->child_prop_name = NULL; + parser_data->context = NULL; + parser_data->translatable = FALSE; +} + +static const GMarkupParser attributes_parser = + { + attributes_start_element, + NULL, + attributes_text_element, + }; + +static gboolean +gtk_container_buildable_custom_tag_start (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + GMarkupParser *parser, + gpointer *data) +{ + PackingPropertiesData *parser_data; + + if (parent_buildable_iface->custom_tag_start (buildable, builder, child, + tagname, parser, data)) + return TRUE; + + if (child && strcmp (tagname, "packing") == 0) + { + parser_data = g_slice_new0 (PackingPropertiesData); + parser_data->builder = builder; + parser_data->container = GTK_CONTAINER (buildable); + parser_data->child = GTK_WIDGET (child); + parser_data->child_prop_name = NULL; + + *parser = attributes_parser; + *data = parser_data; + return TRUE; + } + + return FALSE; +} + +static void +gtk_container_buildable_custom_tag_end (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer *data) +{ + if (strcmp (tagname, "packing") == 0) + { + g_slice_free (PackingPropertiesData, (gpointer)data); + return; + + } + + if (parent_buildable_iface->custom_tag_end) + parent_buildable_iface->custom_tag_end (buildable, builder, + child, tagname, data); + } /** * gtk_container_child_type: - * @container: a #GtkContainer. + * @container: a #GtkContainer * * Returns the type of the children supported by the container. * - * Note that this may return %GTK_TYPE_NONE to indicate that no more + * Note that this may return %G_TYPE_NONE to indicate that no more * children can be added, e.g. for a #GtkPaned which already has two * children. * - * Return value: a #GtkType. + * Return value: a #GType. **/ -GtkType +GType gtk_container_child_type (GtkContainer *container) { - GtkType slot; + GType slot; GtkContainerClass *class; g_return_val_if_fail (GTK_IS_CONTAINER (container), 0); @@ -278,7 +525,7 @@ gtk_container_child_type (GtkContainer *container) if (class->child_type) slot = class->child_type (container); else - slot = GTK_TYPE_NONE; + slot = G_TYPE_NONE; return slot; } @@ -331,6 +578,16 @@ container_set_child_property (GtkContainer *container, g_value_unset (&tmp_value); } +/** + * gtk_container_child_get_valist: + * @container: a #GtkContainer + * @child: a widget which is a child of @container + * @first_property_name: the name of the first property to get + * @var_args: return location for the first property, followed + * optionally by more name/return location pairs, followed by %NULL + * + * Gets the values of one or more child properties for @child and @container. + **/ void gtk_container_child_get_valist (GtkContainer *container, GtkWidget *child, @@ -391,6 +648,15 @@ gtk_container_child_get_valist (GtkContainer *container, g_object_unref (container); } +/** + * gtk_container_child_get_property: + * @container: a #GtkContainer + * @child: a widget which is a child of @container + * @property_name: the name of the property to get + * @value: a location to return the value + * + * Gets the value of a child property for @child and @container. + **/ void gtk_container_child_get_property (GtkContainer *container, GtkWidget *child, @@ -456,13 +722,22 @@ gtk_container_child_get_property (GtkContainer *container, g_object_unref (container); } +/** + * gtk_container_child_set_valist: + * @container: a #GtkContainer + * @child: a widget which is a child of @container + * @first_property_name: the name of the first property to set + * @var_args: a %NULL-terminated list of property names and values, starting + * with @first_prop_name + * + * Sets one or more child properties for @child and @container. + **/ void gtk_container_child_set_valist (GtkContainer *container, GtkWidget *child, const gchar *first_property_name, va_list var_args) { - GObject *object; GObjectNotifyQueue *nqueue; const gchar *name; @@ -473,7 +748,6 @@ gtk_container_child_set_valist (GtkContainer *container, g_object_ref (container); g_object_ref (child); - object = G_OBJECT (container); nqueue = g_object_notify_queue_freeze (G_OBJECT (child), _gtk_widget_child_property_notify_context); name = first_property_name; while (name) @@ -522,13 +796,21 @@ gtk_container_child_set_valist (GtkContainer *container, g_object_unref (child); } +/** + * gtk_container_child_set_property: + * @container: a #GtkContainer + * @child: a widget which is a child of @container + * @property_name: the name of the property to set + * @value: the value to set the property to + * + * Sets a child property for @child and @container. + **/ void gtk_container_child_set_property (GtkContainer *container, GtkWidget *child, const gchar *property_name, const GValue *value) { - GObject *object; GObjectNotifyQueue *nqueue; GParamSpec *pspec; @@ -541,7 +823,6 @@ gtk_container_child_set_property (GtkContainer *container, g_object_ref (container); g_object_ref (child); - object = G_OBJECT (container); nqueue = g_object_notify_queue_freeze (G_OBJECT (child), _gtk_widget_child_property_notify_context); pspec = g_param_spec_pool_lookup (_gtk_widget_child_property_pool, property_name, G_OBJECT_TYPE (container), TRUE); @@ -564,6 +845,17 @@ gtk_container_child_set_property (GtkContainer *container, g_object_unref (child); } +/** + * gtk_container_add_with_properties: + * @container: a #GtkContainer + * @widget: a widget to be placed inside @container + * @first_prop_name: the name of the first child property to set + * @Varargs: a %NULL-terminated list of property names and values, starting + * with @first_prop_name + * + * Adds @widget to @container, setting child properties at the same time. + * See gtk_container_add() and gtk_container_child_set() for more details. + **/ void gtk_container_add_with_properties (GtkContainer *container, GtkWidget *widget, @@ -574,11 +866,11 @@ gtk_container_add_with_properties (GtkContainer *container, g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (widget->parent == NULL); - gtk_widget_ref (GTK_WIDGET (container)); - gtk_widget_ref (widget); + g_object_ref (container); + g_object_ref (widget); gtk_widget_freeze_child_notify (widget); - gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget); + g_signal_emit (container, container_signals[ADD], 0, widget); if (widget->parent) { va_list var_args; @@ -589,10 +881,20 @@ gtk_container_add_with_properties (GtkContainer *container, } gtk_widget_thaw_child_notify (widget); - gtk_widget_unref (widget); - gtk_widget_unref (GTK_WIDGET (container)); + g_object_unref (widget); + g_object_unref (container); } +/** + * gtk_container_child_set: + * @container: a #GtkContainer + * @child: a widget which is a child of @container + * @first_prop_name: the name of the first property to set + * @Varargs: a %NULL-terminated list of property names and values, starting + * with @first_prop_name + * + * Sets one or more child properties for @child and @container. + **/ void gtk_container_child_set (GtkContainer *container, GtkWidget *child, @@ -610,6 +912,16 @@ gtk_container_child_set (GtkContainer *container, va_end (var_args); } +/** + * gtk_container_child_get: + * @container: a #GtkContainer + * @child: a widget which is a child of @container + * @first_prop_name: the name of the first property to get + * @Varargs: return location for the first property, followed + * optionally by more name/return location pairs, followed by %NULL + * + * Gets the values of one or more child properties for @child and @container. + **/ void gtk_container_child_get (GtkContainer *container, GtkWidget *child, @@ -618,9 +930,7 @@ gtk_container_child_get (GtkContainer *container, { va_list var_args; - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); - g_return_if_fail (child != NULL); g_return_if_fail (GTK_IS_WIDGET (child)); g_return_if_fail (child->parent == GTK_WIDGET (container)); @@ -629,59 +939,85 @@ gtk_container_child_get (GtkContainer *container, va_end (var_args); } +/** + * gtk_container_class_install_child_property: + * @cclass: a #GtkContainerClass + * @property_id: the id for the property + * @pspec: the #GParamSpec for the property + * + * Installs a child property on a container class. + **/ void -gtk_container_class_install_child_property (GtkContainerClass *class, +gtk_container_class_install_child_property (GtkContainerClass *cclass, guint property_id, GParamSpec *pspec) { - g_return_if_fail (GTK_IS_CONTAINER_CLASS (class)); + g_return_if_fail (GTK_IS_CONTAINER_CLASS (cclass)); g_return_if_fail (G_IS_PARAM_SPEC (pspec)); if (pspec->flags & G_PARAM_WRITABLE) - g_return_if_fail (class->set_child_property != NULL); + g_return_if_fail (cclass->set_child_property != NULL); if (pspec->flags & G_PARAM_READABLE) - g_return_if_fail (class->get_child_property != NULL); + g_return_if_fail (cclass->get_child_property != NULL); g_return_if_fail (property_id > 0); g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */ if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) g_return_if_fail ((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0); - if (g_param_spec_pool_lookup (_gtk_widget_child_property_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE)) + if (g_param_spec_pool_lookup (_gtk_widget_child_property_pool, pspec->name, G_OBJECT_CLASS_TYPE (cclass), FALSE)) { - g_warning (G_STRLOC ": class `%s' already contains a property named `%s'", - G_OBJECT_CLASS_NAME (class), + g_warning (G_STRLOC ": class `%s' already contains a child property named `%s'", + G_OBJECT_CLASS_NAME (cclass), pspec->name); return; } g_param_spec_ref (pspec); g_param_spec_sink (pspec); PARAM_SPEC_SET_PARAM_ID (pspec, property_id); - g_param_spec_pool_insert (_gtk_widget_child_property_pool, pspec, G_OBJECT_CLASS_TYPE (class)); + g_param_spec_pool_insert (_gtk_widget_child_property_pool, pspec, G_OBJECT_CLASS_TYPE (cclass)); } +/** + * gtk_container_class_find_child_property: + * @cclass: a #GtkContainerClass + * @property_name: the name of the child property to find + * @returns: the #GParamSpec of the child property or %NULL if @class has no + * child property with that name. + * + * Finds a child property of a container class by name. + */ GParamSpec* -gtk_container_class_find_child_property (GObjectClass *class, +gtk_container_class_find_child_property (GObjectClass *cclass, const gchar *property_name) { - g_return_val_if_fail (GTK_IS_CONTAINER_CLASS (class), NULL); + g_return_val_if_fail (GTK_IS_CONTAINER_CLASS (cclass), NULL); g_return_val_if_fail (property_name != NULL, NULL); return g_param_spec_pool_lookup (_gtk_widget_child_property_pool, property_name, - G_OBJECT_CLASS_TYPE (class), + G_OBJECT_CLASS_TYPE (cclass), TRUE); } -GParamSpec** /* free result */ -gtk_container_class_list_child_properties (GObjectClass *class, +/** + * gtk_container_class_list_child_properties: + * @cclass: a #GtkContainerClass + * @n_properties: location to return the number of child properties found + * @returns: a newly allocated %NULL-terminated array of #GParamSpec*. + * The array must be freed with g_free(). + * + * Returns all child properties of a container class. + */ +GParamSpec** +gtk_container_class_list_child_properties (GObjectClass *cclass, guint *n_properties) { GParamSpec **pspecs; guint n; - g_return_val_if_fail (GTK_IS_CONTAINER_CLASS (class), NULL); + g_return_val_if_fail (GTK_IS_CONTAINER_CLASS (cclass), NULL); pspecs = g_param_spec_pool_list (_gtk_widget_child_property_pool, - G_OBJECT_CLASS_TYPE (class), + G_OBJECT_CLASS_TYPE (cclass), &n); if (n_properties) *n_properties = n; @@ -693,14 +1029,14 @@ static void gtk_container_add_unimplemented (GtkContainer *container, GtkWidget *widget) { - g_warning ("GtkContainerClass::add not implemented for `%s'", gtk_type_name (GTK_OBJECT_TYPE (container))); + g_warning ("GtkContainerClass::add not implemented for `%s'", g_type_name (G_TYPE_FROM_INSTANCE (container))); } static void gtk_container_remove_unimplemented (GtkContainer *container, GtkWidget *widget) { - g_warning ("GtkContainerClass::remove not implemented for `%s'", gtk_type_name (GTK_OBJECT_TYPE (container))); + g_warning ("GtkContainerClass::remove not implemented for `%s'", g_type_name (G_TYPE_FROM_INSTANCE (container))); } static void @@ -716,13 +1052,8 @@ gtk_container_init (GtkContainer *container) static void gtk_container_destroy (GtkObject *object) { - GtkContainer *container; - - g_return_if_fail (object != NULL); - g_return_if_fail (GTK_IS_CONTAINER (object)); + GtkContainer *container = GTK_CONTAINER (object); - container = GTK_CONTAINER (object); - if (GTK_CONTAINER_RESIZE_PENDING (container)) _gtk_container_dequeue_resize_handler (container); @@ -731,11 +1062,10 @@ gtk_container_destroy (GtkObject *object) */ if (container->has_focus_chain) gtk_container_unset_focus_chain (container); - + gtk_container_foreach (container, (GtkCallback) gtk_widget_destroy, NULL); - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); + + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void @@ -744,9 +1074,7 @@ gtk_container_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - GtkContainer *container; - - container = GTK_CONTAINER (object); + GtkContainer *container = GTK_CONTAINER (object); switch (prop_id) { @@ -771,9 +1099,7 @@ gtk_container_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - GtkContainer *container; - - container = GTK_CONTAINER (object); + GtkContainer *container = GTK_CONTAINER (object); switch (prop_id) { @@ -792,8 +1118,8 @@ gtk_container_get_property (GObject *object, /** * gtk_container_set_border_width: * @container: a #GtkContainer - * @border_width: amount of blank space to leave outside the container. - * Valid values are in the range 0-65535 pixels. + * @border_width: amount of blank space to leave outside + * the container. Valid values are in the range 0-65535 pixels. * * Sets the border width of the container. * @@ -802,20 +1128,20 @@ gtk_container_get_property (GObject *object, * #GtkWindow; because toplevel windows can't leave space outside, * they leave the space inside. The border is added on all sides of * the container. To add space to only one side, one approach is to - * create a #GtkAlignment widget, call gtk_widget_set_usize() to give - * it a size, and place it on the side of the container as a spacer. + * create a #GtkAlignment widget, call gtk_widget_set_size_request() + * to give it a size, and place it on the side of the container as + * a spacer. **/ void gtk_container_set_border_width (GtkContainer *container, guint border_width) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); if (container->border_width != border_width) { container->border_width = border_width; - g_object_notify (G_OBJECT (container), "border_width"); + g_object_notify (G_OBJECT (container), "border-width"); if (GTK_WIDGET_REALIZED (container)) gtk_widget_queue_resize (GTK_WIDGET (container)); @@ -857,23 +1183,22 @@ void gtk_container_add (GtkContainer *container, GtkWidget *widget) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); if (widget->parent != NULL) { g_warning ("Attempting to add a widget with type %s to a container of " "type %s, but the widget is already inside a container of type %s, " - "the GTK+ FAQ at http://www.gtk.org/faq/ explains how to reparent a widget.", + "the GTK+ FAQ at http://library.gnome.org/devel/gtk-faq/stable/ " + "explains how to reparent a widget.", g_type_name (G_OBJECT_TYPE (widget)), g_type_name (G_OBJECT_TYPE (container)), g_type_name (G_OBJECT_TYPE (widget->parent))); return; } - gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget); + g_signal_emit (container, container_signals[ADD], 0, widget); } /** @@ -886,19 +1211,26 @@ gtk_container_add (GtkContainer *container, * may be the last reference held; so removing a widget from its * container can destroy that widget. If you want to use @widget * again, you need to add a reference to it while it's not inside - * a container, using g_object_ref(). + * a container, using g_object_ref(). If you don't want to use @widget + * again it's usually more efficient to simply destroy it directly + * using gtk_widget_destroy() since this will remove it from the + * container and help break any circular reference count cycles. **/ void gtk_container_remove (GtkContainer *container, GtkWidget *widget) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (widget->parent == GTK_WIDGET (container)); + + /* When using the deprecated API of the toolbar, it is possible + * to legitimately call this function with a widget that is not + * a direct child of the container. + */ + g_return_if_fail (GTK_IS_TOOLBAR (container) || + widget->parent == GTK_WIDGET (container)); - gtk_signal_emit (GTK_OBJECT (container), container_signals[REMOVE], widget); + g_signal_emit (container, container_signals[REMOVE], 0, widget); } void @@ -913,8 +1245,8 @@ _gtk_container_dequeue_resize_handler (GtkContainer *container) /** * gtk_container_set_resize_mode: - * @container: a #GtkContainer. - * @resize_mode: the new resize mode. + * @container: a #GtkContainer + * @resize_mode: the new resize mode * * Sets the resize mode for the container. * @@ -926,7 +1258,6 @@ void gtk_container_set_resize_mode (GtkContainer *container, GtkResizeMode resize_mode) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (resize_mode <= GTK_RESIZE_IMMEDIATE); @@ -934,7 +1265,6 @@ gtk_container_set_resize_mode (GtkContainer *container, resize_mode == GTK_RESIZE_PARENT) { resize_mode = GTK_RESIZE_QUEUE; - g_object_notify (G_OBJECT (container), "resize_mode"); } if (container->resize_mode != resize_mode) @@ -942,7 +1272,7 @@ gtk_container_set_resize_mode (GtkContainer *container, container->resize_mode = resize_mode; gtk_widget_queue_resize (GTK_WIDGET (container)); - g_object_notify (G_OBJECT (container), "resize_mode"); + g_object_notify (G_OBJECT (container), "resize-mode"); } } @@ -965,8 +1295,8 @@ gtk_container_get_resize_mode (GtkContainer *container) /** * gtk_container_set_reallocate_redraws: - * @container: a #GtkContainer. - * @needs_redraws: the new value for the container's @reallocate_redraws flag. + * @container: a #GtkContainer + * @needs_redraws: the new value for the container's @reallocate_redraws flag * * Sets the @reallocate_redraws flag of the container to the given value. * @@ -985,9 +1315,7 @@ gtk_container_set_reallocate_redraws (GtkContainer *container, static GtkContainer* gtk_container_get_resize_container (GtkContainer *container) { - GtkWidget *widget; - - widget = GTK_WIDGET (container); + GtkWidget *widget = GTK_WIDGET (container); while (widget->parent) { @@ -1002,8 +1330,6 @@ gtk_container_get_resize_container (GtkContainer *container) static gboolean gtk_container_idle_sizer (gpointer data) { - GDK_THREADS_ENTER (); - /* we may be invoked with a container_resize_queue of NULL, because * queue_resize could have been adding an extra idle function while * the queue still got processed. we better just ignore such case @@ -1026,8 +1352,6 @@ gtk_container_idle_sizer (gpointer data) gdk_window_process_all_updates (); - GDK_THREADS_LEAVE (); - return FALSE; } @@ -1035,28 +1359,28 @@ void _gtk_container_queue_resize (GtkContainer *container) { GtkContainer *resize_container; + GtkWidget *widget; - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); + widget = GTK_WIDGET (container); resize_container = gtk_container_get_resize_container (container); - if (resize_container) + while (TRUE) { - GtkWidget *widget = GTK_WIDGET (container); + GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED); + GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED); + if ((resize_container && widget == GTK_WIDGET (resize_container)) || + !widget->parent) + break; - while (!GTK_WIDGET_ALLOC_NEEDED (widget) || !GTK_WIDGET_REQUEST_NEEDED (widget)) - { - GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED); - GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED); - if (widget == GTK_WIDGET (resize_container)) - break; - - widget = widget->parent; - } + widget = widget->parent; + } + if (resize_container) + { if (GTK_WIDGET_VISIBLE (resize_container) && - (GTK_WIDGET_TOPLEVEL (resize_container) || GTK_WIDGET_DRAWABLE (resize_container))) + (GTK_WIDGET_TOPLEVEL (resize_container) || GTK_WIDGET_REALIZED (resize_container))) { switch (resize_container->resize_mode) { @@ -1065,9 +1389,9 @@ _gtk_container_queue_resize (GtkContainer *container) { GTK_PRIVATE_SET_FLAG (resize_container, GTK_RESIZE_PENDING); if (container_resize_queue == NULL) - gtk_idle_add_priority (GTK_PRIORITY_RESIZE, - gtk_container_idle_sizer, - NULL); + gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE, + gtk_container_idle_sizer, + NULL, NULL); container_resize_queue = g_slist_prepend (container_resize_queue, resize_container); } break; @@ -1077,7 +1401,7 @@ _gtk_container_queue_resize (GtkContainer *container) break; case GTK_RESIZE_PARENT: - /* Ignore, should not be reached */ + g_assert_not_reached (); break; } } @@ -1095,23 +1419,17 @@ _gtk_container_queue_resize (GtkContainer *container) void gtk_container_check_resize (GtkContainer *container) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); - gtk_signal_emit (GTK_OBJECT (container), container_signals[CHECK_RESIZE]); + g_signal_emit (container, container_signals[CHECK_RESIZE], 0); } static void gtk_container_real_check_resize (GtkContainer *container) { - GtkWidget *widget; + GtkWidget *widget = GTK_WIDGET (container); GtkRequisition requisition; - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_CONTAINER (container)); - - widget = GTK_WIDGET (container); - gtk_widget_size_request (widget, &requisition); if (requisition.width > widget->allocation.width || @@ -1146,7 +1464,6 @@ gtk_container_resize_children (GtkContainer *container) * containers that have an idle sizer pending must be flagged with * RESIZE_PENDING. */ - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); widget = GTK_WIDGET (container); @@ -1173,7 +1490,6 @@ gtk_container_forall (GtkContainer *container, { GtkContainerClass *class; - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (callback != NULL); @@ -1189,7 +1505,7 @@ gtk_container_forall (GtkContainer *container, * @callback: a callback * @callback_data: callback user data * - * Invokes @callback on each non-internal child of @container. See + * Invokes @callback on each non-internal child of @container. See * gtk_container_forall() for details on what constitutes an * "internal" child. Most applications should use * gtk_container_foreach(), rather than gtk_container_forall(). @@ -1201,7 +1517,6 @@ gtk_container_foreach (GtkContainer *container, { GtkContainerClass *class; - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (callback != NULL); @@ -1228,12 +1543,12 @@ gtk_container_foreach_unmarshal (GtkWidget *child, /* first argument */ args[0].name = NULL; - args[0].type = GTK_OBJECT_TYPE (child); + args[0].type = G_TYPE_FROM_INSTANCE (child); GTK_VALUE_OBJECT (args[0]) = GTK_OBJECT (child); /* location for return value */ args[1].name = NULL; - args[1].type = GTK_TYPE_NONE; + args[1].type = G_TYPE_NONE; fdata->callback (fdata->container, fdata->callback_data, 1, args); } @@ -1243,9 +1558,8 @@ gtk_container_foreach_full (GtkContainer *container, GtkCallback callback, GtkCallbackMarshal marshal, gpointer callback_data, - GtkDestroyNotify notify) + GDestroyNotify notify) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); if (marshal) @@ -1269,23 +1583,52 @@ gtk_container_foreach_full (GtkContainer *container, notify (callback_data); } +/** + * gtk_container_set_focus_child: + * @container: a #GtkContainer + * @child: a #GtkWidget, or %NULL + * + * Sets, or unsets if @child is %NULL, the focused child of @container. + * + * This function emits the GtkContainer::set_focus_child signal of + * @container. Implementations of #GtkContainer can override the + * default behaviour by overriding the class closure of this signal. + */ void gtk_container_set_focus_child (GtkContainer *container, - GtkWidget *widget) + GtkWidget *child) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); - if (widget) - g_return_if_fail (GTK_IS_WIDGET (widget)); + if (child) + g_return_if_fail (GTK_IS_WIDGET (child)); + + g_signal_emit (container, container_signals[SET_FOCUS_CHILD], 0, child); +} + +/** + * gtk_container_get_focus_child: + * @container: a #GtkContainer + * + * Returns the current focus child widget inside @container. + * + * Returns: The child widget which has the focus + * inside @container, or %NULL if none is set. + * + * Since: 2.14 + **/ +GtkWidget * +gtk_container_get_focus_child (GtkContainer *container) +{ + g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); - gtk_signal_emit (GTK_OBJECT (container), container_signals[SET_FOCUS_CHILD], widget); + return container->focus_child; } /** * gtk_container_get_children: - * @container: a #GtkContainer. + * @container: a #GtkContainer * - * Returns the the container's non-internal children. See + * Returns the container's non-internal children. See * gtk_container_forall() for details on what constitutes an "internal" child. * * Return value: a newly-allocated list of the container's non-internal children. @@ -1293,9 +1636,7 @@ gtk_container_set_focus_child (GtkContainer *container, GList* gtk_container_get_children (GtkContainer *container) { - GList *children; - - children = NULL; + GList *children = NULL; gtk_container_foreach (container, gtk_container_children_callback, @@ -1339,7 +1680,7 @@ gtk_container_child_default_composite_name (GtkContainer *container, &data); name = g_strdup_printf ("%s-%u", - gtk_type_name (GTK_OBJECT_TYPE (child)), + g_type_name (G_TYPE_FROM_INSTANCE (child)), data.index); return name; @@ -1349,9 +1690,7 @@ gchar* _gtk_container_child_composite_name (GtkContainer *container, GtkWidget *child) { - g_return_val_if_fail (container != NULL, NULL); g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); - g_return_val_if_fail (child != NULL, NULL); g_return_val_if_fail (GTK_IS_WIDGET (child), NULL); g_return_val_if_fail (child->parent == GTK_WIDGET (container), NULL); @@ -1363,7 +1702,7 @@ _gtk_container_child_composite_name (GtkContainer *container, if (!quark_composite_name) quark_composite_name = g_quark_from_static_string ("gtk-composite-name"); - name = gtk_object_get_data_by_id (GTK_OBJECT (child), quark_composite_name); + name = g_object_get_qdata (G_OBJECT (child), quark_composite_name); if (!name) { GtkContainerClass *class; @@ -1385,18 +1724,16 @@ static void gtk_container_real_set_focus_child (GtkContainer *container, GtkWidget *child) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); - if (child) - g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child == NULL || GTK_IS_WIDGET (child)); if (child != container->focus_child) { if (container->focus_child) - gtk_widget_unref (container->focus_child); + g_object_unref (container->focus_child); container->focus_child = child; if (container->focus_child) - gtk_widget_ref (container->focus_child); + g_object_ref (container->focus_child); } @@ -1404,21 +1741,35 @@ gtk_container_real_set_focus_child (GtkContainer *container, */ if (container->focus_child) { - GtkAdjustment *adjustment; - - adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), vadjustment_key_id); - if (adjustment) - gtk_adjustment_clamp_page (adjustment, - container->focus_child->allocation.y, - (container->focus_child->allocation.y + - container->focus_child->allocation.height)); - - adjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), hadjustment_key_id); - if (adjustment) - gtk_adjustment_clamp_page (adjustment, - container->focus_child->allocation.x, - (container->focus_child->allocation.x + - container->focus_child->allocation.width)); + GtkAdjustment *hadj; + GtkAdjustment *vadj; + GtkWidget *focus_child; + gint x, y; + + hadj = g_object_get_qdata (G_OBJECT (container), hadjustment_key_id); + vadj = g_object_get_qdata (G_OBJECT (container), vadjustment_key_id); + if (hadj || vadj) + { + + focus_child = container->focus_child; + while (GTK_IS_CONTAINER (focus_child) && + GTK_CONTAINER (focus_child)->focus_child) + { + focus_child = GTK_CONTAINER (focus_child)->focus_child; + } + + gtk_widget_translate_coordinates (focus_child, container->focus_child, + 0, 0, &x, &y); + + x += container->focus_child->allocation.x; + y += container->focus_child->allocation.y; + + if (vadj) + gtk_adjustment_clamp_page (vadj, y, y + focus_child->allocation.height); + + if (hadj) + gtk_adjustment_clamp_page (hadj, x, x + focus_child->allocation.width); + } } } @@ -1428,6 +1779,20 @@ get_focus_chain (GtkContainer *container) return g_object_get_data (G_OBJECT (container), "gtk-container-focus-chain"); } +/* same as gtk_container_get_children, except it includes internals + */ +static GList * +gtk_container_get_all_children (GtkContainer *container) +{ + GList *children = NULL; + + gtk_container_forall (container, + gtk_container_children_callback, + &children); + + return children; +} + static gboolean gtk_container_focus (GtkWidget *widget, GtkDirectionType direction) @@ -1459,7 +1824,7 @@ gtk_container_focus (GtkWidget *widget, if (container->has_focus_chain) children = g_list_copy (get_focus_chain (container)); else - children = gtk_container_get_children (container); + children = gtk_container_get_all_children (container); if (container->has_focus_chain && (direction == GTK_DIR_TAB_FORWARD || @@ -1471,7 +1836,7 @@ gtk_container_focus (GtkWidget *widget, sorted_children = g_list_reverse (sorted_children); } else - sorted_children = gtk_container_focus_sort (container, children, direction); + sorted_children = _gtk_container_focus_sort (container, children, direction, NULL); return_val = gtk_container_focus_move (container, sorted_children, direction); @@ -1484,10 +1849,12 @@ gtk_container_focus (GtkWidget *widget, static gint tab_compare (gconstpointer a, - gconstpointer b) + gconstpointer b, + gpointer data) { const GtkWidget *child1 = a; const GtkWidget *child2 = b; + GtkTextDirection text_direction = GPOINTER_TO_INT (data); gint y1 = child1->allocation.y + child1->allocation.height / 2; gint y2 = child2->allocation.y + child2->allocation.height / 2; @@ -1497,7 +1864,10 @@ tab_compare (gconstpointer a, gint x1 = child1->allocation.x + child1->allocation.width / 2; gint x2 = child2->allocation.x + child2->allocation.width / 2; - return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1); + if (text_direction == GTK_TEXT_DIR_RTL) + return (x1 < x2) ? 1 : ((x1 == x2) ? 0 : -1); + else + return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1); } else return (y1 < y2) ? -1 : 1; @@ -1506,9 +1876,11 @@ tab_compare (gconstpointer a, static GList * gtk_container_focus_sort_tab (GtkContainer *container, GList *children, - GtkDirectionType direction) + GtkDirectionType direction, + GtkWidget *old_focus) { - children = g_list_sort (children, tab_compare); + GtkTextDirection text_direction = gtk_widget_get_direction (GTK_WIDGET (container)); + children = g_list_sort_with_data (children, tab_compare, GINT_TO_POINTER (text_direction)); /* if we are going backwards then reverse the order * of the children. @@ -1571,8 +1943,8 @@ old_focus_coords (GtkContainer *container, { GtkWidget *widget = GTK_WIDGET (container); GtkWidget *toplevel = gtk_widget_get_toplevel (widget); - - if (toplevel && GTK_IS_WINDOW (toplevel) && GTK_WINDOW (toplevel)->focus_widget) + + if (GTK_IS_WINDOW (toplevel) && GTK_WINDOW (toplevel)->focus_widget) { GtkWidget *old_focus = GTK_WINDOW (toplevel)->focus_widget; @@ -1625,27 +1997,27 @@ up_down_compare (gconstpointer a, static GList * gtk_container_focus_sort_up_down (GtkContainer *container, GList *children, - GtkDirectionType direction) + GtkDirectionType direction, + GtkWidget *old_focus) { CompareInfo compare; GList *tmp_list; - GtkWidget *old_focus; + GdkRectangle old_allocation; compare.container = container; compare.reverse = (direction == GTK_DIR_UP); - old_focus = find_old_focus (container, children); - if (old_focus) + if (!old_focus) + old_focus = find_old_focus (container, children); + + if (old_focus && get_allocation_coords (container, old_focus, &old_allocation)) { - GdkRectangle old_allocation; gint compare_x1; gint compare_x2; gint compare_y; /* Delete widgets from list that don't match minimum criteria */ - get_allocation_coords (container, old_focus, &old_allocation); - compare_x1 = old_allocation.x; compare_x2 = old_allocation.x + old_allocation.width; @@ -1664,17 +2036,20 @@ gtk_container_focus_sort_up_down (GtkContainer *container, if (child != old_focus) { - get_allocation_coords (container, child, &child_allocation); - - child_x1 = child_allocation.x; - child_x2 = child_allocation.x + child_allocation.width; - - if ((child_x2 <= compare_x1 || child_x1 >= compare_x2) /* No horizontal overlap */ || - (direction == GTK_DIR_DOWN && child_allocation.y + child_allocation.height < compare_y) || /* Not below */ - (direction == GTK_DIR_UP && child_allocation.y > compare_y)) /* Not above */ + if (get_allocation_coords (container, child, &child_allocation)) { - children = g_list_delete_link (children, tmp_list); + child_x1 = child_allocation.x; + child_x2 = child_allocation.x + child_allocation.width; + + if ((child_x2 <= compare_x1 || child_x1 >= compare_x2) /* No horizontal overlap */ || + (direction == GTK_DIR_DOWN && child_allocation.y + child_allocation.height < compare_y) || /* Not below */ + (direction == GTK_DIR_UP && child_allocation.y > compare_y)) /* Not above */ + { + children = g_list_delete_link (children, tmp_list); + } } + else + children = g_list_delete_link (children, tmp_list); } tmp_list = next; @@ -1749,28 +2124,27 @@ left_right_compare (gconstpointer a, static GList * gtk_container_focus_sort_left_right (GtkContainer *container, GList *children, - GtkDirectionType direction) + GtkDirectionType direction, + GtkWidget *old_focus) { CompareInfo compare; GList *tmp_list; - GtkWidget *old_focus; + GdkRectangle old_allocation; compare.container = container; compare.reverse = (direction == GTK_DIR_LEFT); + + if (!old_focus) + old_focus = find_old_focus (container, children); - old_focus = find_old_focus (container, children); - if (old_focus) + if (old_focus && get_allocation_coords (container, old_focus, &old_allocation)) { - GdkRectangle old_allocation; - gint compare_y1; gint compare_y2; gint compare_x; /* Delete widgets from list that don't match minimum criteria */ - get_allocation_coords (container, old_focus, &old_allocation); - compare_y1 = old_allocation.y; compare_y2 = old_allocation.y + old_allocation.height; @@ -1789,17 +2163,20 @@ gtk_container_focus_sort_left_right (GtkContainer *container, if (child != old_focus) { - get_allocation_coords (container, child, &child_allocation); - - child_y1 = child_allocation.y; - child_y2 = child_allocation.y + child_allocation.height; - - if ((child_y2 <= compare_y1 || child_y1 >= compare_y2) /* No vertical overlap */ || - (direction == GTK_DIR_RIGHT && child_allocation.x + child_allocation.width < compare_x) || /* Not to left */ - (direction == GTK_DIR_LEFT && child_allocation.x > compare_x)) /* Not to right */ + if (get_allocation_coords (container, child, &child_allocation)) { - children = g_list_delete_link (children, tmp_list); + child_y1 = child_allocation.y; + child_y2 = child_allocation.y + child_allocation.height; + + if ((child_y2 <= compare_y1 || child_y1 >= compare_y2) /* No vertical overlap */ || + (direction == GTK_DIR_RIGHT && child_allocation.x + child_allocation.width < compare_x) || /* Not to left */ + (direction == GTK_DIR_LEFT && child_allocation.x > compare_x)) /* Not to right */ + { + children = g_list_delete_link (children, tmp_list); + } } + else + children = g_list_delete_link (children, tmp_list); } tmp_list = next; @@ -1845,8 +2222,13 @@ gtk_container_focus_sort_left_right (GtkContainer *container, * gtk_container_focus_sort: * @container: a #GtkContainer * @children: a list of descendents of @container (they don't - * have to be direct children. + * have to be direct children) * @direction: focus direction + * @old_focus: widget to use for the starting position, or %NULL + * to determine this automatically. + * (Note, this argument isn't used for GTK_DIR_TAB_*, + * which is the only @direction we use currently, + * so perhaps this argument should be removed) * * Sorts @children in the correct order for focusing with * direction type @direction. @@ -1855,24 +2237,32 @@ gtk_container_focus_sort_left_right (GtkContainer *container, * with children that aren't suitable for focusing in this direction * removed. **/ -static GList * -gtk_container_focus_sort (GtkContainer *container, - GList *children, - GtkDirectionType direction) +GList * +_gtk_container_focus_sort (GtkContainer *container, + GList *children, + GtkDirectionType direction, + GtkWidget *old_focus) { - children = g_list_copy (children); + GList *visible_children = NULL; + + while (children) + { + if (GTK_WIDGET_REALIZED (children->data)) + visible_children = g_list_prepend (visible_children, children->data); + children = children->next; + } switch (direction) { case GTK_DIR_TAB_FORWARD: case GTK_DIR_TAB_BACKWARD: - return gtk_container_focus_sort_tab (container, children, direction); + return gtk_container_focus_sort_tab (container, visible_children, direction, old_focus); case GTK_DIR_UP: case GTK_DIR_DOWN: - return gtk_container_focus_sort_up_down (container, children, direction); + return gtk_container_focus_sort_up_down (container, visible_children, direction, old_focus); case GTK_DIR_LEFT: case GTK_DIR_RIGHT: - return gtk_container_focus_sort_left_right (container, children, direction); + return gtk_container_focus_sort_left_right (container, visible_children, direction, old_focus); } g_assert_not_reached (); @@ -1944,19 +2334,19 @@ chain_widget_destroyed (GtkWidget *widget, chain = g_list_remove (chain, widget); - g_signal_handlers_disconnect_by_func (G_OBJECT (widget), + g_signal_handlers_disconnect_by_func (widget, chain_widget_destroyed, user_data); g_object_set_data (G_OBJECT (container), - "gtk-container-focus-chain", + I_("gtk-container-focus-chain"), chain); } /** * gtk_container_set_focus_chain: - * @container: a #GtkContainer. - * @focusable_widgets: the new focus chain. + * @container: a #GtkContainer + * @focusable_widgets: the new focus chain * * Sets a focus chain, overriding the one computed automatically by GTK+. * @@ -1995,10 +2385,10 @@ gtk_container_set_focus_chain (GtkContainer *container, chain = g_list_prepend (chain, tmp_list->data); - gtk_signal_connect (GTK_OBJECT (tmp_list->data), - "destroy", - GTK_SIGNAL_FUNC (chain_widget_destroyed), - container); + g_signal_connect (tmp_list->data, + "destroy", + G_CALLBACK (chain_widget_destroyed), + container); tmp_list = g_list_next (tmp_list); } @@ -2006,7 +2396,7 @@ gtk_container_set_focus_chain (GtkContainer *container, chain = g_list_reverse (chain); g_object_set_data (G_OBJECT (container), - "gtk-container-focus-chain", + I_("gtk-container-focus-chain"), chain); } @@ -2047,7 +2437,7 @@ gtk_container_get_focus_chain (GtkContainer *container, /** * gtk_container_unset_focus_chain: - * @container: a #GtkContainer. + * @container: a #GtkContainer * * Removes a focus chain explicitly set with gtk_container_set_focus_chain(). **/ @@ -2065,13 +2455,14 @@ gtk_container_unset_focus_chain (GtkContainer *container) container->has_focus_chain = FALSE; - g_object_set_data (G_OBJECT (container), "gtk-container-focus-chain", + g_object_set_data (G_OBJECT (container), + I_("gtk-container-focus-chain"), NULL); tmp_list = chain; while (tmp_list != NULL) { - g_signal_handlers_disconnect_by_func (G_OBJECT (tmp_list->data), + g_signal_handlers_disconnect_by_func (tmp_list->data, chain_widget_destroyed, container); @@ -2082,22 +2473,37 @@ gtk_container_unset_focus_chain (GtkContainer *container) } } +/** + * gtk_container_set_focus_vadjustment: + * @container: a #GtkContainer + * @adjustment: an adjustment which should be adjusted when the focus + * is moved among the descendents of @container + * + * Hooks up an adjustment to focus handling in a container, so when a + * child of the container is focused, the adjustment is scrolled to + * show that widget. This function sets the vertical alignment. See + * gtk_scrolled_window_get_vadjustment() for a typical way of obtaining + * the adjustment and gtk_container_set_focus_hadjustment() for setting + * the horizontal adjustment. + * + * The adjustments have to be in pixel units and in the same coordinate + * system as the allocation for immediate children of the container. + */ void gtk_container_set_focus_vadjustment (GtkContainer *container, GtkAdjustment *adjustment) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); if (adjustment) g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment)); if (adjustment) - gtk_object_ref (GTK_OBJECT(adjustment)); + g_object_ref (adjustment); - gtk_object_set_data_by_id_full (GTK_OBJECT (container), - vadjustment_key_id, - adjustment, - (GtkDestroyNotify) gtk_object_unref); + g_object_set_qdata_full (G_OBJECT (container), + vadjustment_key_id, + adjustment, + g_object_unref); } /** @@ -2105,7 +2511,7 @@ gtk_container_set_focus_vadjustment (GtkContainer *container, * @container: a #GtkContainer * * Retrieves the vertical focus adjustment for the container. See - * gtk_container_set_focus_vadjustment (). + * gtk_container_set_focus_vadjustment(). * * Return value: the vertical focus adjustment, or %NULL if * none has been set. @@ -2117,28 +2523,42 @@ gtk_container_get_focus_vadjustment (GtkContainer *container) g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); - vadjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), - vadjustment_key_id); + vadjustment = g_object_get_qdata (G_OBJECT (container), vadjustment_key_id); return vadjustment; } +/** + * gtk_container_set_focus_hadjustment: + * @container: a #GtkContainer + * @adjustment: an adjustment which should be adjusted when the focus is + * moved among the descendents of @container + * + * Hooks up an adjustment to focus handling in a container, so when a child + * of the container is focused, the adjustment is scrolled to show that + * widget. This function sets the horizontal alignment. + * See gtk_scrolled_window_get_hadjustment() for a typical way of obtaining + * the adjustment and gtk_container_set_focus_vadjustment() for setting + * the vertical adjustment. + * + * The adjustments have to be in pixel units and in the same coordinate + * system as the allocation for immediate children of the container. + */ void gtk_container_set_focus_hadjustment (GtkContainer *container, GtkAdjustment *adjustment) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); if (adjustment) g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment)); if (adjustment) - gtk_object_ref (GTK_OBJECT (adjustment)); + g_object_ref (adjustment); - gtk_object_set_data_by_id_full (GTK_OBJECT (container), - hadjustment_key_id, - adjustment, - (GtkDestroyNotify) gtk_object_unref); + g_object_set_qdata_full (G_OBJECT (container), + hadjustment_key_id, + adjustment, + g_object_unref); } /** @@ -2158,8 +2578,7 @@ gtk_container_get_focus_hadjustment (GtkContainer *container) g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); - hadjustment = gtk_object_get_data_by_id (GTK_OBJECT (container), - hadjustment_key_id); + hadjustment = g_object_get_qdata (G_OBJECT (container), hadjustment_key_id); return hadjustment; } @@ -2168,7 +2587,6 @@ gtk_container_get_focus_hadjustment (GtkContainer *container) static void gtk_container_show_all (GtkWidget *widget) { - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_CONTAINER (widget)); gtk_container_foreach (GTK_CONTAINER (widget), @@ -2180,7 +2598,6 @@ gtk_container_show_all (GtkWidget *widget) static void gtk_container_hide_all (GtkWidget *widget) { - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_CONTAINER (widget)); gtk_widget_hide (widget); @@ -2213,7 +2630,6 @@ gtk_container_expose (GtkWidget *widget, GdkEventExpose *event; } data; - g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_CONTAINER (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); @@ -2284,7 +2700,7 @@ gtk_container_unmap (GtkWidget *widget) * the event's area with the child area, and sending the event. * * In most cases, a container can simply either simply inherit the - * ::expose implementation from #GtkContainer, or, do some drawing + * #GtkWidget::expose implementation from #GtkContainer, or, do some drawing * and then chain to the ::expose implementation from #GtkContainer. **/ void @@ -2292,7 +2708,7 @@ gtk_container_propagate_expose (GtkContainer *container, GtkWidget *child, GdkEventExpose *event) { - GdkEventExpose child_event; + GdkEvent *child_event; g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (GTK_IS_WIDGET (child)); @@ -2304,14 +2720,19 @@ gtk_container_propagate_expose (GtkContainer *container, GTK_WIDGET_NO_WINDOW (child) && (child->window == event->window)) { - child_event = *event; + child_event = gdk_event_new (GDK_EXPOSE); + child_event->expose = *event; + g_object_ref (child_event->expose.window); - child_event.region = gtk_widget_region_intersect (child, event->region); - if (!gdk_region_empty (child_event.region)) + child_event->expose.region = gtk_widget_region_intersect (child, event->region); + if (!gdk_region_empty (child_event->expose.region)) { - gdk_region_get_clipbox (child_event.region, &child_event.area); - gtk_widget_send_expose (child, (GdkEvent *)&child_event); + gdk_region_get_clipbox (child_event->expose.region, &child_event->expose.area); + gtk_widget_send_expose (child, child_event); } - gdk_region_destroy (child_event.region); + gdk_event_free (child_event); } } + +#define __GTK_CONTAINER_C__ +#include "gtkaliasdef.c"