[egg-list-box/flow-box-enhancements: 3/3] Add sorting to EggFlowBox



commit 79f142ed577a5262e90a56f984e5ee8ac96e8fbb
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Sep 22 13:27:36 2013 -0400

    Add sorting to EggFlowBox
    
    This is pretty much a 1-1 copy of the sorting functionality
    in GtkListBox.

 egg-flow-box.c  |  112 ++++++++++++++++++++++++++++++++++++++++++++++---------
 egg-flow-box.h  |   17 ++++++--
 test-flow-box.c |   37 ++++++++++++++++++-
 3 files changed, 143 insertions(+), 23 deletions(-)
---
diff --git a/egg-flow-box.c b/egg-flow-box.c
index 14036cb..8c7abef 100644
--- a/egg-flow-box.c
+++ b/egg-flow-box.c
@@ -142,6 +142,10 @@ struct _EggFlowBoxPrivate {
   EggFlowBoxFilterFunc filter_func;
   gpointer             filter_data;
   GDestroyNotify       filter_destroy;
+
+  EggFlowBoxSortFunc sort_func;
+  gpointer           sort_data;
+  GDestroyNotify     sort_destroy;
 };
 
 typedef struct _EggFlowBoxChildPrivate EggFlowBoxChildPrivate;
@@ -181,6 +185,9 @@ static void egg_flow_box_update_selection    (EggFlowBox      *box,
                                               gboolean         extend);
 static void egg_flow_box_apply_filter        (EggFlowBox      *box,
                                               EggFlowBoxChild *child);
+static gint egg_flow_box_sort                (EggFlowBoxChild *a,
+                                              EggFlowBoxChild *b,
+                                              EggFlowBox      *box);
 
 
 static void
@@ -497,19 +504,6 @@ egg_flow_box_child_get_index (EggFlowBoxChild *child)
 }
 
 void
-egg_flow_box_child_changed (EggFlowBoxChild *child)
-{
-  EggFlowBox *box;
-
-  box = egg_flow_box_child_get_box (child);
-
-  if (box != NULL)
-    {
-      egg_flow_box_apply_filter (box, child);
-    }
-}
-
-void
 egg_flow_box_set_adjustment (EggFlowBox    *box,
                              GtkAdjustment *adjustment)
 {
@@ -1306,7 +1300,11 @@ egg_flow_box_add (GtkContainer *container,
       gtk_container_add (GTK_CONTAINER (info), child);
     }
 
-  iter = g_sequence_append (priv->children, info);
+  if (priv->sort_func != NULL)
+    iter = g_sequence_insert_sorted (priv->children, info,
+                                     (GCompareDataFunc)egg_flow_box_sort, box);
+  else
+    iter = g_sequence_append (priv->children, info);
 
   child_priv = egg_flow_box_child_get_instance_private (info);
   child_priv->iter = iter;
@@ -3482,8 +3480,13 @@ egg_flow_box_realize (GtkWidget *widget)
 static void
 egg_flow_box_finalize (GObject *obj)
 {
-  EggFlowBox *flow_box = EGG_FLOW_BOX (obj);
-  EggFlowBoxPrivate *priv = flow_box->priv;
+  EggFlowBox *box = EGG_FLOW_BOX (obj);
+  EggFlowBoxPrivate *priv = box->priv;
+
+  if (priv->filter_destroy != NULL)
+    priv->filter_destroy (priv->filter_data);
+  if (priv->sort_destroy != NULL)
+    priv->sort_destroy (priv->sort_data);
 
   g_sequence_free (priv->children);
   g_clear_object (&priv->adjustment);
@@ -3981,8 +3984,7 @@ egg_flow_box_set_filter_func (EggFlowBox           *box,
   priv->filter_data = user_data;
   priv->filter_destroy = destroy;
 
-  egg_flow_box_apply_filter_all (box);
-  gtk_widget_queue_resize (GTK_WIDGET (box));
+  egg_flow_box_invalidate_filter (box);
 }
 
 void
@@ -3993,3 +3995,77 @@ egg_flow_box_invalidate_filter (EggFlowBox *box)
   egg_flow_box_apply_filter_all (box);
   gtk_widget_queue_resize (GTK_WIDGET (box));
 }
+
+void
+egg_flow_box_set_sort_func (EggFlowBox         *box,
+                            EggFlowBoxSortFunc  sort_func,
+                            gpointer            user_data,
+                            GDestroyNotify      destroy)
+{
+  EggFlowBoxPrivate *priv;
+
+  g_return_if_fail (EGG_IS_FLOW_BOX (box));
+
+  priv = box->priv;
+
+  if (priv->sort_destroy != NULL)
+    priv->sort_destroy (priv->sort_data);
+
+  priv->sort_func = sort_func;
+  priv->sort_data = user_data;
+  priv->sort_destroy = destroy;
+
+  egg_flow_box_invalidate_sort (box);
+}
+
+static gint
+egg_flow_box_sort (EggFlowBoxChild *a,
+                   EggFlowBoxChild *b,
+                   EggFlowBox      *box)
+{
+  EggFlowBoxPrivate *priv = box->priv;
+
+  return priv->sort_func (a, b, priv->sort_data);
+}
+
+void
+egg_flow_box_invalidate_sort (EggFlowBox *box)
+{
+  EggFlowBoxPrivate *priv;
+
+  g_return_if_fail (EGG_IS_FLOW_BOX (box));
+
+  priv = box->priv;
+
+  if (priv->sort_func != NULL)
+    {
+      g_sequence_sort (priv->children,
+                       (GCompareDataFunc)egg_flow_box_sort, box);
+      gtk_widget_queue_resize (GTK_WIDGET (box));
+    }
+}
+
+void
+egg_flow_box_child_changed (EggFlowBoxChild *child)
+{
+  EggFlowBox *box;
+  EggFlowBoxPrivate *priv;
+  EggFlowBoxChildPrivate *child_priv;
+
+  child_priv = egg_flow_box_child_get_instance_private (child);
+  box = egg_flow_box_child_get_box (child);
+  priv = box->priv;
+
+  if (box == NULL)
+    return;
+
+  if (priv->sort_func != NULL)
+    {
+      g_sequence_sort_changed (child_priv->iter,
+                               (GCompareDataFunc)egg_flow_box_sort, box);
+      gtk_widget_queue_resize (GTK_WIDGET (box));
+    }
+
+  egg_flow_box_apply_filter (box, child);
+}
+
diff --git a/egg-flow-box.h b/egg-flow-box.h
index 68af5c7..56b03d8 100644
--- a/egg-flow-box.h
+++ b/egg-flow-box.h
@@ -114,10 +114,6 @@ struct _EggFlowBoxChildClass
   void (*_gtk_reserved2) (void);
 };
 
-typedef gboolean (*EggFlowBoxFilterFunc) (EggFlowBoxChild *child,
-                                          gpointer         user_data);
-
-
 GType                 egg_flow_box_child_get_type            (void) G_GNUC_CONST;
 GtkWidget*            egg_flow_box_child_new                 (void);
 gint                  egg_flow_box_child_get_index           (EggFlowBoxChild *child);
@@ -175,12 +171,25 @@ void                  egg_flow_box_set_selection_mode           (EggFlowBox
 void                  egg_flow_box_set_adjustment               (EggFlowBox        *box,
                                                                  GtkAdjustment     *adjustment);
 
+typedef gboolean (*EggFlowBoxFilterFunc) (EggFlowBoxChild *child,
+                                          gpointer         user_data);
+
 void                  egg_flow_box_set_filter_func              (EggFlowBox        *box,
                                                                  EggFlowBoxFilterFunc filter_func,
                                                                  gpointer             user_data,
                                                                  GDestroyNotify       destroy);
 void                  egg_flow_box_invalidate_filter            (EggFlowBox        *box);
 
+typedef gint (*EggFlowBoxSortFunc) (EggFlowBoxChild *child1,
+                                    EggFlowBoxChild *child2,
+                                    gpointer         user_data);
+
+void                  egg_flow_box_set_sort_func                (EggFlowBox        *box,
+                                                                 EggFlowBoxSortFunc  sort_func,
+                                                                 gpointer            user_data,
+                                                                 GDestroyNotify      destroy);
+void                  egg_flow_box_invalidate_sort              (EggFlowBox         *box);
+
 G_END_DECLS
 
 
diff --git a/test-flow-box.c b/test-flow-box.c
index 9061892..cbe5b5b 100644
--- a/test-flow-box.c
+++ b/test-flow-box.c
@@ -328,6 +328,29 @@ filter_toggled (GtkToggleButton *button,
     egg_flow_box_set_filter_func (flowbox, NULL, NULL, NULL);
 }
 
+static gint
+sort_func (EggFlowBoxChild *a,
+           EggFlowBoxChild *b,
+           gpointer         data)
+{
+  gchar *ida, *idb;
+
+  ida = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (a))), "id");
+  idb = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (b))), "id");
+  return g_strcmp0 (ida, idb);
+}
+
+static void
+sort_toggled (GtkToggleButton *button,
+              EggFlowBox      *flowbox)
+{
+  gboolean state = gtk_toggle_button_get_active (button);
+
+  if (state)
+    egg_flow_box_set_sort_func (flowbox, sort_func, NULL, NULL);
+  else
+    egg_flow_box_set_sort_func (flowbox, NULL, NULL, NULL);
+}
 
 static GtkWidget *
 create_window (void)
@@ -521,6 +544,10 @@ create_window (void)
   g_signal_connect (G_OBJECT (widget), "value-changed",
                     G_CALLBACK (spacing_changed), GINT_TO_POINTER (GTK_ORIENTATION_VERTICAL));
 
+  gtk_box_pack_start (GTK_BOX (flowbox_cntl), hbox, FALSE, FALSE, 0);
+
+  /* filtering and sorting */
+
   widget = gtk_check_button_new_with_label ("Filter");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
   gtk_widget_show (widget);
@@ -531,7 +558,15 @@ create_window (void)
   g_signal_connect (G_OBJECT (widget), "toggled",
                     G_CALLBACK (filter_toggled), flowbox);
 
-  gtk_box_pack_start (GTK_BOX (flowbox_cntl), hbox, FALSE, FALSE, 0);
+  widget = gtk_check_button_new_with_label ("Sort");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+  gtk_widget_show (widget);
+
+  gtk_widget_set_tooltip_text (widget, "Set whether items should be sorted");
+  gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
+
+  g_signal_connect (G_OBJECT (widget), "toggled",
+                    G_CALLBACK (sort_toggled), flowbox);
 
 
   /* Add test items control frame */


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