[egg-list-box/flow-box-enhancements: 2/3] Add filtering to EggFlowBox
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [egg-list-box/flow-box-enhancements: 2/3] Add filtering to EggFlowBox
- Date: Sun, 22 Sep 2013 17:31:40 +0000 (UTC)
commit c21272bcf116a7f5e091b9bdc2071add506f4b3f
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Sep 22 12:49:51 2013 -0400
Add filtering to EggFlowBox
This is pretty much a 1-1 copy of the filtering functionality
in GtkListBox.
egg-flow-box.c | 160 +++++++++++++++++++++++++++++++++++++++----------------
egg-flow-box.h | 10 ++++
test-flow-box.c | 37 ++++++++++++-
3 files changed, 158 insertions(+), 49 deletions(-)
---
diff --git a/egg-flow-box.c b/egg-flow-box.c
index fa295e8..14036cb 100644
--- a/egg-flow-box.c
+++ b/egg-flow-box.c
@@ -138,15 +138,18 @@ struct _EggFlowBoxPrivate {
guint16 cur_children_per_line;
GSequence *children;
+
+ EggFlowBoxFilterFunc filter_func;
+ gpointer filter_data;
+ GDestroyNotify filter_destroy;
};
typedef struct _EggFlowBoxChildPrivate EggFlowBoxChildPrivate;
struct _EggFlowBoxChildPrivate
{
GSequenceIter *iter;
- GtkWidget *widget;
- guint selected : 1;
GdkRectangle area;
+ guint selected : 1;
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -167,6 +170,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (EggFlowBoxChild, egg_flow_box_child, GTK_TYPE_BIN)
((EggFlowBox *)(box))->priv->valign_policy : \
((EggFlowBox *)(box))->priv->halign_policy)
+
static void egg_flow_box_update_cursor (EggFlowBox *box,
EggFlowBoxChild *child);
static void egg_flow_box_select_and_activate (EggFlowBox *box,
@@ -175,12 +179,9 @@ static void egg_flow_box_update_selection (EggFlowBox *box,
EggFlowBoxChild *child,
gboolean modify,
gboolean extend);
+static void egg_flow_box_apply_filter (EggFlowBox *box,
+ EggFlowBoxChild *child);
-GtkWidget *
-egg_flow_box_child_new (void)
-{
- return g_object_new (EGG_TYPE_FLOW_BOX_CHILD, NULL);
-}
static void
egg_flow_box_child_init (EggFlowBoxChild *child)
@@ -292,38 +293,6 @@ egg_flow_box_child_activate (EggFlowBoxChild *child)
egg_flow_box_select_and_activate (box, child);
}
-static void
-egg_flow_box_child_visibility_changed (EggFlowBox *box,
- EggFlowBoxChild *child)
-{
-}
-
-static void
-egg_flow_box_child_show (GtkWidget *widget)
-{
- EggFlowBoxChild *child = EGG_FLOW_BOX_CHILD (widget);
- EggFlowBox *box;
-
- GTK_WIDGET_CLASS (egg_flow_box_child_parent_class)->show (widget);
-
- box = egg_flow_box_child_get_box (child);
- if (box)
- egg_flow_box_child_visibility_changed (box, child);
-}
-
-static void
-egg_flow_box_child_hide (GtkWidget *widget)
-{
- EggFlowBoxChild *child = EGG_FLOW_BOX_CHILD (widget);
- EggFlowBox *box;
-
- GTK_WIDGET_CLASS (egg_flow_box_child_parent_class)->hide (widget);
-
- box = egg_flow_box_child_get_box (child);
- if (box)
- egg_flow_box_child_visibility_changed (box, child);
-}
-
static gboolean
egg_flow_box_child_draw (GtkWidget *widget,
cairo_t *cr)
@@ -483,8 +452,6 @@ egg_flow_box_child_class_init (EggFlowBoxChildClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
- widget_class->show = egg_flow_box_child_show;
- widget_class->hide = egg_flow_box_child_hide;
widget_class->draw = egg_flow_box_child_draw;
widget_class->get_preferred_height = egg_flow_box_child_get_preferred_height;
widget_class->get_preferred_height_for_width = egg_flow_box_child_get_preferred_height_for_width;
@@ -508,6 +475,40 @@ egg_flow_box_child_class_init (EggFlowBoxChildClass *class)
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_LIST_ITEM);
}
+GtkWidget *
+egg_flow_box_child_new (void)
+{
+ return g_object_new (EGG_TYPE_FLOW_BOX_CHILD, NULL);
+}
+
+gint
+egg_flow_box_child_get_index (EggFlowBoxChild *child)
+{
+ EggFlowBoxChildPrivate *priv;
+
+ g_return_val_if_fail (EGG_IS_FLOW_BOX_CHILD (child), -1);
+
+ priv = egg_flow_box_child_get_instance_private (child);
+
+ if (priv->iter != NULL)
+ return g_sequence_iter_get_position (priv->iter);
+
+ return -1;
+}
+
+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)
@@ -719,7 +720,7 @@ get_largest_size_for_line_in_opposing_orientation (EggFlowBox *box,
child = g_sequence_get (iter);
- if (!gtk_widget_is_visible (child))
+ if (!child_is_visible (child))
continue;
/* Distribute the extra pixels to the first children in the line
@@ -775,7 +776,7 @@ gather_aligned_item_requests (EggFlowBox *box,
i = 0;
for (iter = g_sequence_get_begin_iter (priv->children);
!g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter), i++)
+ iter = g_sequence_iter_next (iter))
{
GtkWidget *child;
GtkAlign item_align;
@@ -804,6 +805,8 @@ gather_aligned_item_requests (EggFlowBox *box,
/* Round up the size of every column/row */
item_sizes[position].minimum_size = MAX (item_sizes[position].minimum_size, child_min);
item_sizes[position].natural_size = MAX (item_sizes[position].natural_size, child_nat);
+
+ i++;
}
for (i = 0; i < line_length; i++)
@@ -848,8 +851,8 @@ fit_aligned_item_requests (EggFlowBox *box,
n_children,
try_sizes);
- if (try_line_size <= avail_size
- && items_per_line >= try_length)
+ if (try_line_size <= avail_size &&
+ items_per_line >= try_length)
{
*line_length = try_length;
@@ -1130,7 +1133,7 @@ egg_flow_box_size_allocate (GtkWidget *widget,
this_line_size = line_size;
else
{
- this_line_size = line_sizes[0].minimum_size;
+ this_line_size = line_sizes[0].minimum_size;
if (line_align == GTK_ALIGN_FILL)
{
@@ -1308,7 +1311,7 @@ egg_flow_box_add (GtkContainer *container,
child_priv = egg_flow_box_child_get_instance_private (info);
child_priv->iter = iter;
gtk_widget_set_parent (GTK_WIDGET (info), GTK_WIDGET (box));
- gtk_widget_set_child_visible (GTK_WIDGET (info), TRUE);
+ egg_flow_box_apply_filter (box, info);
}
static void
@@ -3927,3 +3930,66 @@ egg_flow_box_get_selection_mode (EggFlowBox *box)
return box->priv->selection_mode;
}
+
+static void
+egg_flow_box_apply_filter (EggFlowBox *box,
+ EggFlowBoxChild *child)
+{
+ EggFlowBoxPrivate *priv = box->priv;
+ gboolean do_show;
+
+ do_show = TRUE;
+ if (priv->filter_func != NULL)
+ do_show = priv->filter_func (child, priv->filter_data);
+
+ gtk_widget_set_child_visible (GTK_WIDGET (child), do_show);
+}
+
+static void
+egg_flow_box_apply_filter_all (EggFlowBox *box)
+{
+ EggFlowBoxPrivate *priv = box->priv;
+ EggFlowBoxChild *child;
+ GSequenceIter *iter;
+
+ for (iter = g_sequence_get_begin_iter (priv->children);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter))
+ {
+ child = g_sequence_get (iter);
+ egg_flow_box_apply_filter (box, child);
+ }
+
+}
+
+void
+egg_flow_box_set_filter_func (EggFlowBox *box,
+ EggFlowBoxFilterFunc filter_func,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ EggFlowBoxPrivate *priv;
+
+ g_return_if_fail (EGG_IS_FLOW_BOX (box));
+
+ priv = box->priv;
+
+ if (priv->filter_destroy != NULL)
+ priv->filter_destroy (priv->filter_data);
+
+ priv->filter_func = filter_func;
+ priv->filter_data = user_data;
+ priv->filter_destroy = destroy;
+
+ egg_flow_box_apply_filter_all (box);
+ gtk_widget_queue_resize (GTK_WIDGET (box));
+}
+
+void
+egg_flow_box_invalidate_filter (EggFlowBox *box)
+{
+ g_return_if_fail (EGG_IS_FLOW_BOX (box));
+
+ egg_flow_box_apply_filter_all (box);
+ gtk_widget_queue_resize (GTK_WIDGET (box));
+}
diff --git a/egg-flow-box.h b/egg-flow-box.h
index d85b147..68af5c7 100644
--- a/egg-flow-box.h
+++ b/egg-flow-box.h
@@ -114,6 +114,10 @@ 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);
@@ -171,6 +175,12 @@ void egg_flow_box_set_selection_mode (EggFlowBox
void egg_flow_box_set_adjustment (EggFlowBox *box,
GtkAdjustment *adjustment);
+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);
+
G_END_DECLS
diff --git a/test-flow-box.c b/test-flow-box.c
index 42f714c..9061892 100644
--- a/test-flow-box.c
+++ b/test-flow-box.c
@@ -33,7 +33,7 @@ enum {
#define INITIAL_MAXIMUM_LENGTH 6
#define INITIAL_CSPACING 2
#define INITIAL_RSPACING 2
-#define N_ITEMS 4000
+#define N_ITEMS 1000
static EggFlowBox *the_flowbox = NULL;
static gint items_type = SIMPLE_ITEMS;
@@ -303,9 +303,32 @@ static void
on_selected_children_changed (EggFlowBox *self)
{
g_message ("Selection changed");
- egg_flow_box_selected_foreach (self, selection_foreach, NULL);
+ //egg_flow_box_selected_foreach (self, selection_foreach, NULL);
}
+static gboolean
+filter_func (EggFlowBoxChild *child, gpointer user_data)
+{
+ gint index;
+
+ index = egg_flow_box_child_get_index (child);
+
+ return (index % 3) == 0;
+}
+
+static void
+filter_toggled (GtkToggleButton *button,
+ EggFlowBox *flowbox)
+{
+ gboolean state = gtk_toggle_button_get_active (button);
+
+ if (state)
+ egg_flow_box_set_filter_func (flowbox, filter_func, NULL, NULL);
+ else
+ egg_flow_box_set_filter_func (flowbox, NULL, NULL, NULL);
+}
+
+
static GtkWidget *
create_window (void)
{
@@ -498,6 +521,16 @@ create_window (void)
g_signal_connect (G_OBJECT (widget), "value-changed",
G_CALLBACK (spacing_changed), GINT_TO_POINTER (GTK_ORIENTATION_VERTICAL));
+ widget = gtk_check_button_new_with_label ("Filter");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+ gtk_widget_show (widget);
+
+ gtk_widget_set_tooltip_text (widget, "Set whether some items should be filtered out");
+ gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
+
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ G_CALLBACK (filter_toggled), flowbox);
+
gtk_box_pack_start (GTK_BOX (flowbox_cntl), hbox, FALSE, FALSE, 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]