]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcontainer.c
Replace a lot of idle and timeout calls by the new gdk_threads api.
[~andy/gtk] / gtk / gtkcontainer.c
index b6c87b82c629e7d4b7a1237d63bb2b4fa4263c78..b7ced4e359d5ef5d8ee482e529b1781d7e43b07c 100644 (file)
@@ -24,6 +24,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
 #include <stdarg.h>
 #include <string.h>
 #include <stdlib.h>
 #include "gtkmarshalers.h"
 #include "gtkwindow.h"
 #include "gtkintl.h"
+#include "gtktoolbar.h"
 #include <gobject/gobjectnotifyqueue.c>
 #include <gobject/gvaluecollector.h>
+#include "gtkalias.h"
 
 
 enum {
@@ -98,9 +101,9 @@ static gchar* gtk_container_child_default_composite_name (GtkContainer *containe
 
 
 /* --- 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 };
@@ -117,7 +120,7 @@ gtk_container_get_type (void)
 
   if (!container_type)
     {
-      static const GTypeInfo container_info =
+      const GTypeInfo container_info =
       {
        sizeof (GtkContainerClass),
        (GBaseInitFunc) gtk_container_base_class_init,
@@ -132,7 +135,7 @@ gtk_container_get_type (void)
       };
 
       container_type =
-       g_type_register_static (GTK_TYPE_WIDGET, "GtkContainer"
+       g_type_register_static (GTK_TYPE_WIDGET, I_("GtkContainer")
                                &container_info, G_TYPE_FLAG_ABSTRACT);
     }
 
@@ -198,30 +201,30 @@ 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] =
-    g_signal_new ("add",
+    g_signal_new (I_("add"),
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GtkContainerClass, add),
@@ -230,7 +233,7 @@ gtk_container_class_init (GtkContainerClass *class)
                  G_TYPE_NONE, 1,
                  GTK_TYPE_WIDGET);
   container_signals[REMOVE] =
-    g_signal_new ("remove",
+    g_signal_new (I_("remove"),
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GtkContainerClass, remove),
@@ -239,7 +242,7 @@ gtk_container_class_init (GtkContainerClass *class)
                  G_TYPE_NONE, 1,
                  GTK_TYPE_WIDGET);
   container_signals[CHECK_RESIZE] =
-    g_signal_new ("check_resize",
+    g_signal_new (I_("check_resize"),
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkContainerClass, check_resize),
@@ -247,7 +250,7 @@ gtk_container_class_init (GtkContainerClass *class)
                  _gtk_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
   container_signals[SET_FOCUS_CHILD] =
-    g_signal_new ("set-focus-child",
+    g_signal_new (I_("set-focus-child"),
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GtkContainerClass, set_focus_child),
@@ -494,7 +497,6 @@ gtk_container_child_set_valist (GtkContainer *container,
                                const gchar  *first_property_name,
                                va_list       var_args)
 {
-  GObject *object;
   GObjectNotifyQueue *nqueue;
   const gchar *name;
 
@@ -505,7 +507,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)
@@ -569,7 +570,6 @@ gtk_container_child_set_property (GtkContainer *container,
                                  const gchar  *property_name,
                                  const GValue *value)
 {
-  GObject *object;
   GObjectNotifyQueue *nqueue;
   GParamSpec *pspec;
 
@@ -582,7 +582,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);
@@ -901,7 +900,7 @@ gtk_container_set_border_width (GtkContainer *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));
@@ -970,7 +969,10 @@ 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,
@@ -978,7 +980,13 @@ 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 (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));
   
   g_signal_emit (container, container_signals[REMOVE], 0, widget);
 }
@@ -1022,7 +1030,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");
     }
 }
 
@@ -1080,8 +1088,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
@@ -1104,8 +1110,6 @@ gtk_container_idle_sizer (gpointer data)
 
   gdk_window_process_all_updates ();
 
-  GDK_THREADS_LEAVE ();
-
   return FALSE;
 }
 
@@ -1120,7 +1124,7 @@ _gtk_container_queue_resize (GtkContainer *container)
   widget = GTK_WIDGET (container);
   resize_container = gtk_container_get_resize_container (container);
   
-  while (!GTK_WIDGET_ALLOC_NEEDED (widget) || !GTK_WIDGET_REQUEST_NEEDED (widget))
+  while (TRUE)
     {
       GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
       GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
@@ -1143,7 +1147,7 @@ _gtk_container_queue_resize (GtkContainer *container)
                {
                  GTK_PRIVATE_SET_FLAG (resize_container, GTK_RESIZE_PENDING);
                  if (container_resize_queue == NULL)
-                   g_idle_add_full (GTK_PRIORITY_RESIZE,
+                   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);
@@ -1352,7 +1356,7 @@ gtk_container_set_focus_child (GtkContainer *container,
  * gtk_container_get_children:
  * @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.
@@ -1449,8 +1453,7 @@ gtk_container_real_set_focus_child (GtkContainer     *container,
                                    GtkWidget        *child)
 {
   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)
     {
@@ -1466,21 +1469,35 @@ gtk_container_real_set_focus_child (GtkContainer     *container,
    */
   if (container->focus_child)
     {
-      GtkAdjustment *adjustment;
-      
-      adjustment = g_object_get_qdata (G_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 = g_object_get_qdata (G_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);
+       }
     }
 }
 
@@ -1560,10 +1577,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;
@@ -1573,7 +1592,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;
@@ -1585,7 +1607,8 @@ gtk_container_focus_sort_tab (GtkContainer     *container,
                              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.
@@ -1679,10 +1702,8 @@ up_down_compare (gconstpointer a,
   CompareInfo *compare = data;
   gint y1, y2;
 
-  if (!get_allocation_coords (compare->container, (GtkWidget *)a, &allocation1))
-    return 0;
-  if (!get_allocation_coords (compare->container, (GtkWidget *)b, &allocation2))
-    return 0;
+  get_allocation_coords (compare->container, (GtkWidget *)a, &allocation1);
+  get_allocation_coords (compare->container, (GtkWidget *)b, &allocation2);
 
   y1 = allocation1.y + allocation1.height / 2;
   y2 = allocation2.y + allocation2.height / 2;
@@ -1808,10 +1829,8 @@ left_right_compare (gconstpointer a,
   CompareInfo *compare = data;
   gint x1, x2;
 
-  if (!get_allocation_coords (compare->container, (GtkWidget *)a, &allocation1))
-    return 0;
-  if (!get_allocation_coords (compare->container, (GtkWidget *)b, &allocation2))
-    return 0;
+  get_allocation_coords (compare->container, (GtkWidget *)a, &allocation1);
+  get_allocation_coords (compare->container, (GtkWidget *)b, &allocation2);
 
   x1 = allocation1.x + allocation1.width / 2;
   x2 = allocation2.x + allocation2.width / 2;
@@ -1952,19 +1971,26 @@ _gtk_container_focus_sort (GtkContainer     *container,
                           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, old_focus);
+      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, old_focus);
+      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, old_focus);
+      return gtk_container_focus_sort_left_right (container, visible_children, direction, old_focus);
     }
 
   g_assert_not_reached ();
@@ -2041,7 +2067,7 @@ chain_widget_destroyed (GtkWidget *widget,
                                         user_data);
   
   g_object_set_data (G_OBJECT (container),
-                     "gtk-container-focus-chain",
+                     I_("gtk-container-focus-chain"),
                      chain);  
 }
 
@@ -2098,7 +2124,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);
 }
 
@@ -2157,7 +2183,8 @@ 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;
@@ -2174,6 +2201,21 @@ 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)
@@ -2213,6 +2255,21 @@ gtk_container_get_focus_vadjustment (GtkContainer *container)
   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)
@@ -2402,3 +2459,6 @@ gtk_container_propagate_expose (GtkContainer   *container,
       gdk_event_free (child_event);
     }
 }
+
+#define __GTK_CONTAINER_C__
+#include "gtkaliasdef.c"