gint column);
static gint gail_tree_view_get_n_rows (AtkTable *table);
static gint gail_tree_view_get_n_columns (AtkTable *table);
-static gint get_n_actual_columns (GtkTreeView *tree_view);
static gboolean gail_tree_view_is_row_selected (AtkTable *table,
gint row);
static gboolean gail_tree_view_is_selected (AtkTable *table,
static void free_row_info (GArray *array,
gint array_idx,
gboolean shift);
-static void clean_cell_info (GailTreeView *tree_view,
- GList *list);
static void clean_rows (GailTreeView *tree_view);
static void clean_cols (GailTreeView *tree_view,
GtkTreeViewColumn *tv_col);
static gboolean get_tree_path_from_row_index (GtkTreeModel *model,
gint row_index,
GtkTreePath **tree_path);
-static gint get_row_count (GtkTreeModel *model);
static gboolean get_path_column_from_index (GtkTreeView *tree_view,
gint index,
GtkTreePath **path,
static GailTreeViewCellInfo* find_cell_info (GailTreeView *view,
GailCell *cell,
- GList** list,
gboolean live_only);
static AtkObject * get_header_from_column (GtkTreeViewColumn *tv_col);
static gboolean idle_garbage_collect_cell_data (gpointer data);
view->summary = NULL;
view->row_data = NULL;
view->col_data = NULL;
- view->cell_data = NULL;
view->focus_cell = NULL;
view->old_hadj = NULL;
view->old_vadj = NULL;
view->n_children_deleted = 0;
+ view->cell_info_by_index = g_hash_table_new (g_int_hash, g_int_equal);
+
widget = GTK_WIDGET (data);
g_signal_connect_after (widget,
"row-collapsed",
(GCallback) focus_out, NULL, NULL, 0);
view->tree_model = tree_model;
+ view->n_rows = 0;
+ view->n_cols = 0;
if (tree_model)
{
g_object_add_weak_pointer (G_OBJECT (view->tree_model), (gpointer *)&view->tree_model);
+ count_rows (tree_model, NULL, NULL, &view->n_rows, 0, G_MAXINT);
connect_model_signals (tree_view, view);
if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
for (tmp_list = tv_cols; tmp_list; tmp_list = tmp_list->next)
{
+ view->n_cols++;
g_signal_connect_data (tmp_list->data, "notify::visible",
(GCallback)column_visibility_changed,
tree_view, NULL, FALSE);
disconnect_model_signals (gailview);
clear_cached_data (gailview);
gailview->tree_model = tree_model;
+ gailview->n_rows = 0;
/*
* if there is no model the GtkTreeView is probably being destroyed
*/
if (tree_model)
{
g_object_add_weak_pointer (G_OBJECT (gailview->tree_model), (gpointer *)&gailview->tree_model);
+ count_rows (tree_model, NULL, NULL, &gailview->n_rows, 0, G_MAXINT);
connect_model_signals (tree_view, gailview);
if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
if (view->tree_model)
disconnect_model_signals (view);
+ if (view->cell_info_by_index)
+ g_hash_table_destroy (view->cell_info_by_index);
+
if (view->col_data)
{
GArray *array = view->col_data;
gail_tree_view_get_n_children (AtkObject *obj)
{
GtkWidget *widget;
- GtkTreeView *tree_view;
- GtkTreeModel *tree_model;
- gint n_rows, n_cols;
gail_return_val_if_fail (GAIL_IS_TREE_VIEW (obj), 0);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
if (widget == NULL)
- /*
- * State is defunct
- */
return 0;
- tree_view = GTK_TREE_VIEW (widget);
- tree_model = gtk_tree_view_get_model (tree_view);
-
- /*
- * We get the total number of rows including those which are collapsed
- */
- n_rows = get_row_count (tree_model);
- /*
- * We get the total number of columns including those which are not visible
- */
- n_cols = get_n_actual_columns (tree_view);
- return (n_rows * n_cols);
+ return (GAIL_TREE_VIEW (obj)->n_rows + 1) * GAIL_TREE_VIEW (obj)->n_cols;
}
static AtkObject*
if (i >= gail_tree_view_get_n_children (obj))
return NULL;
+ gailview = GAIL_TREE_VIEW (obj);
tree_view = GTK_TREE_VIEW (widget);
- if (i < get_n_actual_columns (tree_view))
+ if (i < gailview->n_cols)
{
tv_col = gtk_tree_view_get_column (tree_view, i);
child = get_header_from_column (tv_col);
return child;
}
- gailview = GAIL_TREE_VIEW (obj);
/*
* Check whether the child is cached
*/
else
{
gint parent_index;
- gint n_columns;
- n_columns = get_n_actual_columns (tree_view);
- parent_index = get_index (tree_view, path, i % n_columns);
+ parent_index = get_index (tree_view, path, i % gailview->n_cols);
parent_node = atk_object_ref_accessible_child (obj, parent_index);
}
accessible_array[0] = parent_node;
return -1;
tree_view = GTK_TREE_VIEW (widget);
- n_columns = get_n_actual_columns (tree_view);
+ n_columns = GAIL_TREE_VIEW (table)->n_cols;
if (n_columns == 0)
return 0;
if (!tree_model)
n_rows = 0;
else if (gtk_tree_model_get_flags (tree_model) & GTK_TREE_MODEL_LIST_ONLY)
- /*
- * If working with a LIST store, then this is a faster way
- * to get the number of rows.
+ /*
+ * If working with a LIST store, then no rows are collapsed
*/
- n_rows = gtk_tree_model_iter_n_children (tree_model, NULL);
+ n_rows = GAIL_TREE_VIEW (table)->n_rows;
else
{
GtkTreePath *root_tree;
return n_rows;
}
-/*
- * The function get_n_actual_columns returns the number of columns in the
- * GtkTreeView. i.e. it include both visible and non-visible columns.
- */
-static gint
-get_n_actual_columns (GtkTreeView *tree_view)
-{
- GList *columns;
- gint n_cols;
-
- columns = gtk_tree_view_get_columns (tree_view);
- n_cols = g_list_length (columns);
- g_list_free (columns);
- return n_cols;
-}
-
-static gint
+static gint
gail_tree_view_get_n_columns (AtkTable *table)
{
GtkWidget *widget;
{
top_cell = cell;
}
- cell_info = find_cell_info (GAIL_TREE_VIEW (parent), top_cell, NULL, TRUE);
+ cell_info = find_cell_info (GAIL_TREE_VIEW (parent), top_cell, TRUE);
gail_return_if_fail (cell_info);
gail_return_if_fail (cell_info->cell_col_ref);
gail_return_if_fail (cell_info->cell_row_ref);
tree_view = GTK_TREE_VIEW (widget);
- cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, NULL, TRUE);
+ cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, TRUE);
gail_return_val_if_fail (cell_info, FALSE);
gail_return_val_if_fail (cell_info->cell_col_ref, FALSE);
gail_return_val_if_fail (cell_info->cell_row_ref, FALSE);
GailTreeView *gailview;
GtkTreeView *tree_view;
GtkWidget *widget;
- GList *cell_list;
- GList *l;
GailTreeViewCellInfo *info;
GtkTreeSelection *tree_selection;
GtkTreePath *path;
+ GHashTableIter iter;
gailview = GAIL_TREE_VIEW (data);
- cell_list = gailview->cell_data;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (gailview));
if (widget == NULL)
/*
clean_rows (gailview);
- for (l = cell_list; l; l = l->next)
+ /* FIXME: clean rows iterates through all cells too */
+ g_hash_table_iter_init (&iter, gailview->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&info))
{
- info = (GailTreeViewCellInfo *) (l->data);
-
if (info->in_use)
{
gail_cell_remove_state (info->cell, ATK_STATE_SELECTED, TRUE);
* gailview->col_data
*/
tv_cols = gtk_tree_view_get_columns (tree_view);
+ gailview->n_cols = g_list_length (tv_cols);
/* check for adds or moves */
for (tmp_list = tv_cols; tmp_list; tmp_list = tmp_list->next)
*/
if (!column_found)
{
- gint n_cols, n_rows, row;
+ gint row;
if (!stale_set)
{
g_signal_emit_by_name (atk_obj, "column_inserted", column_count, 1);
/* Generate children-changed signals */
- n_rows = get_row_count (gtk_tree_view_get_model (tree_view));
- n_cols = get_n_actual_columns (tree_view);
- for (row = 0; row < n_rows; row++)
+ for (row = 0; row < gailview->n_rows; row++)
{
/*
* Pass NULL as the child object, i.e. 4th argument.
*/
g_signal_emit_by_name (atk_obj, "children_changed::add",
- ((row * n_cols) + column_count), NULL, NULL);
+ ((row * gailview->n_cols) + column_count), NULL, NULL);
}
}
*/
if (!column_found)
{
- gint n_rows, n_cols, row;
+ gint row;
clean_cols (gailview,
(GtkTreeViewColumn *)g_array_index (gailview->col_data,
g_signal_emit_by_name (atk_obj, "column_deleted", i, 1);
/* Generate children-changed signals */
- n_rows = get_row_count (gtk_tree_view_get_model (tree_view));
- n_cols = get_n_actual_columns (tree_view);
- for (row = 0; row < n_rows; row++)
+ for (row = 0; row < gailview->n_rows; row++)
{
/*
* Pass NULL as the child object, 4th argument.
*/
g_signal_emit_by_name (atk_obj, "children_changed::remove",
- ((row * n_cols) + column_count), NULL, NULL);
+ ((row * gailview->n_cols) + column_count), NULL, NULL);
}
}
}
GtkTreeView *tree_view = GTK_TREE_VIEW(user_data);
GailTreeView *gailview;
GtkTreePath *cell_path;
- GList *l;
GailTreeViewCellInfo *cell_info;
-
+ GHashTableIter hash_iter;
+
gailview = GAIL_TREE_VIEW (gtk_widget_get_accessible (GTK_WIDGET (tree_view)));
/* Loop through our cached cells */
/* Must loop through them all */
- for (l = gailview->cell_data; l; l = l->next)
+ g_hash_table_iter_init (&hash_iter, gailview->cell_info_by_index);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer *)&cell_info))
{
- cell_info = (GailTreeViewCellInfo *) l->data;
- if (cell_info->in_use)
+ if (cell_info->in_use)
{
cell_path = gtk_tree_row_reference_get_path (cell_info->cell_row_ref);
*/
GtkTreeView *tree_view = (GtkTreeView *)user_data;
GailTreeView *gailview;
- GList *l;
GailTreeViewCellInfo *cell_info;
GtkTreeViewColumn *this_col = GTK_TREE_VIEW_COLUMN (object);
GtkTreeViewColumn *tv_col;
+ GHashTableIter iter;
gailview = GAIL_TREE_VIEW (gtk_widget_get_accessible (GTK_WIDGET (tree_view))
);
g_signal_emit_by_name (gailview, "model_changed");
- for (l = gailview->cell_data; l; l = l->next)
+ g_hash_table_iter_init (&iter, gailview->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
{
- cell_info = (GailTreeViewCellInfo *) l->data;
- if (cell_info->in_use)
+ if (cell_info->in_use)
{
tv_col = cell_info->cell_col_ref;
if (tv_col == this_col)
GailTreeView *gailview = GAIL_TREE_VIEW (atk_obj);
gint row, n_inserted, child_row;
+ gailview->n_rows++;
+
if (gailview->idle_expand_id)
{
g_source_remove (gailview->idle_expand_id);
GtkTreePath *path_copy;
AtkObject *atk_obj;
GailTreeView *gailview;
- gint row, col, n_cols;
+ gint row, col;
tree_view = (GtkTreeView *)user_data;
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
gailview = GAIL_TREE_VIEW (atk_obj);
+ gailview->n_rows--;
+ g_assert (gailview->n_rows >= 0);
+
if (gailview->idle_expand_id)
{
g_source_remove (gailview->idle_expand_id);
gailview->n_children_deleted = 0;
/* Generate children-changed signals */
- n_cols = get_n_actual_columns (tree_view);
- for (col = 0; col < n_cols; col++)
+ for (col = 0; col < gailview->n_cols; col++)
{
/*
* Pass NULL as the child object, 4th argument.
*/
g_signal_emit_by_name (atk_obj, "children_changed::remove",
- ((row * n_cols) + col), NULL, NULL);
+ ((row * gailview->n_cols) + col), NULL, NULL);
}
}
prop_list = gail_renderer_cell_class->property_list;
cell = GAIL_CELL (renderer_cell);
- cell_info = find_cell_info (gailview, cell, NULL, TRUE);
+ cell_info = find_cell_info (gailview, cell, TRUE);
gail_return_val_if_fail (cell_info, FALSE);
gail_return_val_if_fail (cell_info->cell_col_ref, FALSE);
gail_return_val_if_fail (cell_info->cell_row_ref, FALSE);
static void
clean_cell_info (GailTreeView *gailview,
- GList *list)
+ GailTreeViewCellInfo *cell_info)
{
- GailTreeViewCellInfo *cell_info;
GObject *obj;
g_assert (GAIL_IS_TREE_VIEW (gailview));
- cell_info = list->data;
-
if (cell_info->in_use) {
obj = G_OBJECT (cell_info->cell);
clean_rows (GailTreeView *gailview)
{
GArray *array;
+ GailTreeViewCellInfo *cell_info;
+ GHashTableIter iter;
/* Clean GailTreeViewRowInfo data */
}
/* Clean GailTreeViewCellInfo data */
-
- if (gailview->cell_data != NULL)
+ g_hash_table_iter_init (&iter, gailview->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
{
- GailTreeViewCellInfo *cell_info;
GtkTreePath *row_path;
- GList *cur_list;
- GList *temp_list;
- temp_list = gailview->cell_data;
-
- /* Must loop through them all */
- while (temp_list != NULL)
+ row_path = gtk_tree_row_reference_get_path (cell_info->cell_row_ref);
+ /*
+ * If the cell has become invalid because the row has been removed,
+ * then set the cell's state to ATK_STATE_DEFUNCT and schedule
+ * its removal. If row_path is NULL then the row has
+ * been removed.
+ */
+ if (row_path == NULL)
{
- cur_list = temp_list;
- cell_info = temp_list->data;
- temp_list = temp_list->next;
- row_path = gtk_tree_row_reference_get_path (cell_info->cell_row_ref);
-
- /*
- * If the cell has become invalid because the row has been removed,
- * then set the cell's state to ATK_STATE_DEFUNCT and remove the cell
- * from gailview->cell_data. If row_path is NULL then the row has
- * been removed.
- */
- if (row_path == NULL)
- {
- clean_cell_info (gailview, cur_list);
- }
- else
- {
- gtk_tree_path_free (row_path);
- }
+ clean_cell_info (gailview, cell_info);
+ }
+ else
+ {
+ gtk_tree_path_free (row_path);
}
}
}
-static void
+static void
clean_cols (GailTreeView *gailview,
GtkTreeViewColumn *tv_col)
{
- /* Clean GailTreeViewCellInfo data */
+ GailTreeViewCellInfo *cell_info;
+ GHashTableIter iter;
- if (gailview->cell_data != NULL)
+ /* Clean GailTreeViewCellInfo data */
+ g_hash_table_iter_init (&iter, gailview->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cell_info))
{
- GailTreeViewCellInfo *cell_info;
- GList *cur_list, *temp_list;
-
- temp_list = gailview->cell_data;
-
- while (temp_list != NULL)
+ /*
+ * If the cell has become invalid because the column tv_col
+ * has been removed, then set the cell's state to ATK_STATE_DEFUNCT
+ * and remove the cell from gailview->cell_data.
+ */
+ if (cell_info->cell_col_ref == tv_col)
{
- cur_list = temp_list;
- cell_info = temp_list->data;
- temp_list = temp_list->next;
-
- /*
- * If the cell has become invalid because the column tv_col
- * has been removed, then set the cell's state to ATK_STATE_DEFUNCT
- * and remove the cell from gailview->cell_data.
- */
- if (cell_info->cell_col_ref == tv_col)
- {
- clean_cell_info (gailview, cur_list);
- }
+ clean_cell_info (gailview, cell_info);
}
}
}
garbage_collect_cell_data (gpointer data)
{
GailTreeView *tree_view;
- GList *temp_list, *list;
GailTreeViewCellInfo *cell_info;
+ GHashTableIter iter;
g_assert (GAIL_IS_TREE_VIEW (data));
tree_view = (GailTreeView *)data;
- list = g_list_copy (tree_view->cell_data);
tree_view->garbage_collection_pending = FALSE;
if (tree_view->idle_garbage_collect_id != 0)
}
/* Must loop through them all */
- temp_list = list;
- while (temp_list != NULL)
+ g_hash_table_iter_init (&iter, tree_view->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
{
- cell_info = temp_list->data;
if (!cell_info->in_use)
{
/* g_object_unref (cell_info->cell); */
- tree_view->cell_data = g_list_remove (tree_view->cell_data,
- cell_info);
if (cell_info->cell_row_ref)
gtk_tree_row_reference_free (cell_info->cell_row_ref);
g_free (cell_info);
+ g_hash_table_iter_remove (&iter);
}
- temp_list = temp_list->next;
}
- g_list_free (list);
return tree_view->garbage_collection_pending;
}
gboolean set_stale,
gboolean inc_row)
{
- if (tree_view->cell_data != NULL)
- {
- GailTreeViewCellInfo *cell_info;
- GtkTreeView *gtk_tree_view;
- GList *temp_list;
- GtkWidget *widget;
+ GailTreeViewCellInfo *cell_info;
+ GtkTreeView *gtk_tree_view;
+ GtkWidget *widget;
+ GHashTableIter iter;
- g_assert (GTK_IS_ACCESSIBLE (tree_view));
+ g_assert (GTK_IS_ACCESSIBLE (tree_view));
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (tree_view));
- if (!widget)
- /* Widget is being deleted */
- return;
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (tree_view));
+ if (!widget)
+ /* Widget is being deleted */
+ return;
- gtk_tree_view = GTK_TREE_VIEW (widget);
- temp_list = tree_view->cell_data;
+ gtk_tree_view = GTK_TREE_VIEW (widget);
- /* Must loop through them all */
- while (temp_list != NULL)
- {
- GtkTreePath *row_path;
- gboolean act_on_cell;
+ /* Must loop through them all */
+ g_hash_table_iter_init (&iter, tree_view->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cell_info))
+ {
+ GtkTreePath *row_path;
+ gboolean act_on_cell;
- cell_info = temp_list->data;
- temp_list = temp_list->next;
+ if (cell_info->in_use)
+ {
+ row_path = gtk_tree_row_reference_get_path (cell_info->cell_row_ref);
+ g_return_if_fail (row_path != NULL);
+ if (tree_path == NULL)
+ act_on_cell = TRUE;
+ else
+ {
+ gint comparison;
- if (cell_info->in_use)
- {
- row_path = gtk_tree_row_reference_get_path (cell_info->cell_row_ref);
- g_return_if_fail (row_path != NULL);
- if (tree_path == NULL)
- act_on_cell = TRUE;
- else
- {
- gint comparison;
-
- comparison = gtk_tree_path_compare (row_path, tree_path);
- if ((comparison > 0) ||
- (comparison == 0 && inc_row))
- act_on_cell = TRUE;
- else
- act_on_cell = FALSE;
- }
- if (!cell_info->in_use) g_warning ("warning: cell info destroyed during traversal");
- if (act_on_cell && cell_info->in_use)
- {
- if (set_stale)
- gail_cell_add_state (cell_info->cell, ATK_STATE_STALE, TRUE);
- set_cell_visibility (gtk_tree_view,
- cell_info->cell,
- cell_info->cell_col_ref,
- row_path, TRUE);
- }
- gtk_tree_path_free (row_path);
- }
- }
+ comparison = gtk_tree_path_compare (row_path, tree_path);
+ if ((comparison > 0) ||
+ (comparison == 0 && inc_row))
+ act_on_cell = TRUE;
+ else
+ act_on_cell = FALSE;
+ }
+ if (!cell_info->in_use) g_warning ("warning: cell info destroyed during traversal");
+ if (act_on_cell && cell_info->in_use)
+ {
+ if (set_stale)
+ gail_cell_add_state (cell_info->cell, ATK_STATE_STALE, TRUE);
+ set_cell_visibility (gtk_tree_view,
+ cell_info->cell,
+ cell_info->cell_col_ref,
+ row_path, TRUE);
+ }
+ gtk_tree_path_free (row_path);
+ }
}
+
g_signal_emit_by_name (tree_view, "visible-data-changed");
}
GtkTreePath *tree_path,
gboolean set_on_ancestor)
{
- if (gailview->cell_data != NULL)
+ GtkTreeViewColumn *expander_tv;
+ GailTreeViewCellInfo *cell_info;
+ GtkTreePath *cell_path;
+ GtkTreeIter iter;
+ gboolean found;
+ GHashTableIter hash_iter;
+
+ g_hash_table_iter_init (&hash_iter, gailview->cell_info_by_index);
+ while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer *) &cell_info))
{
- GtkTreeViewColumn *expander_tv;
- GailTreeViewCellInfo *cell_info;
- GList *temp_list;
- GtkTreePath *cell_path;
- GtkTreeIter iter;
- gboolean found;
+ if (cell_info->in_use)
+ {
+ cell_path = gtk_tree_row_reference_get_path (cell_info->cell_row_ref);
+ found = FALSE;
- temp_list = gailview->cell_data;
+ if (cell_path != NULL)
+ {
+ GailCell *cell = GAIL_CELL (cell_info->cell);
- while (temp_list != NULL)
- {
- cell_info = temp_list->data;
- temp_list = temp_list->next;
- if (cell_info->in_use)
- {
- cell_path = gtk_tree_row_reference_get_path (cell_info->cell_row_ref);
- found = FALSE;
-
- if (cell_path != NULL)
- {
- GailCell *cell = GAIL_CELL (cell_info->cell);
-
- expander_tv = gtk_tree_view_get_expander_column (tree_view);
-
- /*
- * Only set state for the cell that is in the column with the
- * expander toggle
- */
- if (expander_tv == cell_info->cell_col_ref)
- {
- if (tree_path && gtk_tree_path_compare (cell_path, tree_path) == 0)
- found = TRUE;
- else if (set_on_ancestor &&
- gtk_tree_path_get_depth (cell_path) <
- gtk_tree_path_get_depth (tree_path) &&
- gtk_tree_path_is_ancestor (cell_path, tree_path) == 1)
- /* Only set if set_on_ancestor was passed in as TRUE */
- found = TRUE;
- }
-
- /*
- * Set ATK_STATE_EXPANDABLE and ATK_STATE_EXPANDED
- * for ancestors and found cells.
- */
- if (found)
- {
- /*
- * Must check against cell_path since cell_path
- * can be equal to or an ancestor of tree_path.
- */
- gtk_tree_model_get_iter (tree_model, &iter, cell_path);
-
- /* Set or unset ATK_STATE_EXPANDABLE as appropriate */
- if (gtk_tree_model_iter_has_child (tree_model, &iter))
- {
- set_cell_expandable (cell);
-
- if (gtk_tree_view_row_expanded (tree_view, cell_path))
- gail_cell_add_state (cell, ATK_STATE_EXPANDED, TRUE);
- else
- gail_cell_remove_state (cell,
- ATK_STATE_EXPANDED, TRUE);
- }
- else
- {
- gail_cell_remove_state (cell,
- ATK_STATE_EXPANDED, TRUE);
- if (gail_cell_remove_state (cell,
- ATK_STATE_EXPANDABLE, TRUE))
- /* The state may have been propagated to the container cell */
- if (!GAIL_IS_CONTAINER_CELL (cell))
- gail_cell_remove_action_by_name (cell,
- "expand or contract");
- }
-
- /*
- * We assume that each cell in the cache once and
- * a container cell is before its child cells so we are
- * finished if set_on_ancestor is not set to TRUE.
- */
- if (!set_on_ancestor)
- break;
- }
- }
- gtk_tree_path_free (cell_path);
- }
- }
+ expander_tv = gtk_tree_view_get_expander_column (tree_view);
+
+ /* Only set state for the cell that is in the column with the
+ * expander toggle
+ */
+ if (expander_tv == cell_info->cell_col_ref)
+ {
+ if (tree_path && gtk_tree_path_compare (cell_path, tree_path) == 0)
+ found = TRUE;
+ else if (set_on_ancestor &&
+ gtk_tree_path_get_depth (cell_path) <
+ gtk_tree_path_get_depth (tree_path) &&
+ gtk_tree_path_is_ancestor (cell_path, tree_path) == 1)
+ /* Only set if set_on_ancestor was passed in as TRUE */
+ found = TRUE;
+ }
+
+ /* Set ATK_STATE_EXPANDABLE and ATK_STATE_EXPANDED
+ * for ancestors and found cells.
+ */
+ if (found)
+ {
+ /* Must check against cell_path since cell_path
+ * can be equal to or an ancestor of tree_path.
+ */
+ gtk_tree_model_get_iter (tree_model, &iter, cell_path);
+
+ /* Set or unset ATK_STATE_EXPANDABLE as appropriate */
+ if (gtk_tree_model_iter_has_child (tree_model, &iter))
+ {
+ set_cell_expandable (cell);
+
+ if (gtk_tree_view_row_expanded (tree_view, cell_path))
+ gail_cell_add_state (cell, ATK_STATE_EXPANDED, TRUE);
+ else
+ gail_cell_remove_state (cell,
+ ATK_STATE_EXPANDED, TRUE);
+ }
+ else
+ {
+ gail_cell_remove_state (cell,
+ ATK_STATE_EXPANDED, TRUE);
+ if (gail_cell_remove_state (cell,
+ ATK_STATE_EXPANDABLE, TRUE))
+ /* The state may have been propagated to the container cell */
+ if (!GAIL_IS_CONTAINER_CELL (cell))
+ gail_cell_remove_action_by_name (cell,
+ "expand or contract");
+ }
+
+ /* We assume that each cell in the cache once and
+ * a container cell is before its child cells so we are
+ * finished if set_on_ancestor is not set to TRUE.
+ */
+ if (!set_on_ancestor)
+ break;
+ }
+ }
+ gtk_tree_path_free (cell_path);
+ }
}
}
if (GAIL_IS_CONTAINER_CELL (parent))
parent = atk_object_get_parent (parent);
- cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, NULL, TRUE);
+ cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, TRUE);
gail_return_if_fail (cell_info);
gail_return_if_fail (cell_info->cell_col_ref);
gail_return_if_fail (cell_info->cell_row_ref);
parent = atk_object_get_parent (parent);
}
- cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, NULL, TRUE);
+ cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, TRUE);
gail_return_if_fail (cell_info);
gail_return_if_fail (cell_info->cell_col_ref);
gail_return_if_fail (cell_info->cell_row_ref);
if (GAIL_IS_CONTAINER_CELL (parent))
parent = atk_object_get_parent (parent);
- cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, NULL, TRUE);
+ cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, TRUE);
gail_return_if_fail (cell_info);
gail_return_if_fail (cell_info->cell_col_ref);
gail_return_if_fail (cell_info->cell_row_ref);
if (GAIL_IS_CONTAINER_CELL (parent))
parent = atk_object_get_parent (parent);
- cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, NULL, TRUE);
+ cell_info = find_cell_info (GAIL_TREE_VIEW (parent), cell, TRUE);
gail_return_if_fail (cell_info);
gail_return_if_fail (cell_info->cell_col_ref);
gail_return_if_fail (cell_info->cell_row_ref);
}
}
-#if 0
-static void
-cell_info_remove (GailTreeView *tree_view,
- GailCell *cell)
-{
- GailTreeViewCellInfo *info;
- GList *temp_list;
-
- info = find_cell_info (tree_view, cell, &temp_list, FALSE);
- if (info)
- {
- info->in_use = FALSE;
- return;
- }
- g_warning ("No cell removed in cell_info_remove\n");
-}
-#endif
-
static void
cell_info_get_index (GtkTreeView *tree_view,
GailTreeViewCellInfo *info,
}
static void
-cell_info_new (GailTreeView *gailview,
- GtkTreeModel *tree_model,
+cell_info_new (GailTreeView *gailview,
+ GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeViewColumn *tv_col,
GailCell *cell )
cell_info->cell = cell;
cell_info->in_use = TRUE; /* if we've created it, assume it's in use */
cell_info->view = gailview;
- gailview->cell_data = g_list_append (gailview->cell_data, cell_info);
-
+ g_hash_table_insert (gailview->cell_info_by_index, &cell->index, cell_info);
+
/* Setup weak reference notification */
g_object_weak_ref (G_OBJECT (cell),
gint index)
{
GailTreeViewCellInfo *info;
- GtkTreeView *tree_view;
- GList *cell_list;
- GList *l;
- gint real_index;
- gboolean needs_cleaning = FALSE;
GailCell *retval = NULL;
- tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (gailview)));
- cell_list = gailview->cell_data;
-
- for (l = cell_list; l; l = l->next)
- {
- info = (GailTreeViewCellInfo *) (l->data);
- if (info->in_use)
- {
- cell_info_get_index (tree_view, info, &real_index);
- if (index == real_index)
- {
- retval = info->cell;
- break;
- }
- }
- else
- {
- needs_cleaning = TRUE;
- }
- }
- if (needs_cleaning)
- garbage_collect_cell_data (gailview);
+ info = g_hash_table_lookup (gailview->cell_info_by_index, &index);
+ if (info != NULL)
+ retval = info->cell;
return retval;
}
GailTreeViewCellInfo *info;
AtkObject *parent;
GtkTreeView *tree_view;
+ GailTreeView *gailview;
gint index;
parent = atk_object_get_parent (ATK_OBJECT (cell));
gail_return_if_fail (GAIL_IS_TREE_VIEW (parent));
+ gailview = GAIL_TREE_VIEW (parent);
tree_view = GTK_TREE_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)));
/* Find this cell in the GailTreeView's cache */
- info = find_cell_info (GAIL_TREE_VIEW (parent), cell, NULL, TRUE);
+ info = find_cell_info (gailview, cell, TRUE);
gail_return_if_fail (info);
cell_info_get_index (tree_view, info, &index);
cell->index = index;
+ g_hash_table_insert (gailview->cell_info_by_index, &index, info);
}
static void
}
static void
-disconnect_model_signals (GailTreeView *view)
+disconnect_model_signals (GailTreeView *view)
{
GObject *obj;
GtkWidget *widget;
static void
clear_cached_data (GailTreeView *view)
{
- GList *temp_list;
+ GailTreeViewCellInfo *cell_info;
+ GHashTableIter iter;
if (view->row_data)
{
gint i;
/*
- * Since the third argument to free_row_info is FALSE, we don't remove
+ * Since the third argument to free_row_info is FALSE, we don't remove
* the element. Therefore it is safe to loop forward.
*/
for (i = 0; i < array->len; i++)
view->row_data = NULL;
}
- if (view->cell_data)
+ /* Must loop through them all */
+ g_hash_table_iter_init (&iter, view->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cell_info))
{
- /* Must loop through them all */
- for (temp_list = view->cell_data; temp_list; temp_list = temp_list->next)
- {
- clean_cell_info (view, temp_list);
- }
+ clean_cell_info (view, cell_info);
}
+
+ /* FIXME: seems pretty inefficient to loop again here */
garbage_collect_cell_data (view);
- if (view->cell_data)
- g_list_free (view->cell_data);
-
- view->cell_data = NULL;
}
/*
GtkTreeViewColumn *column,
gboolean visible)
{
- GList *temp_list, *column_list;
GtkTreeViewColumn *tv_column;
gint ret_val;
+ gint i;
+ AtkObject *atk_obj;
+ GailTreeView *gailview;
+
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
+ gailview = GAIL_TREE_VIEW (atk_obj);
- column_list = gtk_tree_view_get_columns (tree_view);
ret_val = 0;
- for (temp_list = column_list; temp_list; temp_list = temp_list->next)
+ for (i = 0; i < gailview->col_data->len; i++)
{
- tv_column = GTK_TREE_VIEW_COLUMN (temp_list->data);
+ tv_column = g_array_index (gailview->col_data, GtkTreeViewColumn *, i);
if (tv_column == column)
break;
if (!visible || gtk_tree_view_column_get_visible (tv_column))
ret_val++;
}
- if (temp_list == NULL)
+ if (i == gailview->col_data->len)
{
ret_val = -1;
}
- g_list_free (column_list);
+
return ret_val;
-}
+}
static gint
-get_index (GtkTreeView *tree_view,
- GtkTreePath *path,
- gint actual_column)
+get_index (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ gint actual_column)
{
+ AtkObject *atk_obj;
+ GailTreeView *gailview;
gint depth = 0;
gint index = 1;
gint *indices = NULL;
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
+ gailview = GAIL_TREE_VIEW (atk_obj);
if (path)
{
if (path)
index += indices[depth-1];
- index *= get_n_actual_columns (tree_view);
+ index *= gailview->n_cols;
index += actual_column;
return index;
}
gtk_tree_path_to_string (gtk_tree_model_get_path (model, iter)));
#endif
+ if (gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY)
+ return;
+
if (level >= depth)
return;
*tree_path = NULL;
return FALSE;
}
- }
-}
-
-/*
- * This function returns the number of rows, including those which are collapsed
- */
-static gint
-get_row_count (GtkTreeModel *model)
-{
- gint n_rows = 1;
-
- count_rows (model, NULL, NULL, &n_rows, 0, G_MAXINT);
-
- return n_rows;
+ }
}
static gboolean
GtkTreeViewColumn **column)
{
GtkTreeModel *tree_model;
- gint n_columns;
+ AtkObject *atk_obj;
+ GailTreeView *gailview;
+
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (tree_view));
+ gailview = GAIL_TREE_VIEW (atk_obj);
tree_model = gtk_tree_view_get_model (tree_view);
- n_columns = get_n_actual_columns (tree_view);
- if (n_columns == 0)
+ if (gailview->n_cols == 0)
return FALSE;
/* First row is the column headers */
- index -= n_columns;
+ index -= gailview->n_cols;
if (index < 0)
return FALSE;
gint row_index;
gboolean retval;
- row_index = index / n_columns;
+ row_index = index / gailview->n_cols;
retval = get_tree_path_from_row_index (tree_model, row_index, path);
gail_return_val_if_fail (retval, FALSE);
if (*path == NULL)
if (column)
{
- *column = gtk_tree_view_get_column (tree_view, index % n_columns);
+ *column = gtk_tree_view_get_column (tree_view, index % gailview->n_cols);
if (*column == NULL)
{
if (path)
static GailTreeViewCellInfo*
find_cell_info (GailTreeView *view,
GailCell *cell,
- GList** list,
- gboolean live_only)
+ gboolean live_only)
{
- GList *temp_list;
GailTreeViewCellInfo *cell_info;
+ GHashTableIter iter;
- for (temp_list = view->cell_data; temp_list; temp_list = temp_list->next)
+ /* Clean GailTreeViewCellInfo data */
+ g_hash_table_iter_init (&iter, view->cell_info_by_index);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cell_info))
{
- cell_info = (GailTreeViewCellInfo *) temp_list->data;
if (cell_info->cell == cell && (!live_only || cell_info->in_use))
- {
- if (list)
- *list = temp_list;
- return cell_info;
- }
+ return cell_info;
}
return NULL;
}