[libdazzle] tree: add build-children vfunc for tree builders
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdazzle] tree: add build-children vfunc for tree builders
- Date: Sat, 9 Dec 2017 09:37:54 +0000 (UTC)
commit a05d323871c8108e97cd65a7152ce7321d8db323
Author: Christian Hergert <chergert redhat com>
Date: Sat Dec 9 01:26:13 2017 -0800
tree: add build-children vfunc for tree builders
This separates build-node from build-children. This allows
builders that just add new information to a node vs builders
that add new children to the builders (when we expand them).
src/tree/dzl-tree-builder.c | 25 ++++++++++++
src/tree/dzl-tree-builder.h | 3 +
src/tree/dzl-tree-node.c | 24 ++++++------
src/tree/dzl-tree-private.h | 10 +++-
src/tree/dzl-tree.c | 91 ++++++++++++++++++++++++++++++-------------
tests/test-tree.c | 6 +-
6 files changed, 114 insertions(+), 45 deletions(-)
---
diff --git a/src/tree/dzl-tree-builder.c b/src/tree/dzl-tree-builder.c
index c26fc64..95c9ced 100644
--- a/src/tree/dzl-tree-builder.c
+++ b/src/tree/dzl-tree-builder.c
@@ -42,6 +42,7 @@ enum {
enum {
ADDED,
REMOVED,
+ BUILD_CHILDREN,
BUILD_NODE,
DRAG_DATA_GET,
DRAG_DATA_RECEIVED,
@@ -108,6 +109,16 @@ _dzl_tree_builder_node_unselected (DzlTreeBuilder *builder,
}
void
+_dzl_tree_builder_build_children (DzlTreeBuilder *builder,
+ DzlTreeNode *node)
+{
+ g_return_if_fail (DZL_IS_TREE_BUILDER (builder));
+ g_return_if_fail (DZL_IS_TREE_NODE (node));
+
+ g_signal_emit (builder, signals [BUILD_CHILDREN], 0, node);
+}
+
+void
_dzl_tree_builder_build_node (DzlTreeBuilder *builder,
DzlTreeNode *node)
{
@@ -367,6 +378,20 @@ dzl_tree_builder_class_init (DzlTreeBuilderClass *klass)
G_TYPE_FROM_CLASS (klass),
g_cclosure_marshal_VOID__OBJECTv);
+ signals [BUILD_CHILDREN] =
+ g_signal_new ("build-children",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DzlTreeBuilderClass, build_children),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ DZL_TYPE_TREE_NODE);
+ g_signal_set_va_marshaller (signals [BUILD_CHILDREN],
+ G_TYPE_FROM_CLASS (klass),
+ g_cclosure_marshal_VOID__OBJECTv);
+
signals [DRAG_NODE_RECEIVED] =
g_signal_new ("drag-node-received",
G_TYPE_FROM_CLASS (klass),
diff --git a/src/tree/dzl-tree-builder.h b/src/tree/dzl-tree-builder.h
index a2904a6..2bfba3b 100644
--- a/src/tree/dzl-tree-builder.h
+++ b/src/tree/dzl-tree-builder.h
@@ -38,6 +38,8 @@ struct _DzlTreeBuilderClass
GtkWidget *tree);
void (*build_node) (DzlTreeBuilder *builder,
DzlTreeNode *node);
+ void (*build_children) (DzlTreeBuilder *builder,
+ DzlTreeNode *parent);
gboolean (*node_activated) (DzlTreeBuilder *builder,
DzlTreeNode *node);
void (*node_selected) (DzlTreeBuilder *builder,
@@ -79,6 +81,7 @@ struct _DzlTreeBuilderClass
DZL_AVAILABLE_IN_ALL
DzlTree *dzl_tree_builder_get_tree (DzlTreeBuilder *builder);
+
DZL_AVAILABLE_IN_3_28
DzlTreeBuilder *dzl_tree_builder_new (void);
diff --git a/src/tree/dzl-tree-node.c b/src/tree/dzl-tree-node.c
index 05b357e..832720d 100644
--- a/src/tree/dzl-tree-node.c
+++ b/src/tree/dzl-tree-node.c
@@ -41,7 +41,7 @@ struct _DzlTreeNode
GQuark expanded_icon_name;
guint use_markup : 1;
- guint needs_build : 1;
+ guint needs_build_children : 1;
guint is_dummy : 1;
guint children_possible : 1;
guint use_dim_label : 1;
@@ -949,7 +949,7 @@ dzl_tree_node_class_init (DzlTreeNodeClass *klass)
static void
dzl_tree_node_init (DzlTreeNode *node)
{
- node->needs_build = TRUE;
+ node->needs_build_children = TRUE;
}
static gboolean
@@ -1073,22 +1073,22 @@ _dzl_tree_node_is_dummy (DzlTreeNode *self)
}
gboolean
-_dzl_tree_node_get_needs_build (DzlTreeNode *self)
+_dzl_tree_node_get_needs_build_children (DzlTreeNode *self)
{
g_assert (DZL_IS_TREE_NODE (self));
- return self->needs_build;
+ return self->needs_build_children;
}
void
-_dzl_tree_node_set_needs_build (DzlTreeNode *self,
- gboolean needs_build)
+_dzl_tree_node_set_needs_build_children (DzlTreeNode *self,
+ gboolean needs_build_children)
{
g_assert (DZL_IS_TREE_NODE (self));
- self->needs_build = !!needs_build;
+ self->needs_build_children = !!needs_build_children;
- if (!needs_build)
+ if (!needs_build_children)
self->is_dummy = FALSE;
}
@@ -1155,7 +1155,7 @@ dzl_tree_node_get_children_possible (DzlTreeNode *self)
*/
void
dzl_tree_node_set_children_possible (DzlTreeNode *self,
- gboolean children_possible)
+ gboolean children_possible)
{
g_return_if_fail (DZL_IS_TREE_NODE (self));
@@ -1165,7 +1165,7 @@ dzl_tree_node_set_children_possible (DzlTreeNode *self,
{
self->children_possible = children_possible;
- if (self->tree && self->needs_build)
+ if (self->tree != NULL && self->needs_build_children)
{
if (self->children_possible)
_dzl_tree_node_add_dummy_child (self);
@@ -1242,7 +1242,7 @@ dzl_tree_node_n_children (DzlTreeNode *self)
{
g_return_val_if_fail (DZL_IS_TREE_NODE (self), 0);
- if (!self->needs_build && self->tree != NULL)
+ if (!self->needs_build_children && self->tree != NULL)
{
GtkTreeIter iter;
GtkTreeModel *model;
@@ -1270,7 +1270,7 @@ dzl_tree_node_nth_child (DzlTreeNode *self,
guint nth)
{
g_return_val_if_fail (DZL_IS_TREE_NODE (self), NULL);
- g_return_val_if_fail (!self->needs_build, NULL);
+ g_return_val_if_fail (!self->needs_build_children, NULL);
if (self->tree != NULL)
{
diff --git a/src/tree/dzl-tree-private.h b/src/tree/dzl-tree-private.h
index ed988fe..169d488 100644
--- a/src/tree/dzl-tree-private.h
+++ b/src/tree/dzl-tree-private.h
@@ -27,6 +27,8 @@ void _dzl_tree_invalidate (DzlTree
DzlTreeNode *node);
GtkTreePath *_dzl_tree_get_path (DzlTree *tree,
GList *list);
+void _dzl_tree_build_children (DzlTree *self,
+ DzlTreeNode *node);
void _dzl_tree_build_node (DzlTree *self,
DzlTreeNode *node);
void _dzl_tree_append (DzlTree *self,
@@ -55,9 +57,9 @@ void _dzl_tree_node_set_tree (DzlTreeNode
void _dzl_tree_node_set_parent (DzlTreeNode *node,
DzlTreeNode *parent);
const gchar *_dzl_tree_node_get_expanded_icon (DzlTreeNode *node);
-gboolean _dzl_tree_node_get_needs_build (DzlTreeNode *node);
-void _dzl_tree_node_set_needs_build (DzlTreeNode *node,
- gboolean needs_build);
+gboolean _dzl_tree_node_get_needs_build_children (DzlTreeNode *node);
+void _dzl_tree_node_set_needs_build_children (DzlTreeNode *node,
+ gboolean needs_build_children);
void _dzl_tree_node_add_dummy_child (DzlTreeNode *node);
void _dzl_tree_node_remove_dummy_child (DzlTreeNode *node);
gboolean _dzl_tree_node_is_dummy (DzlTreeNode *self);
@@ -69,6 +71,8 @@ void _dzl_tree_builder_removed (DzlTreeBuilder
DzlTree *tree);
void _dzl_tree_builder_build_node (DzlTreeBuilder *builder,
DzlTreeNode *node);
+void _dzl_tree_builder_build_children (DzlTreeBuilder *builder,
+ DzlTreeNode *node);
gboolean _dzl_tree_builder_drag_data_get (DzlTreeBuilder *builder,
DzlTreeNode *node,
GtkSelectionData *data);
diff --git a/src/tree/dzl-tree.c b/src/tree/dzl-tree.c
index 4231728..3cbe798 100644
--- a/src/tree/dzl-tree.c
+++ b/src/tree/dzl-tree.c
@@ -124,20 +124,40 @@ _dzl_tree_build_node (DzlTree *self,
DzlTreeNode *node)
{
DzlTreePrivate *priv = dzl_tree_get_instance_private (self);
- gsize i;
g_assert (DZL_IS_TREE (self));
g_assert (DZL_IS_TREE_NODE (node));
- _dzl_tree_node_set_needs_build (node, FALSE);
+ for (guint i = 0; i < priv->builders->len; i++)
+ {
+ DzlTreeBuilder *builder = g_ptr_array_index (priv->builders, i);
+
+ _dzl_tree_builder_build_node (builder, node);
+ }
+
+ if (!priv->always_expand &&
+ dzl_tree_node_get_children_possible (node) &&
+ dzl_tree_node_n_children (node) == 0)
+ _dzl_tree_node_add_dummy_child (node);
+}
+
+void
+_dzl_tree_build_children (DzlTree *self,
+ DzlTreeNode *node)
+{
+ DzlTreePrivate *priv = dzl_tree_get_instance_private (self);
+
+ g_assert (DZL_IS_TREE (self));
+ g_assert (DZL_IS_TREE_NODE (node));
+
+ _dzl_tree_node_set_needs_build_children (node, FALSE);
_dzl_tree_node_remove_dummy_child (node);
- for (i = 0; i < priv->builders->len; i++)
+ for (guint i = 0; i < priv->builders->len; i++)
{
- DzlTreeBuilder *builder;
+ DzlTreeBuilder *builder = g_ptr_array_index (priv->builders, i);
- builder = g_ptr_array_index (priv->builders, i);
- _dzl_tree_builder_build_node (builder, node);
+ _dzl_tree_builder_build_children (builder, node);
}
}
@@ -314,17 +334,24 @@ dzl_tree_add_builder_foreach_cb (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data)
{
+ g_autoptr(DzlTreeNode) node = NULL;
DzlTreeBuilder *builder = user_data;
- DzlTreeNode *node = NULL;
+ DzlTreePrivate *priv;
+ DzlTree *tree;
g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
g_return_val_if_fail (path != NULL, FALSE);
g_return_val_if_fail (iter != NULL, FALSE);
+ tree = dzl_tree_builder_get_tree (builder);
+ priv = dzl_tree_get_instance_private (tree);
+
gtk_tree_model_get (model, iter, 0, &node, -1);
- if (!_dzl_tree_node_get_needs_build (node))
- _dzl_tree_builder_build_node (builder, node);
- g_clear_object (&node);
+
+ _dzl_tree_builder_build_node (builder, node);
+
+ if (priv->always_expand || !_dzl_tree_node_get_needs_build_children (node))
+ _dzl_tree_builder_build_children (builder, node);
return FALSE;
}
@@ -484,17 +511,19 @@ dzl_tree_add (DzlTree *self,
0, child,
-1);
+ _dzl_tree_build_node (self, child);
+
if (dzl_tree_node_get_children_possible (child))
_dzl_tree_node_add_dummy_child (child);
if (priv->always_expand)
{
- _dzl_tree_build_node (self, child);
+ _dzl_tree_build_children (self, child);
dzl_tree_node_expand (child, TRUE);
}
else if (node == priv->root)
{
- _dzl_tree_build_node (self, child);
+ _dzl_tree_build_children (self, child);
}
g_object_unref (child);
@@ -522,7 +551,7 @@ _dzl_tree_insert_sorted (DzlTree *self,
_dzl_tree_node_set_tree (child, self);
_dzl_tree_node_set_parent (child, node);
- _dzl_tree_node_set_needs_build (child, TRUE);
+ _dzl_tree_node_set_needs_build_children (child, TRUE);
g_object_ref_sink (child);
@@ -554,8 +583,10 @@ _dzl_tree_insert_sorted (DzlTree *self,
gtk_tree_store_set (priv->store, &children, 0, child, -1);
inserted:
- if (node == priv->root)
- _dzl_tree_build_node (self, child);
+ _dzl_tree_build_node (self, child);
+
+ if (priv->always_expand || priv->root == child)
+ _dzl_tree_build_children (self, child);
g_object_unref (child);
}
@@ -618,12 +649,13 @@ dzl_tree_row_expanded (GtkTreeView *tree_view,
g_assert (DZL_IS_TREE_NODE (node));
/*
- * If we are expanding a row that has a dummy child, we might need to
- * build the node immediately, and re-expand it.
+ * If we are expanding a row that has a dummy child, we need to allow
+ * the builders to add children to the node.
*/
- if (_dzl_tree_node_get_needs_build (node))
+
+ if (_dzl_tree_node_get_needs_build_children (node))
{
- _dzl_tree_build_node (self, node);
+ _dzl_tree_build_children (self, node);
dzl_tree_node_expand (node, FALSE);
dzl_tree_node_select (node);
}
@@ -680,7 +712,7 @@ dzl_tree_row_collapsed (GtkTreeView *tree_view,
}
_dzl_tree_node_add_dummy_child (node);
- _dzl_tree_node_set_needs_build (node, TRUE);
+ _dzl_tree_node_set_needs_build_children (node, TRUE);
}
/* Notify builders of collapse */
@@ -1511,7 +1543,7 @@ dzl_tree_set_root (DzlTree *self,
priv->root = g_object_ref_sink (root);
_dzl_tree_node_set_parent (priv->root, NULL);
_dzl_tree_node_set_tree (priv->root, self);
- _dzl_tree_build_node (self, priv->root);
+ _dzl_tree_build_children (self, priv->root);
}
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ROOT]);
@@ -1535,7 +1567,7 @@ dzl_tree_rebuild (DzlTree *self)
if (priv->root != NULL)
{
gtk_tree_store_clear (priv->store);
- _dzl_tree_build_node (self, priv->root);
+ _dzl_tree_build_children (self, priv->root);
}
}
@@ -1661,12 +1693,17 @@ _dzl_tree_invalidate (DzlTree *self,
gtk_tree_path_free (path);
}
- _dzl_tree_node_set_needs_build (node, TRUE);
+ _dzl_tree_node_set_needs_build_children (node, TRUE);
parent = dzl_tree_node_get_parent (node);
- if ((parent == NULL) || dzl_tree_node_get_expanded (parent))
+ /* Build the node (unless it's the root */
+ if (parent != NULL)
_dzl_tree_build_node (self, node);
+
+ /* Now build the children if necessary */
+ if ((parent == NULL) || dzl_tree_node_get_expanded (parent))
+ _dzl_tree_build_children (self, node);
}
/**
@@ -1707,8 +1744,8 @@ dzl_tree_find_child_node (DzlTree *self,
return NULL;
}
- if (_dzl_tree_node_get_needs_build (node))
- _dzl_tree_build_node (self, node);
+ if (_dzl_tree_node_get_needs_build_children (node))
+ _dzl_tree_build_children (self, node);
model = GTK_TREE_MODEL (priv->store);
path = dzl_tree_node_get_path (node);
@@ -1827,7 +1864,7 @@ dzl_tree_model_filter_recursive (GtkTreeModel *model,
if (filter->filter_func (filter->self, node, filter->filter_data))
return TRUE;
- if (!_dzl_tree_node_get_needs_build (node))
+ if (!_dzl_tree_node_get_needs_build_children (node))
{
if (dzl_tree_model_filter_recursive (model, &child, filter))
return TRUE;
diff --git a/tests/test-tree.c b/tests/test-tree.c
index 739794d..3f4ec7e 100644
--- a/tests/test-tree.c
+++ b/tests/test-tree.c
@@ -1,8 +1,8 @@
#include <dazzle.h>
static void
-build_node_cb (DzlTreeBuilder *builder,
- DzlTreeNode *node)
+build_children_cb (DzlTreeBuilder *builder,
+ DzlTreeNode *node)
{
GFile *file;
@@ -215,7 +215,7 @@ main (gint argc,
gtk_container_add (GTK_CONTAINER (scroller), tree);
builder = dzl_tree_builder_new ();
- g_signal_connect (builder, "build-node", G_CALLBACK (build_node_cb), NULL);
+ g_signal_connect (builder, "build-children", G_CALLBACK (build_children_cb), NULL);
g_signal_connect (builder, "drag-data-get", G_CALLBACK (node_drag_data_get_cb), NULL);
g_signal_connect (builder, "drag-data-received", G_CALLBACK (drag_data_received_cb), NULL);
g_signal_connect (builder, "drag-node-received", G_CALLBACK (drag_node_received_cb), NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]