- }
- }
-
- pspp_sheet_view_scroll_to_point (tree_view, dest_x, dest_y);
- }
-}
-
-/**
- * pspp_sheet_view_row_activated:
- * @tree_view: A #PsppSheetView
- * @path: The #GtkTreePath to be activated.
- * @column: The #PsppSheetViewColumn to be activated.
- *
- * Activates the cell determined by @path and @column.
- **/
-void
-pspp_sheet_view_row_activated (PsppSheetView *tree_view,
- GtkTreePath *path,
- PsppSheetViewColumn *column)
-{
- g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
-
- g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
-}
-
-
-static void
-pspp_sheet_view_expand_all_emission_helper (GtkRBTree *tree,
- GtkRBNode *node,
- gpointer data)
-{
- PsppSheetView *tree_view = data;
-
- if ((node->flags & PSPP_RBNODE_IS_PARENT) == PSPP_RBNODE_IS_PARENT &&
- node->children)
- {
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = _pspp_sheet_view_find_path (tree_view, tree, node);
- gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
-
- g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
-
- gtk_tree_path_free (path);
- }
-
- if (node->children)
- _pspp_rbtree_traverse (node->children,
- node->children->root,
- G_PRE_ORDER,
- pspp_sheet_view_expand_all_emission_helper,
- tree_view);
-}
-
-/**
- * pspp_sheet_view_expand_all:
- * @tree_view: A #PsppSheetView.
- *
- * Recursively expands all nodes in the @tree_view.
- **/
-void
-pspp_sheet_view_expand_all (PsppSheetView *tree_view)
-{
- GtkTreePath *path;
- GtkRBTree *tree;
- GtkRBNode *node;
-
- g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
-
- if (tree_view->priv->tree == NULL)
- return;
-
- path = gtk_tree_path_new_first ();
- _pspp_sheet_view_find_node (tree_view, path, &tree, &node);
-
- while (node)
- {
- pspp_sheet_view_real_expand_row (tree_view, path, tree, node, TRUE, FALSE);
- node = _pspp_rbtree_next (tree, node);
- gtk_tree_path_next (path);
- }
-
- gtk_tree_path_free (path);
-}
-
-/* Timeout to animate the expander during expands and collapses */
-static gboolean
-expand_collapse_timeout (gpointer data)
-{
- return do_expand_collapse (data);
-}
-
-static void
-add_expand_collapse_timeout (PsppSheetView *tree_view,
- GtkRBTree *tree,
- GtkRBNode *node,
- gboolean expand)
-{
- if (tree_view->priv->expand_collapse_timeout != 0)
- return;
-
- tree_view->priv->expand_collapse_timeout =
- gdk_threads_add_timeout (50, expand_collapse_timeout, tree_view);
- tree_view->priv->expanded_collapsed_tree = tree;
- tree_view->priv->expanded_collapsed_node = node;
-
- if (expand)
- PSPP_RBNODE_SET_FLAG (node, PSPP_RBNODE_IS_SEMI_COLLAPSED);
- else
- PSPP_RBNODE_SET_FLAG (node, PSPP_RBNODE_IS_SEMI_EXPANDED);
-}
-
-static void
-remove_expand_collapse_timeout (PsppSheetView *tree_view)
-{
- if (tree_view->priv->expand_collapse_timeout)
- {
- g_source_remove (tree_view->priv->expand_collapse_timeout);
- tree_view->priv->expand_collapse_timeout = 0;
- }
-
- if (tree_view->priv->expanded_collapsed_node != NULL)
- {
- PSPP_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, PSPP_RBNODE_IS_SEMI_EXPANDED);
- PSPP_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, PSPP_RBNODE_IS_SEMI_COLLAPSED);
-
- tree_view->priv->expanded_collapsed_node = NULL;
- }
-}
-
-static void
-cancel_arrow_animation (PsppSheetView *tree_view)
-{
- if (tree_view->priv->expand_collapse_timeout)
- {
- while (do_expand_collapse (tree_view));
-
- remove_expand_collapse_timeout (tree_view);
- }
-}
-
-static gboolean
-do_expand_collapse (PsppSheetView *tree_view)
-{
- GtkRBNode *node;
- GtkRBTree *tree;
- gboolean expanding;
- gboolean redraw;
-
- redraw = FALSE;
- expanding = TRUE;
-
- node = tree_view->priv->expanded_collapsed_node;
- tree = tree_view->priv->expanded_collapsed_tree;
-
- if (node->children == NULL)
- expanding = FALSE;
-
- if (expanding)
- {
- if (PSPP_RBNODE_FLAG_SET (node, PSPP_RBNODE_IS_SEMI_COLLAPSED))
- {
- PSPP_RBNODE_UNSET_FLAG (node, PSPP_RBNODE_IS_SEMI_COLLAPSED);
- PSPP_RBNODE_SET_FLAG (node, PSPP_RBNODE_IS_SEMI_EXPANDED);
-
- redraw = TRUE;
-
- }
- else if (PSPP_RBNODE_FLAG_SET (node, PSPP_RBNODE_IS_SEMI_EXPANDED))
- {
- PSPP_RBNODE_UNSET_FLAG (node, PSPP_RBNODE_IS_SEMI_EXPANDED);
-
- redraw = TRUE;
- }
- }
- else
- {
- if (PSPP_RBNODE_FLAG_SET (node, PSPP_RBNODE_IS_SEMI_EXPANDED))
- {
- PSPP_RBNODE_UNSET_FLAG (node, PSPP_RBNODE_IS_SEMI_EXPANDED);
- PSPP_RBNODE_SET_FLAG (node, PSPP_RBNODE_IS_SEMI_COLLAPSED);
-
- redraw = TRUE;
- }
- else if (PSPP_RBNODE_FLAG_SET (node, PSPP_RBNODE_IS_SEMI_COLLAPSED))
- {
- PSPP_RBNODE_UNSET_FLAG (node, PSPP_RBNODE_IS_SEMI_COLLAPSED);
-
- redraw = TRUE;
-
- }
- }
-
- if (redraw)
- {
- pspp_sheet_view_queue_draw_arrow (tree_view, tree, node, NULL);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * pspp_sheet_view_collapse_all:
- * @tree_view: A #PsppSheetView.
- *
- * Recursively collapses all visible, expanded nodes in @tree_view.
- **/
-void
-pspp_sheet_view_collapse_all (PsppSheetView *tree_view)
-{
- GtkRBTree *tree;
- GtkRBNode *node;
- GtkTreePath *path;
- gint *indices;
-
- g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
-
- if (tree_view->priv->tree == NULL)
- return;
-
- path = gtk_tree_path_new ();
- gtk_tree_path_down (path);
- indices = gtk_tree_path_get_indices (path);
-
- tree = tree_view->priv->tree;
- node = tree->root;
- while (node && node->left != tree->nil)
- node = node->left;
-
- while (node)
- {
- if (node->children)
- pspp_sheet_view_real_collapse_row (tree_view, path, tree, node, FALSE);
- indices[0]++;
- node = _pspp_rbtree_next (tree, node);
- }
-
- gtk_tree_path_free (path);
-}
-
-/**
- * pspp_sheet_view_expand_to_path:
- * @tree_view: A #PsppSheetView.
- * @path: path to a row.
- *
- * Expands the row at @path. This will also expand all parent rows of
- * @path as necessary.
- *
- * Since: 2.2
- **/
-void
-pspp_sheet_view_expand_to_path (PsppSheetView *tree_view,
- GtkTreePath *path)
-{
- gint i, depth;
- gint *indices;
- GtkTreePath *tmp;
-
- g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
- g_return_if_fail (path != NULL);
-
- depth = gtk_tree_path_get_depth (path);
- indices = gtk_tree_path_get_indices (path);
-
- tmp = gtk_tree_path_new ();
- g_return_if_fail (tmp != NULL);
-
- for (i = 0; i < depth; i++)
- {
- gtk_tree_path_append_index (tmp, indices[i]);
- pspp_sheet_view_expand_row (tree_view, tmp, FALSE);
- }
-
- gtk_tree_path_free (tmp);
-}
-
-/* FIXME the bool return values for expand_row and collapse_row are
- * not analagous; they should be TRUE if the row had children and
- * was not already in the requested state.
- */
-
-
-static gboolean
-pspp_sheet_view_real_expand_row (PsppSheetView *tree_view,
- GtkTreePath *path,
- GtkRBTree *tree,
- GtkRBNode *node,
- gboolean open_all,
- gboolean animate)
-{
- GtkTreeIter iter;
- GtkTreeIter temp;
- gboolean expand;
-
- if (animate)
- g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
- "gtk-enable-animations", &animate,
- NULL);
-
- remove_auto_expand_timeout (tree_view);
-
- if (node->children && !open_all)
- return FALSE;
-
- if (! PSPP_RBNODE_FLAG_SET (node, PSPP_RBNODE_IS_PARENT))
- return FALSE;
-
- gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
- if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
- return FALSE;
-
-
- if (node->children && open_all)
- {
- gboolean retval = FALSE;
- GtkTreePath *tmp_path = gtk_tree_path_copy (path);
-
- gtk_tree_path_append_index (tmp_path, 0);
- tree = node->children;
- node = tree->root;
- while (node->left != tree->nil)
- node = node->left;
- /* try to expand the children */
- do
- {
- gboolean t;
- t = pspp_sheet_view_real_expand_row (tree_view, tmp_path, tree, node,
- TRUE, animate);
- if (t)
- retval = TRUE;
-
- gtk_tree_path_next (tmp_path);
- node = _pspp_rbtree_next (tree, node);
- }
- while (node != NULL);
-
- gtk_tree_path_free (tmp_path);
-
- return retval;
- }
-
- g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
-
- if (!gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
- return FALSE;
-
- if (expand)
- return FALSE;
-
- node->children = _pspp_rbtree_new ();
- node->children->parent_tree = tree;
- node->children->parent_node = node;
-
- gtk_tree_model_iter_children (tree_view->priv->model, &temp, &iter);
-
- pspp_sheet_view_build_tree (tree_view,
- node->children,
- &temp,
- gtk_tree_path_get_depth (path) + 1,
- open_all);
-
- remove_expand_collapse_timeout (tree_view);
-
- if (animate)
- add_expand_collapse_timeout (tree_view, tree, node, TRUE);
-
- install_presize_handler (tree_view);
-
- g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
- if (open_all && node->children)
- {
- _pspp_rbtree_traverse (node->children,
- node->children->root,
- G_PRE_ORDER,
- pspp_sheet_view_expand_all_emission_helper,
- tree_view);
- }
- return TRUE;
-}
-
-
-/**
- * pspp_sheet_view_expand_row:
- * @tree_view: a #PsppSheetView
- * @path: path to a row
- * @open_all: whether to recursively expand, or just expand immediate children
- *
- * Opens the row so its children are visible.
- *
- * Return value: %TRUE if the row existed and had children
- **/
-gboolean
-pspp_sheet_view_expand_row (PsppSheetView *tree_view,
- GtkTreePath *path,
- gboolean open_all)
-{
- GtkRBTree *tree;
- GtkRBNode *node;
-
- g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
- g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
-
- if (_pspp_sheet_view_find_node (tree_view,
- path,
- &tree,
- &node))
- return FALSE;
-
- if (tree != NULL)
- return pspp_sheet_view_real_expand_row (tree_view, path, tree, node, open_all, FALSE);
- else
- return FALSE;
-}
-
-static gboolean
-pspp_sheet_view_real_collapse_row (PsppSheetView *tree_view,
- GtkTreePath *path,
- GtkRBTree *tree,
- GtkRBNode *node,
- gboolean animate)
-{
- GtkTreeIter iter;
- GtkTreeIter children;
- gboolean collapse;
- gint x, y;
- GList *list;
- GdkWindow *child, *parent;
-
- if (animate)
- g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
- "gtk-enable-animations", &animate,
- NULL);
-
- remove_auto_expand_timeout (tree_view);
-
- if (node->children == NULL)
- return FALSE;
-
- gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
-
- g_signal_emit (tree_view, tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
-
- if (collapse)
- return FALSE;
-
- /* if the prelighted node is a child of us, we want to unprelight it. We have
- * a chance to prelight the correct node below */
-
- if (tree_view->priv->prelight_tree)
- {
- GtkRBTree *parent_tree;
- GtkRBNode *parent_node;
-
- parent_tree = tree_view->priv->prelight_tree->parent_tree;
- parent_node = tree_view->priv->prelight_tree->parent_node;
- while (parent_tree)
- {
- if (parent_tree == tree && parent_node == node)
- {
- ensure_unprelighted (tree_view);
- break;
- }
- parent_node = parent_tree->parent_node;
- parent_tree = parent_tree->parent_tree;
- }
- }
-
- TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_children (tree_view->priv->model, &children, &iter), FALSE);
-
- for (list = tree_view->priv->columns; list; list = list->next)
- {
- PsppSheetViewColumn *column = list->data;
-
- if (column->visible == FALSE)
- continue;
- if (pspp_sheet_view_column_get_sizing (column) == PSPP_SHEET_VIEW_COLUMN_AUTOSIZE)
- _pspp_sheet_view_column_cell_set_dirty (column, TRUE);
- }
-
- if (tree_view->priv->destroy_count_func)
- {
- GtkTreePath *child_path;
- gint child_count = 0;
- child_path = gtk_tree_path_copy (path);
- gtk_tree_path_down (child_path);
- if (node->children)
- _pspp_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
- tree_view->priv->destroy_count_func (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
- gtk_tree_path_free (child_path);
- }
-
- if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
- {
- GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
-
- if (gtk_tree_path_is_ancestor (path, cursor_path))
- {
- gtk_tree_row_reference_free (tree_view->priv->cursor);
- tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
- tree_view->priv->model,
- path);
- }
- gtk_tree_path_free (cursor_path);
- }
-
- if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
- {
- GtkTreePath *anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
- if (gtk_tree_path_is_ancestor (path, anchor_path))
- {
- gtk_tree_row_reference_free (tree_view->priv->anchor);
- tree_view->priv->anchor = NULL;
- }
- gtk_tree_path_free (anchor_path);
- }
-
- /* Stop a pending double click */
- tree_view->priv->last_button_x = -1;
- tree_view->priv->last_button_y = -1;
-
- remove_expand_collapse_timeout (tree_view);
-
- if (pspp_sheet_view_unref_and_check_selection_tree (tree_view, node->children))
- {
- _pspp_rbtree_remove (node->children);
- g_signal_emit_by_name (tree_view->priv->selection, "changed");
- }
- else
- _pspp_rbtree_remove (node->children);
-
- if (animate)
- add_expand_collapse_timeout (tree_view, tree, node, FALSE);
-
- if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
- {
- gtk_widget_queue_resize (GTK_WIDGET (tree_view));
- }
-
- g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
-
- if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
- {
- /* now that we've collapsed all rows, we want to try to set the prelight
- * again. To do this, we fake a motion event and send it to ourselves. */
-
- child = tree_view->priv->bin_window;
- parent = gdk_window_get_parent (child);
-
- if (gdk_window_get_pointer (parent, &x, &y, NULL) == child)
- {
- GdkEventMotion event;
- gint child_x, child_y;
-
- gdk_window_get_position (child, &child_x, &child_y);
-
- event.window = tree_view->priv->bin_window;
- event.x = x - child_x;
- event.y = y - child_y;
-
- /* despite the fact this isn't a real event, I'm almost positive it will
- * never trigger a drag event. maybe_drag is the only function that uses
- * more than just event.x and event.y. */
- pspp_sheet_view_motion_bin_window (GTK_WIDGET (tree_view), &event);
- }
- }
-
- return TRUE;
-}
-
-/**
- * pspp_sheet_view_collapse_row:
- * @tree_view: a #PsppSheetView
- * @path: path to a row in the @tree_view
- *
- * Collapses a row (hides its child rows, if they exist).
- *
- * Return value: %TRUE if the row was collapsed.
- **/
-gboolean
-pspp_sheet_view_collapse_row (PsppSheetView *tree_view,
- GtkTreePath *path)
-{
- GtkRBTree *tree;
- GtkRBNode *node;
-
- g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
- g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
-
- if (_pspp_sheet_view_find_node (tree_view,
- path,
- &tree,
- &node))
- return FALSE;
-
- if (tree == NULL || node->children == NULL)
- return FALSE;
-
- return pspp_sheet_view_real_collapse_row (tree_view, path, tree, node, FALSE);
-}
-
-static void
-pspp_sheet_view_map_expanded_rows_helper (PsppSheetView *tree_view,
- GtkRBTree *tree,
- GtkTreePath *path,
- PsppSheetViewMappingFunc func,
- gpointer user_data)
-{
- GtkRBNode *node;
-
- if (tree == NULL || tree->root == NULL)
- return;
-
- node = tree->root;
-
- while (node && node->left != tree->nil)
- node = node->left;
-
- while (node)
- {
- if (node->children)
- {
- (* func) (tree_view, path, user_data);
- gtk_tree_path_down (path);
- pspp_sheet_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
- gtk_tree_path_up (path);