]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcontainer.c
Change FSF Address
[~andy/gtk] / gtk / gtkcontainer.c
index f6fff0697b13c556931a2fc733d7bbe937676257..88f79b394e30e63b52920255411d83d9424f2e4b 100644 (file)
@@ -12,9 +12,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
@@ -27,6 +25,7 @@
 #include "config.h"
 
 #include "gtkcontainer.h"
+#include "gtkcontainerprivate.h"
 
 #include <stdarg.h>
 #include <string.h>
@@ -44,9 +43,9 @@
 #include "gtksizerequest.h"
 #include "gtkwidgetprivate.h"
 #include "gtkwindow.h"
+#include "gtkassistant.h"
 #include "gtkintl.h"
-#include "gtktoolbar.h"
-
+#include "a11y/gtkcontaineraccessible.h"
 
 /**
  * SECTION:gtkcontainer
@@ -72,7 +71,7 @@
  * The second type of container can have more than one child; its purpose is to
  * manage <emphasis>layout</emphasis>. This means that these containers assign
  * sizes and positions to their children. For example, a #GtkHBox arranges its
- * children in a horizontal row, and a #GtkTable arranges the widgets it contains
+ * children in a horizontal row, and a #GtkGrid arranges the widgets it contains
  * in a two-dimensional grid.
  *
  * <refsect2 id="container-geometry-management">
@@ -239,6 +238,7 @@ struct _GtkContainerPrivate
   guint need_resize        : 1;
   guint reallocate_redraws : 1;
   guint resize_mode        : 2;
+  guint request_mode       : 2;
 };
 
 enum {
@@ -307,6 +307,7 @@ static void     gtk_container_adjust_size_allocation (GtkWidget       *widget,
                                                       gint            *natural_size,
                                                       gint            *allocated_pos,
                                                       gint            *allocated_size);
+static GtkSizeRequestMode gtk_container_get_request_mode (GtkWidget   *widget);
 
 static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
                                                           GtkWidget    *child);
@@ -437,6 +438,7 @@ gtk_container_class_init (GtkContainerClass *class)
 
   widget_class->adjust_size_request = gtk_container_adjust_size_request;
   widget_class->adjust_size_allocation = gtk_container_adjust_size_allocation;
+  widget_class->get_request_mode = gtk_container_get_request_mode;
 
   class->add = gtk_container_add_unimplemented;
   class->remove = gtk_container_remove_unimplemented;
@@ -508,6 +510,8 @@ gtk_container_class_init (GtkContainerClass *class)
                   GTK_TYPE_WIDGET);
 
   g_type_class_add_private (class, sizeof (GtkContainerPrivate));
+
+  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_CONTAINER_ACCESSIBLE);
 }
 
 static void
@@ -547,7 +551,7 @@ gtk_container_buildable_set_child_property (GtkContainer *container,
                                             const gchar  *value)
 {
   GParamSpec *pspec;
-  GValue gvalue = { 0, };
+  GValue gvalue = G_VALUE_INIT;
   GError *error = NULL;
 
   pspec = gtk_container_class_find_child_property
@@ -761,6 +765,68 @@ gtk_container_child_type (GtkContainer *container)
 }
 
 /* --- GtkContainer child property mechanism --- */
+
+/**
+ * gtk_container_child_notify:
+ * @container: the #GtkContainer
+ * @child: the child widget
+ * @child_property: the name of a child property installed on
+ *     the class of @container
+ *
+ * Emits a #GtkWidget::child-notify signal for the
+ * <link linkend="child-properties">child property</link>
+ * @child_property on widget.
+ *
+ * This is an analogue of g_object_notify() for child properties.
+ *
+ * Also see gtk_widget_child_notify().
+ *
+ * Since: 3.2
+ */
+void
+gtk_container_child_notify (GtkContainer *container,
+                            GtkWidget    *child,
+                            const gchar  *child_property)
+{
+  GObject *obj;
+  GParamSpec *pspec;
+
+  g_return_if_fail (GTK_IS_CONTAINER (container));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+  g_return_if_fail (child_property != NULL);
+
+  obj = G_OBJECT (child);
+
+  if (obj->ref_count == 0)
+    return;
+
+  g_object_ref (obj);
+
+  pspec = g_param_spec_pool_lookup (_gtk_widget_child_property_pool,
+                                    child_property,
+                                    G_OBJECT_TYPE (container),
+                                    TRUE);
+
+  if (pspec == NULL)
+    {
+      g_warning ("%s: container class `%s' has no child property named `%s'",
+                 G_STRLOC,
+                 G_OBJECT_TYPE_NAME (container),
+                 child_property);
+    }
+  else
+    {
+      GObjectNotifyQueue *nqueue;
+
+      nqueue = g_object_notify_queue_freeze (obj, _gtk_widget_child_property_notify_context);
+
+      g_object_notify_queue_add (obj, nqueue, pspec);
+      g_object_notify_queue_thaw (obj, nqueue);
+    }
+
+  g_object_unref (obj);
+}
+
 static inline void
 container_get_child_property (GtkContainer *container,
                               GtkWidget    *child,
@@ -779,7 +845,7 @@ container_set_child_property (GtkContainer       *container,
                               const GValue       *value,
                               GObjectNotifyQueue *nqueue)
 {
-  GValue tmp_value = { 0, };
+  GValue tmp_value = G_VALUE_INIT;
   GtkContainerClass *class = g_type_class_peek (pspec->owner_type);
 
   /* provide a copy to work from, convert (if necessary) and validate */
@@ -828,7 +894,6 @@ gtk_container_child_get_valist (GtkContainer *container,
 
   g_return_if_fail (GTK_IS_CONTAINER (container));
   g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
 
   g_object_ref (container);
   g_object_ref (child);
@@ -836,7 +901,7 @@ gtk_container_child_get_valist (GtkContainer *container,
   name = first_property_name;
   while (name)
     {
-      GValue value = { 0, };
+      GValue value = G_VALUE_INIT;
       GParamSpec *pspec;
       gchar *error;
 
@@ -897,7 +962,6 @@ gtk_container_child_get_property (GtkContainer *container,
 
   g_return_if_fail (GTK_IS_CONTAINER (container));
   g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
   g_return_if_fail (property_name != NULL);
   g_return_if_fail (G_IS_VALUE (value));
 
@@ -917,7 +981,7 @@ gtk_container_child_get_property (GtkContainer *container,
                G_OBJECT_TYPE_NAME (container));
   else
     {
-      GValue *prop_value, tmp_value = { 0, };
+      GValue *prop_value, tmp_value = G_VALUE_INIT;
 
       /* auto-conversion of the callers value type
        */
@@ -973,7 +1037,6 @@ gtk_container_child_set_valist (GtkContainer *container,
 
   g_return_if_fail (GTK_IS_CONTAINER (container));
   g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
 
   g_object_ref (container);
   g_object_ref (child);
@@ -982,7 +1045,7 @@ gtk_container_child_set_valist (GtkContainer *container,
   name = first_property_name;
   while (name)
     {
-      GValue value = { 0, };
+      GValue value = G_VALUE_INIT;
       gchar *error = NULL;
       GParamSpec *pspec = g_param_spec_pool_lookup (_gtk_widget_child_property_pool,
                                                     name,
@@ -1047,7 +1110,6 @@ gtk_container_child_set_property (GtkContainer *container,
 
   g_return_if_fail (GTK_IS_CONTAINER (container));
   g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
   g_return_if_fail (property_name != NULL);
   g_return_if_fail (G_IS_VALUE (value));
 
@@ -1081,12 +1143,12 @@ gtk_container_child_set_property (GtkContainer *container,
  * @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
+ * @...: 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,
@@ -1121,11 +1183,11 @@ gtk_container_add_with_properties (GtkContainer *container,
  * @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
+ * @...: 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,
@@ -1134,10 +1196,6 @@ gtk_container_child_set (GtkContainer      *container,
 {
   va_list var_args;
 
-  g_return_if_fail (GTK_IS_CONTAINER (container));
-  g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
-
   va_start (var_args, first_prop_name);
   gtk_container_child_set_valist (container, child, first_prop_name, var_args);
   va_end (var_args);
@@ -1148,11 +1206,11 @@ gtk_container_child_set (GtkContainer      *container,
  * @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
+ * @...: 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,
@@ -1161,10 +1219,6 @@ gtk_container_child_get (GtkContainer      *container,
 {
   va_list var_args;
 
-  g_return_if_fail (GTK_IS_CONTAINER (container));
-  g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
-
   va_start (var_args, first_prop_name);
   gtk_container_child_get_valist (container, child, first_prop_name, var_args);
   va_end (var_args);
@@ -1211,10 +1265,11 @@ gtk_container_class_install_child_property (GtkContainerClass *cclass,
  * gtk_container_class_find_child_property:
  * @cclass: (type GtkContainerClass): a #GtkContainerClass
  * @property_name: the name of the child property to find
- * @returns: (transfer none): 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.
+ *
+ * Returns: (transfer none): the #GParamSpec of the child property
+ *     or %NULL if @class has no child property with that name.
  */
 GParamSpec*
 gtk_container_class_find_child_property (GObjectClass *cclass,
@@ -1233,11 +1288,12 @@ gtk_container_class_find_child_property (GObjectClass *cclass,
  * gtk_container_class_list_child_properties:
  * @cclass: (type GtkContainerClass): a #GtkContainerClass
  * @n_properties: location to return the number of child properties found
- * @returns: (array length=n_properties) (transfer container): a newly
- *           allocated %NULL-terminated array of #GParamSpec*.  The
- *           array must be freed with g_free().
  *
  * Returns all child properties of a container class.
+ *
+ * Returns: (array length=n_properties) (transfer container):
+ *     a newly allocated %NULL-terminated array of #GParamSpec*.
+ *     The array must be freed with g_free().
  */
 GParamSpec**
 gtk_container_class_list_child_properties (GObjectClass *cclass,
@@ -1423,10 +1479,10 @@ gtk_container_get_border_width (GtkContainer *container)
  *
  * Adds @widget to @container. Typically used for simple containers
  * such as #GtkWindow, #GtkFrame, or #GtkButton; for more complicated
- * layout containers such as #GtkBox or #GtkTable, this function will
+ * layout containers such as #GtkBox or #GtkGrid, this function will
  * pick default packing parameters that may not be correct.  So
  * consider functions such as gtk_box_pack_start() and
- * gtk_table_attach() as an alternative to gtk_container_add() in
+ * gtk_grid_attach() as an alternative to gtk_container_add() in
  * those cases. A widget may be added to only one container at a time;
  * you can't place the same widget inside two different containers.
  **/
@@ -1476,7 +1532,7 @@ gtk_container_remove (GtkContainer *container,
 {
   g_return_if_fail (GTK_IS_CONTAINER (container));
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container));
+  g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container) || GTK_IS_ASSISTANT (container));
 
   g_signal_emit (container, container_signals[REMOVE], 0, widget);
 }
@@ -1851,6 +1907,57 @@ gtk_container_adjust_size_allocation (GtkWidget         *widget,
                                         allocated_size);
 }
 
+typedef struct {
+  gint hfw;
+  gint wfh;
+} RequestModeCount;
+
+static void
+count_request_modes (GtkWidget        *widget,
+                    RequestModeCount *count)
+{
+  GtkSizeRequestMode mode = gtk_widget_get_request_mode (widget);
+
+  switch (mode)
+    {
+    case GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH:
+      count->hfw++;
+      break;
+    case GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT:
+      count->wfh++;
+      break;
+    case GTK_SIZE_REQUEST_CONSTANT_SIZE:
+    default:
+      break;
+    }
+}
+
+static GtkSizeRequestMode 
+gtk_container_get_request_mode (GtkWidget *widget)
+{
+  GtkContainer        *container = GTK_CONTAINER (widget);
+  GtkContainerPrivate *priv      = container->priv;
+
+  /* Recalculate the request mode of the children by majority
+   * vote whenever the internal content changes */
+  if (_gtk_widget_get_width_request_needed (widget) ||
+      _gtk_widget_get_height_request_needed (widget))
+    {
+      RequestModeCount count = { 0, 0 };
+
+      gtk_container_forall (container, (GtkCallback)count_request_modes, &count);
+
+      if (!count.hfw && !count.wfh)
+       priv->request_mode = GTK_SIZE_REQUEST_CONSTANT_SIZE;
+      else
+       priv->request_mode = count.wfh > count.hfw ? 
+         GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT :
+         GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+    }
+
+  return priv->request_mode;
+}
+
 /**
  * gtk_container_class_handle_border_width:
  * @klass: the class struct of a #GtkContainer subclass
@@ -2193,8 +2300,8 @@ get_focus_chain (GtkContainer *container)
 
 /* same as gtk_container_get_children, except it includes internals
  */
-static GList *
-gtk_container_get_all_children (GtkContainer *container)
+GList *
+_gtk_container_get_all_children (GtkContainer *container)
 {
   GList *children = NULL;
 
@@ -2230,6 +2337,8 @@ gtk_container_real_get_path_for_child (GtkContainer *container,
       g_list_free_1 (cur);
     }
 
+  gtk_widget_path_append_for_widget (path, child);
+
   return path;
 }
 
@@ -2266,7 +2375,7 @@ gtk_container_focus (GtkWidget        *widget,
       if (priv->has_focus_chain)
         children = g_list_copy (get_focus_chain (container));
       else
-        children = gtk_container_get_all_children (container);
+        children = _gtk_container_get_all_children (container);
 
       if (priv->has_focus_chain &&
           (direction == GTK_DIR_TAB_FORWARD ||
@@ -3258,7 +3367,7 @@ _gtk_container_get_reallocate_redraws (GtkContainer *container)
  * @child: a child of @container
  *
  * Returns a newly created widget path representing all the widget hierarchy
- * from the toplevel down to @child (this one not being included).
+ * from the toplevel down to and including @child.
  *
  * Returns: A newly created #GtkWidgetPath
  **/
@@ -3266,9 +3375,21 @@ GtkWidgetPath *
 gtk_container_get_path_for_child (GtkContainer *container,
                                   GtkWidget    *child)
 {
+  GtkWidgetPath *path;
+
   g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
   g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
   g_return_val_if_fail (container == (GtkContainer *) gtk_widget_get_parent (child), NULL);
 
-  return GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
+  path = GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
+  if (gtk_widget_path_get_object_type (path) != G_OBJECT_TYPE (child))
+    {
+      g_critical ("%s %p returned a widget path for type %s, but child is %s",
+                  G_OBJECT_TYPE_NAME (container),
+                  container,
+                  g_type_name (gtk_widget_path_get_object_type (path)),
+                  G_OBJECT_TYPE_NAME (child));
+    }
+
+  return path;
 }