GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

Commit a05d3238 authored by Christian Hergert's avatar Christian Hergert

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).
parent 3755a576
......@@ -42,6 +42,7 @@ enum {
enum {
ADDED,
REMOVED,
BUILD_CHILDREN,
BUILD_NODE,
DRAG_DATA_GET,
DRAG_DATA_RECEIVED,
......@@ -107,6 +108,16 @@ _dzl_tree_builder_node_unselected (DzlTreeBuilder *builder,
g_signal_emit (builder, signals [NODE_UNSELECTED], 0, node);
}
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),
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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;
......
#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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment