[libgd] Implemented gd_stack_reorder_child



commit 42e48be3b7cc5c4a21b684f92628c28c4445f3b7
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Fri Mar 1 18:34:33 2013 +0100

    Implemented gd_stack_reorder_child
    
    This is similar to the reordering API of GtkBox and GtkNotebook.
    GdStackSwitcher reorders its buttons accordingly.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694945

 libgd/gd-stack-switcher.c |   18 ++++++++++
 libgd/gd-stack.c          |   84 ++++++++++++++++++++++++++++++++++++++++++++-
 libgd/gd-stack.h          |    2 -
 3 files changed, 101 insertions(+), 3 deletions(-)
---
diff --git a/libgd/gd-stack-switcher.c b/libgd/gd-stack-switcher.c
index 34f9885..d006254 100644
--- a/libgd/gd-stack-switcher.c
+++ b/libgd/gd-stack-switcher.c
@@ -145,6 +145,23 @@ on_title_icon_updated (GtkWidget       *widget,
 }
 
 static void
+on_position_updated (GtkWidget       *widget,
+                     GParamSpec      *pspec,
+                     GdStackSwitcher *self)
+{
+  GtkWidget *button;
+  gint position;
+
+  button = g_hash_table_lookup (self->priv->buttons, widget);
+
+  gtk_container_child_get (GTK_CONTAINER (self->priv->stack), widget,
+                          "position", &position,
+                          NULL);
+
+  gtk_box_reorder_child (GTK_BOX (self), button, position);
+}
+
+static void
 add_child (GdStackSwitcher *self,
            GtkWidget       *widget)
 {
@@ -175,6 +192,7 @@ add_child (GdStackSwitcher *self,
   g_signal_connect (button, "clicked", G_CALLBACK (on_button_clicked), self);
   g_signal_connect (widget, "child-notify::title", G_CALLBACK (on_title_icon_updated), self);
   g_signal_connect (widget, "child-notify::symbolic-icon-name", G_CALLBACK (on_title_icon_updated), self);
+  g_signal_connect (widget, "child-notify::position", G_CALLBACK (on_position_updated), self);
 
   g_hash_table_insert (self->priv->buttons, widget, button);
 }
diff --git a/libgd/gd-stack.c b/libgd/gd-stack.c
index f56f63a..7c57684 100644
--- a/libgd/gd-stack.c
+++ b/libgd/gd-stack.c
@@ -47,7 +47,8 @@ enum
   CHILD_PROP_0,
   CHILD_PROP_NAME,
   CHILD_PROP_TITLE,
-  CHILD_PROP_SYMBOLIC_ICON_NAME
+  CHILD_PROP_SYMBOLIC_ICON_NAME,
+  CHILD_PROP_POSITION
 };
 
 typedef struct _GdStackChildInfo GdStackChildInfo;
@@ -379,6 +380,13 @@ gd_stack_class_init (GdStackClass * klass)
                          NULL,
                          GTK_PARAM_READWRITE));
 
+  gtk_container_class_install_child_property (container_class, CHILD_PROP_POSITION,
+    g_param_spec_int ("position",
+                      "Position",
+                      "The index of the child in the parent",
+                      -1, G_MAXINT, 0,
+                      GTK_PARAM_READWRITE));
+
   g_type_class_add_private (klass, sizeof (GdStackPrivate));
 }
 
@@ -408,6 +416,61 @@ find_child_info_for_widget (GdStack *stack,
 }
 
 static void
+reorder_child (GdStack   *stack,
+               GtkWidget *child,
+               gint       position)
+{
+  GdStackPrivate *priv;
+  GList *l;
+  GList *old_link = NULL;
+  GList *new_link = NULL;
+  GdStackChildInfo *child_info;
+  gint num = 0;
+
+  priv = stack->priv;
+
+  l = priv->children;
+
+  /* Loop to find the old position and link of child, new link of child and
+   * total number of children. new_link will be NULL if the child should be
+   * moved to the end (in case of position being < 0 || >= num)
+   */
+  while (l && (new_link == NULL || old_link == NULL))
+    {
+      /* Record the new position if found */
+      if (position == num)
+        new_link = l;
+
+      if (old_link == NULL)
+        {
+          GdStackChildInfo *info;
+          info = l->data;
+
+          /* Keep trying to find the current position and link location of the
+             child */
+          if (info->widget == child)
+            {
+              old_link = l;
+              child_info = info;
+            }
+        }
+
+      l = g_list_next (l);
+      num++;
+    }
+
+  g_return_if_fail (old_link != NULL);
+
+  if (old_link == new_link || (g_list_next (old_link) == NULL && new_link == NULL))
+    return;
+
+  priv->children = g_list_delete_link (priv->children, old_link);
+  priv->children = g_list_insert_before (priv->children, new_link, child_info);
+
+  gtk_widget_child_notify (child, "position");
+}
+
+static void
 gd_stack_get_child_property (GtkContainer *container,
                              GtkWidget    *child,
                              guint         property_id,
@@ -416,6 +479,8 @@ gd_stack_get_child_property (GtkContainer *container,
 {
   GdStack *stack = GD_STACK (container);
   GdStackChildInfo *info;
+  GList *list;
+  guint i;
 
   info = find_child_info_for_widget (stack, child);
   if (info == NULL)
@@ -438,6 +503,17 @@ gd_stack_get_child_property (GtkContainer *container,
       g_value_set_string (value, info->symbolic_icon_name);
       break;
 
+    case CHILD_PROP_POSITION:
+      i = 0;
+      for (list = stack->priv->children; list != NULL; list = g_list_next (list))
+        {
+          if (info == list->data)
+            break;
+          ++i;
+        }
+      g_value_set_int (value, i);
+      break;
+
     default:
       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
       break;
@@ -487,6 +563,10 @@ gd_stack_set_child_property (GtkContainer *container,
       gtk_container_child_notify (container, child, "symbolic-icon-name");
       break;
 
+    case CHILD_PROP_POSITION:
+      reorder_child (stack, child, g_value_get_int (value));
+      break;
+
     default:
       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
       break;
@@ -776,6 +856,8 @@ gd_stack_add (GtkContainer *container,
   g_signal_connect (child, "notify::visible",
                     G_CALLBACK (stack_child_visibility_notify_cb), stack);
 
+  gtk_widget_child_notify (child, "position");
+
   if (priv->visible_child == NULL &&
       gtk_widget_get_visible (child))
     set_visible_child (stack, child_info);
diff --git a/libgd/gd-stack.h b/libgd/gd-stack.h
index 49d3fe5..0754455 100644
--- a/libgd/gd-stack.h
+++ b/libgd/gd-stack.h
@@ -80,8 +80,6 @@ void                  gd_stack_set_transition_type     (GdStack               *s
                                                        GdStackTransitionType  type);
 GdStackTransitionType gd_stack_get_transition_type     (GdStack               *stack);
 
-
-
 G_END_DECLS
 
 #endif


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