[gnome-builder/wip/large-project] tree: allow GbTree to be even more lazy with dummy children
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/large-project] tree: allow GbTree to be even more lazy with dummy children
- Date: Mon, 15 Jun 2015 10:08:18 +0000 (UTC)
commit 189e1e1963cfdd5320bd2496f0473e0d4f7ac820
Author: Christian Hergert <christian hergert me>
Date: Mon Jun 15 03:07:12 2015 -0700
tree: allow GbTree to be even more lazy with dummy children
Some nodes may know they might have children, but want to delay the work
of checking and populating those children until necessary. Setting
gb_tree_node_set_children_possible() will add a dummy child to the node.
This causes the expand arrow to be displayed. Upon expansion, the node
will be fully built.
src/tree/gb-tree-node.c | 81 +++++++++++++++++++++++++++++++++++++++++
src/tree/gb-tree-node.h | 3 ++
src/tree/gb-tree-private.h | 1 +
src/tree/gb-tree.c | 85 ++++---------------------------------------
4 files changed, 93 insertions(+), 77 deletions(-)
---
diff --git a/src/tree/gb-tree-node.c b/src/tree/gb-tree-node.c
index 0f08aaa..1764f94 100644
--- a/src/tree/gb-tree-node.c
+++ b/src/tree/gb-tree-node.c
@@ -35,6 +35,8 @@ struct _GbTreeNode
GQuark icon_name;
guint use_markup : 1;
guint needs_build : 1;
+ guint is_dummy : 1;
+ guint children_possible : 1;
};
typedef struct
@@ -814,4 +816,83 @@ _gb_tree_node_set_needs_build (GbTreeNode *self,
g_assert (GB_IS_TREE_NODE (self));
self->needs_build = !!needs_build;
+
+ if (!needs_build)
+ self->is_dummy = FALSE;
+}
+
+void
+_gb_tree_node_add_dummy_child (GbTreeNode *self)
+{
+ GtkTreeModel *model;
+ GbTreeNode *dummy;
+ GtkTreeIter iter;
+ GtkTreeIter parent;
+
+ g_assert (GB_IS_TREE_NODE (self));
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->tree));
+
+ gb_tree_node_get_iter (self, &parent);
+
+ dummy = gb_tree_node_new ();
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
+ 0, g_object_ref_sink (dummy),
+ -1);
+ g_object_unref (dummy);
+}
+
+void
+_gb_tree_node_remove_dummy_child (GbTreeNode *self)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeIter children;
+
+ g_assert (GB_IS_TREE_NODE (self));
+
+ if (self->parent == NULL)
+ return;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->tree));
+
+ if (gb_tree_node_get_iter (self, &iter) &&
+ gtk_tree_model_iter_children (model, &children, &iter))
+ {
+ while (gtk_tree_store_remove (GTK_TREE_STORE (model), &children))
+ {
+ }
+ }
+}
+
+/**
+ * gb_tree_node_set_children_possible:
+ * @self: A #GbTreeNode.
+ * @children_possible: If the node has children.
+ *
+ * If the node has not yet been built, setting this to %TRUE will add a
+ * dummy child node. This dummy node will be removed when when the node
+ * is built by the registered #GbTreeBuilder instances.
+ */
+void
+gb_tree_node_set_children_possible (GbTreeNode *self,
+ gboolean children_possible)
+{
+ g_return_if_fail (GB_IS_TREE_NODE (self));
+
+ children_possible = !!children_possible;
+
+ if (children_possible != self->children_possible)
+ {
+ self->children_possible = children_possible;
+
+ if (self->needs_build)
+ {
+ if (self->children_possible)
+ _gb_tree_node_add_dummy_child (self);
+ else
+ _gb_tree_node_remove_dummy_child (self);
+ }
+ }
}
diff --git a/src/tree/gb-tree-node.h b/src/tree/gb-tree-node.h
index 828883e..34e3d23 100644
--- a/src/tree/gb-tree-node.h
+++ b/src/tree/gb-tree-node.h
@@ -58,6 +58,9 @@ const gchar *gb_tree_node_get_text (GbTreeNode *node);
void gb_tree_node_set_text (GbTreeNode *node,
const gchar *text);
GbTree *gb_tree_node_get_tree (GbTreeNode *node);
+void gb_tree_node_set_children_possible
+ (GbTreeNode *self,
+ gboolean children_possible);
G_END_DECLS
diff --git a/src/tree/gb-tree-private.h b/src/tree/gb-tree-private.h
index 08caa39..5aee1e9 100644
--- a/src/tree/gb-tree-private.h
+++ b/src/tree/gb-tree-private.h
@@ -46,6 +46,7 @@ void _gb_tree_node_set_parent (GbTreeNode *node,
gboolean _gb_tree_node_get_needs_build (GbTreeNode *node);
void _gb_tree_node_set_needs_build (GbTreeNode *node,
gboolean needs_build);
+void _gb_tree_node_remove_dummy_child (GbTreeNode *node);
void _gb_tree_builder_set_tree (GbTreeBuilder *builder,
GbTree *tree);
diff --git a/src/tree/gb-tree.c b/src/tree/gb-tree.c
index a42adbb..0a1310f 100644
--- a/src/tree/gb-tree.c
+++ b/src/tree/gb-tree.c
@@ -80,6 +80,7 @@ gb_tree_build_node (GbTree *self,
g_assert (GB_IS_TREE_NODE (node));
_gb_tree_node_set_needs_build (node, FALSE);
+ _gb_tree_node_remove_dummy_child (node);
for (i = 0; i < priv->builders->len; i++)
{
@@ -361,48 +362,6 @@ gb_tree_selection_changed (GbTree *self,
IDE_EXIT;
}
-#if 0
-static gboolean
-gb_tree_get_iter_for_node (GbTree *self,
- GtkTreeIter *parent,
- GtkTreeIter *iter,
- GbTreeNode *node)
-{
- GbTreePrivate *priv = gb_tree_get_instance_private (self);
- GtkTreeModel *model;
- GbTreeNode *that = NULL;
- gboolean ret;
-
- g_return_val_if_fail (GB_IS_TREE (self), FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (GB_IS_TREE_NODE (node), FALSE);
-
- model = GTK_TREE_MODEL (priv->store);
-
- if (parent)
- ret = gtk_tree_model_iter_children (model, iter, parent);
- else
- ret = gtk_tree_model_get_iter_first (model, iter);
-
- if (ret)
- {
- do
- {
- gtk_tree_model_get (model, iter, 0, &that, -1);
- if (that == node)
- {
- g_clear_object (&that);
- return TRUE;
- }
- g_clear_object (&that);
- }
- while (gtk_tree_model_iter_next (model, iter));
- }
-
- return FALSE;
-}
-#endif
-
static gboolean
gb_tree_add_builder_foreach_cb (GtkTreeModel *model,
GtkTreePath *path,
@@ -556,7 +515,7 @@ gb_tree_add (GbTree *self,
gtk_tree_store_set (priv->store, &iter, 0, child, -1);
- if (gb_tree_node_get_expanded (node))
+ if (node == priv->root)
gb_tree_build_node (self, child);
g_object_unref (child);
@@ -613,7 +572,7 @@ _gb_tree_insert_sorted (GbTree *self,
gtk_tree_store_set (priv->store, &children, 0, child, -1);
inserted:
- if (gb_tree_node_get_expanded (node))
+ if (node == priv->root)
gb_tree_build_node (self, child);
g_object_unref (child);
@@ -677,42 +636,14 @@ gb_tree_row_expanded (GtkTreeView *tree_view,
gtk_tree_model_get (model, iter, 0, &node, -1);
- if (_gb_tree_node_get_needs_build (node))
- gb_tree_build_node (self, node);
-
/*
- * The following code looks like inefficient use of GtkTreeModel as we
- * are not using iter_children() and iter_next(). However, this is required
- * since the tree will likely have changes since our last iteration cycle.
- * This is due to the builders adding children for the individual nodes.
- * Therefore, we simply require that path is still valid (since builders
- * cannot change anything but current/child nodes).
+ * If we are expanding a row that has a dummy child, we might need to
+ * build the node immediately, and re-expand it.
*/
-
- if (gtk_tree_model_iter_has_child (model, iter))
+ if (_gb_tree_node_get_needs_build (node))
{
- GtkTreeIter child_iter;
- guint n_children;
- guint i;
-
- n_children = gtk_tree_model_iter_n_children (model, iter);
-
- for (i = 0; i < n_children; i++)
- {
- gtk_tree_model_get_iter (model, iter, path);
-
- if (gtk_tree_model_iter_nth_child (model, &child_iter, iter, i))
- {
- GbTreeNode *child;
-
- gtk_tree_model_get (model, &child_iter, 0, &child, -1);
-
- if (_gb_tree_node_get_needs_build (child))
- gb_tree_build_node (self, child);
-
- g_clear_object (&child);
- }
- }
+ gb_tree_build_node (self, node);
+ gb_tree_node_expand (node, FALSE);
}
g_clear_object (&node);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]