enum
{
ROW_ACTIVATED,
+ EXPAND_ROW,
+ COLLAPSE_ROW,
LAST_SIGNAL
};
static void gtk_tree_view_set_adjustments (GtkTreeView *tree_view,
GtkAdjustment *hadj,
GtkAdjustment *vadj);
-static void gtk_tree_view_changed (GtkTreeModel *model,
+static void gtk_tree_view_range_changed (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
+ GtkTreePath *end_path,
+ GtkTreeIter *end_iter,
gpointer data);
static void gtk_tree_view_inserted (GtkTreeModel *model,
GtkTreePath *path,
gpointer data);
static void gtk_tree_view_reordered (GtkTreeModel *model,
GtkTreePath *parent,
- gint *new_order);
+ GtkTreeIter *iter,
+ gint *new_order,
+ gpointer data);
/* Internal functions */
static void gtk_tree_view_unref_tree (GtkTreeView *tree_view,
GtkRBTree *tree);
GTK_TYPE_NONE, 2,
GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
- tree_view_signals[ROW_ACTIVATED] = gtk_signal_new ("row_activated",
- GTK_RUN_LAST | GTK_RUN_ACTION,
- GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
- gtk_marshal_VOID__BOXED_OBJECT,
- GTK_TYPE_NONE, 2,
- GTK_TYPE_TREE_PATH,
- GTK_TYPE_TREE_VIEW_COLUMN);
-
+ tree_view_signals[ROW_ACTIVATED] =
+ gtk_signal_new ("row_activated",
+ GTK_RUN_LAST | GTK_RUN_ACTION,
+ GTK_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
+ gtk_marshal_VOID__BOXED_OBJECT,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_TREE_PATH,
+ GTK_TYPE_TREE_VIEW_COLUMN);
+ tree_view_signals[EXPAND_ROW] =
+ g_signal_newc ("expand_row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkTreeViewClass, expand_row),
+ _gtk_boolean_handled_accumulator, NULL,
+ gtk_marshal_BOOLEAN__BOXED_BOXED,
+ G_TYPE_BOOLEAN, 2,
+ GTK_TYPE_TREE_ITER,
+ GTK_TYPE_TREE_PATH);
+ tree_view_signals[COLLAPSE_ROW] =
+ g_signal_newc ("collapse_row",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkTreeViewClass, collapse_row),
+ _gtk_boolean_handled_accumulator, NULL,
+ gtk_marshal_BOOLEAN__BOXED_BOXED,
+ G_TYPE_BOOLEAN, 2,
+ GTK_TYPE_TREE_ITER,
+ GTK_TYPE_TREE_PATH);
}
static void
if (tree_view->priv->button_pressed_node == tree_view->priv->prelight_node &&
GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
{
- GtkTreePath *path;
+ GtkTreePath *path = NULL;
GtkTreeIter iter;
/* Actually activate the node */
if (tree_view->priv->button_pressed_node->children == NULL)
{
GtkTreeIter child;
- path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
+ path = _gtk_tree_view_find_path (tree_view,
tree_view->priv->button_pressed_tree,
tree_view->priv->button_pressed_node);
- tree_view->priv->button_pressed_node->children = _gtk_rbtree_new ();
- tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree;
- tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node;
gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
if (gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter))
- gtk_tree_view_build_tree (tree_view,
- tree_view->priv->button_pressed_node->children,
- &child,
- gtk_tree_path_get_depth (path) + 1,
- FALSE,
- GTK_WIDGET_REALIZED (widget));
+ {
+ gboolean expand;
+ g_signal_emit (G_OBJECT (tree_view), tree_view_signals[EXPAND_ROW], 0, &iter, path, &expand);
+ if (! expand)
+ {
+ tree_view->priv->button_pressed_node->children = _gtk_rbtree_new ();
+ tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree;
+ tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node;
+ gtk_tree_view_build_tree (tree_view,
+ tree_view->priv->button_pressed_node->children,
+ &child,
+ gtk_tree_path_get_depth (path) + 1,
+ FALSE,
+ GTK_WIDGET_REALIZED (widget));
+
+ }
+ }
}
else
{
+ gboolean collapse;
+
path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
- tree_view->priv->button_pressed_node->children,
- tree_view->priv->button_pressed_node->children->root);
+ tree_view->priv->button_pressed_tree,
+ tree_view->priv->button_pressed_node);
gtk_tree_model_get_iter (tree_view->priv->model,
&iter,
path);
+ g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLLAPSE_ROW], 0, &iter, path, &collapse);
- gtk_tree_view_discover_dirty (GTK_TREE_VIEW (widget),
- tree_view->priv->button_pressed_node->children,
- &iter,
- gtk_tree_path_get_depth (path));
- gtk_tree_view_unref_tree (GTK_TREE_VIEW (widget),
- tree_view->priv->button_pressed_node->children);
- _gtk_rbtree_remove (tree_view->priv->button_pressed_node->children);
+ if (! collapse)
+ {
+ GtkTreeIter child_iter;
+ gtk_tree_path_append_index (path, 0);
+ gtk_tree_model_iter_children (tree_view->priv->model,
+ &child_iter,
+ &iter);
+ gtk_tree_view_discover_dirty (GTK_TREE_VIEW (widget),
+ tree_view->priv->button_pressed_node->children,
+ &child_iter,
+ gtk_tree_path_get_depth (path));
+ gtk_tree_view_unref_tree (GTK_TREE_VIEW (widget),
+ tree_view->priv->button_pressed_node->children);
+ _gtk_rbtree_remove (tree_view->priv->button_pressed_node->children);
+ }
}
- gtk_tree_path_free (path);
+ if (path)
+ gtk_tree_path_free (path);
_gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
}
*/
static void
-gtk_tree_view_changed (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
+gtk_tree_view_range_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ GtkTreePath *end_path,
+ GtkTreeIter *end_iter,
+ gpointer data)
{
GtkTreeView *tree_view = (GtkTreeView *)data;
GtkRBTree *tree;
static void
gtk_tree_view_reordered (GtkTreeModel *model,
GtkTreePath *parent,
- gint *new_order)
+ GtkTreeIter *iter,
+ gint *new_order,
+ gpointer data)
{
-
+ GtkTreeView *tree_view = GTK_TREE_VIEW (data);
+ GtkRBTree *tree;
+ GtkRBNode *node;
+ gint len;
+
+ len = gtk_tree_model_iter_n_children (model, iter);
+
+ if (len < 2)
+ return;
+
+ gtk_tree_row_reference_reordered (G_OBJECT (data),
+ parent,
+ iter,
+ new_order);
+
+ if (_gtk_tree_view_find_node (tree_view,
+ parent,
+ &tree,
+ &node))
+ return;
+
+ /* We need to special case the parent path */
+ if (tree == NULL)
+ tree = tree_view->priv->tree;
+ else
+ tree = node->children;
+
+ if (tree == NULL)
+ return;
+
+ /* FIXME: we need to unprelight our tree, if it's prelit. */
+ _gtk_rbtree_reorder (tree, new_order, len);
+
+ gtk_widget_queue_draw (GTK_WIDGET (tree_view));
}
/* Internal tree functions */
else
gtk_tree_view_column_set_width (column, MAX (column->width, width));
}
+
_gtk_rbtree_node_set_height (tree, temp, max_height);
+
if (temp->children != NULL &&
gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
gtk_tree_view_calc_size (tree_view, temp->children, &child, depth + 1);
GtkTreeViewColumn *column;
GList *list;
gint i;
- gint retval = FALSE;
+ gboolean retval = FALSE;
gint tmpheight;
if (height)
return path;
}
-/* Returns TRUE if we ran out of tree before finding the node,
- * so the returned node is the last node we saw and the returned
- * tree is NULL
+/* Returns TRUE if we ran out of tree before finding the path.
*/
gboolean
_gtk_tree_view_find_node (GtkTreeView *tree_view,
*node = NULL;
*tree = NULL;
+ if (depth == 0)
+ return FALSE;
do
{
if (tmptree == NULL)
tree_view->priv->tree = NULL;
g_signal_connectc (tree_view->priv->model,
- "changed",
- gtk_tree_view_changed,
+ "range_changed",
+ gtk_tree_view_range_changed,
tree_view,
FALSE);
g_signal_connectc (tree_view->priv->model,
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+ if (model == tree_view->priv->model)
+ return;
+
if (model != NULL)
g_object_ref (model);
if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
{
g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
- G_SIGNAL_MATCH_FUNC,
+ G_SIGNAL_MATCH_DATA,
0, 0, NULL,
- gtk_tree_view_changed, NULL);
+ NULL, tree_view);
g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
- G_SIGNAL_MATCH_FUNC,
+ G_SIGNAL_MATCH_DATA,
0, 0, NULL,
- gtk_tree_view_inserted, NULL);
+ NULL, tree_view);
g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
- G_SIGNAL_MATCH_FUNC,
+ G_SIGNAL_MATCH_DATA,
0, 0, NULL,
- gtk_tree_view_has_child_toggled, NULL);
+ NULL, tree_view);
g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
- G_SIGNAL_MATCH_FUNC,
+ G_SIGNAL_MATCH_DATA,
0, 0, NULL,
- gtk_tree_view_deleted, NULL);
+ NULL, tree_view);
g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
- G_SIGNAL_MATCH_FUNC,
+ G_SIGNAL_MATCH_DATA,
0, 0, NULL,
- gtk_tree_view_reordered, NULL);
+ NULL, tree_view);
_gtk_rbtree_free (tree_view->priv->tree);
}
tree_view->priv->tree = NULL;
if (GTK_WIDGET_REALIZED (tree_view))
_gtk_tree_view_update_size (tree_view);
- return;
}
else if (GTK_WIDGET_REALIZED (tree_view))
{
GtkTreeIter child;
GtkRBTree *tree;
GtkRBNode *node;
+ gboolean expand;
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
return FALSE;
+ g_signal_emit (G_OBJECT (tree_view), tree_view_signals[EXPAND_ROW], 0, &iter, path, &expand);
+
+ if (expand)
+ return FALSE;
+
node->children = _gtk_rbtree_new ();
node->children->parent_tree = tree;
node->children->parent_node = node;
* @tree_view: a #GtkTreeView
* @path: path to a row in the @tree_view
*
- * Collapses a row (hides its child rows).
+ * Collapses a row (hides its child rows, if they exist.)
*
- * Return value: %TRUE if the row was expanded
+ * Return value: %TRUE if the row was collapsed.
**/
gboolean
gtk_tree_view_collapse_row (GtkTreeView *tree_view,
GtkRBTree *tree;
GtkRBNode *node;
GtkTreeIter iter;
+ gboolean collapse;
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
return FALSE;
gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
+
+ g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLLAPSE_ROW], 0, &iter, path, &collapse);
+
+ if (collapse)
+ return FALSE;
+
gtk_tree_view_discover_dirty (tree_view,
node->children,
&iter,
(pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
{
- gtk_tree_view_expand_row (tree_view,
- dest_path,
- FALSE);
+ gtk_tree_view_expand_row (tree_view, dest_path, FALSE);
tree_view->priv->open_dest_timeout = 0;
gtk_tree_path_free (dest_path);