[gtk+] box: Add support for siblings in widget paths of box children



commit cd838480eb01ad8a9185cb1d407088b7eb34d926
Author: Benjamin Otte <otte redhat com>
Date:   Wed May 25 23:38:59 2011 +0200

    box: Add support for siblings in widget paths of box children

 gtk/gtkbox.c |  126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 123 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkbox.c b/gtk/gtkbox.c
index b1d1df9..0c52a90 100644
--- a/gtk/gtkbox.c
+++ b/gtk/gtkbox.c
@@ -115,6 +115,7 @@ struct _GtkBoxPrivate
 
   GtkOrientation  orientation;
   gint16          spacing;
+  GtkWidgetPath  *sibling_path;
 
   guint           default_expand : 1;
   guint           homogeneous    : 1;
@@ -182,6 +183,9 @@ static void gtk_box_get_child_property (GtkContainer   *container,
                                         GValue         *value,
                                         GParamSpec     *pspec);
 static GType gtk_box_child_type        (GtkContainer   *container);
+static GtkWidgetPath * gtk_box_get_path_for_child
+                                       (GtkContainer   *container,
+                                        GtkWidget      *child);
 
 
 static void               gtk_box_get_preferred_width            (GtkWidget           *widget,
@@ -226,6 +230,7 @@ gtk_box_class_init (GtkBoxClass *class)
   container_class->child_type = gtk_box_child_type;
   container_class->set_child_property = gtk_box_set_child_property;
   container_class->get_child_property = gtk_box_get_child_property;
+  container_class->get_path_for_child = gtk_box_get_path_for_child;
   gtk_container_class_handle_border_width (container_class);
 
   g_object_class_override_property (object_class,
@@ -831,6 +836,113 @@ gtk_box_get_child_property (GtkContainer *container,
     }
 }
 
+typedef struct _CountingData CountingData;
+struct _CountingData {
+  GtkWidget *widget;
+  gboolean found;
+  guint count;
+};
+
+static void
+count_widget_position (GtkWidget *widget,
+                       gpointer   data)
+{
+  CountingData *count = data;
+
+#if 0
+  /* We cannot reliably detect changes in widget visibility */
+  if (!gtk_widget_get_visible (widget))
+    return;
+#endif
+
+  if (count->found)
+    return;
+
+  if (count->widget == widget)
+    {
+      count->found = TRUE;
+      return;
+    }
+
+  count->count++;
+}
+
+static guint
+gtk_box_get_visible_position (GtkBox *box,
+                              GtkWidget *child)
+{
+  CountingData count = { child, FALSE, 0 };
+
+  /* forall iterates in visible order */
+  gtk_container_forall (GTK_CONTAINER (box),
+                        count_widget_position,
+                        &count);
+
+  g_assert (count.found);
+  return count.count;
+}
+
+static void
+add_widget_to_path (GtkWidget *widget,
+                    gpointer   path)
+{
+#if 0
+  /* We cannot reliably detect changes in widget visibility */
+  if (!gtk_widget_get_visible (widget))
+    return;
+#endif
+
+  gtk_widget_path_append_for_widget (path, widget);
+}
+
+static GtkWidgetPath *
+gtk_box_get_path_for_child (GtkContainer *container,
+                            GtkWidget    *child)
+{
+  GtkWidgetPath *path;
+  GtkBox *box;
+  GtkBoxPrivate *private;
+
+  box = GTK_BOX (container);
+  private = box->priv;
+
+  if (private->sibling_path == NULL)
+    {
+      private->sibling_path = gtk_widget_path_new ();
+      /* forall iterates in visible order */
+      gtk_container_forall (container,
+                            add_widget_to_path,
+                            private->sibling_path);
+    }
+
+  path = gtk_widget_path_copy (gtk_widget_get_path (GTK_WIDGET (container)));
+  if (gtk_widget_get_visible (child))
+    gtk_widget_path_append_with_siblings (path,
+                                          private->sibling_path,
+                                          gtk_box_get_visible_position (box,
+                                                                        child));
+  else
+    gtk_widget_path_append_for_widget (path, child);
+
+  return path;
+}
+
+static void
+gtk_box_invalidate_order (GtkBox *box)
+{
+  GtkBoxPrivate *private = box->priv;
+
+  if (private->sibling_path != NULL)
+    {
+      gtk_widget_path_unref (private->sibling_path);
+      private->sibling_path = NULL;
+    }
+
+  gtk_container_foreach (GTK_CONTAINER (box),
+                         (GtkCallback) gtk_widget_reset_style,
+                         NULL);
+}
+
 static void
 gtk_box_pack (GtkBox      *box,
               GtkWidget   *child,
@@ -857,6 +969,7 @@ gtk_box_pack (GtkBox      *box,
 
   gtk_widget_freeze_child_notify (child);
 
+  gtk_box_invalidate_order (box);
   gtk_widget_set_parent (child, GTK_WIDGET (box));
 
   gtk_widget_child_notify (child, "expand");
@@ -1495,7 +1608,10 @@ gtk_box_reorder_child (GtkBox    *box,
   gtk_widget_child_notify (child, "position");
   if (gtk_widget_get_visible (child)
       && gtk_widget_get_visible (GTK_WIDGET (box)))
-    gtk_widget_queue_resize (child);
+    {
+      gtk_box_invalidate_order (box);
+      gtk_widget_queue_resize (child);
+    }
 }
 
 /**
@@ -1614,10 +1730,11 @@ gtk_box_set_child_packing (GtkBox      *box,
       gtk_widget_child_notify (child, "padding");
       if (pack_type != GTK_PACK_END)
         pack_type = GTK_PACK_START;
-      if (child_info->pack_type != pack_type)
+      if (child_info->pack != pack_type)
         {
 	  child_info->pack = GTK_PACK_END;
           gtk_widget_child_notify (child, "pack-type");
+          gtk_box_invalidate_order (box);
         }
 
       if (gtk_widget_get_visible (child)
@@ -1680,7 +1797,10 @@ gtk_box_remove (GtkContainer *container,
 	   * since that's what is needed by toplevels.
 	   */
 	  if (was_visible)
-	    gtk_widget_queue_resize (GTK_WIDGET (container));
+            {
+              gtk_box_invalidate_order (box);
+	      gtk_widget_queue_resize (GTK_WIDGET (container));
+            }
 
 	  break;
 	}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]