X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktreeselection.c;h=10c9cd717a6908cf686251f22bd0ee58fb1e49d4;hb=HEAD;hp=a004b6c4df65628ad656977e80ba092c35a87de1;hpb=94eec042676a8e18cebc9af8f27cd251355f4ba4;p=~andy%2Fgtk diff --git a/gtk/gtktreeselection.c b/gtk/gtktreeselection.c index a004b6c4d..10c9cd717 100644 --- a/gtk/gtktreeselection.c +++ b/gtk/gtktreeselection.c @@ -12,22 +12,62 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ -#include +#include "config.h" #include #include "gtktreeselection.h" #include "gtktreeprivate.h" #include "gtkrbtree.h" #include "gtkmarshalers.h" #include "gtkintl.h" -#include "gtkalias.h" +#include "gtktypebuiltins.h" +#include "a11y/gtktreeviewaccessibleprivate.h" -static void gtk_tree_selection_init (GtkTreeSelection *selection); -static void gtk_tree_selection_class_init (GtkTreeSelectionClass *class); + +/** + * SECTION:gtktreeselection + * @Short_description: The selection object for GtkTreeView + * @Title: GtkTreeSelection + * @See_also: #GtkTreeView, #GtkTreeViewColumn, #GtkTreeDnd, #GtkTreeMode, + * #GtkTreeSortable, #GtkTreeModelSort, #GtkListStore, #GtkTreeStore, + * #GtkCellRenderer, #GtkCellEditable, #GtkCellRendererPixbuf, + * #GtkCellRendererText, #GtkCellRendererToggle + * + * The #GtkTreeSelection object is a helper object to manage the selection + * for a #GtkTreeView widget. The #GtkTreeSelection object is + * automatically created when a new #GtkTreeView widget is created, and + * cannot exist independentally of this widget. The primary reason the + * #GtkTreeSelection objects exists is for cleanliness of code and API. + * That is, there is no conceptual reason all these functions could not be + * methods on the #GtkTreeView widget instead of a separate function. + * + * The #GtkTreeSelection object is gotten from a #GtkTreeView by calling + * gtk_tree_view_get_selection(). It can be manipulated to check the + * selection status of the tree, as well as select and deselect individual + * rows. Selection is done completely view side. As a result, multiple + * views of the same model can have completely different selections. + * Additionally, you cannot change the selection of a row on the model that + * is not currently displayed by the view without expanding its parents + * first. + * + * One of the important things to remember when monitoring the selection of + * a view is that the #GtkTreeSelection::changed signal is mostly a hint. + * That is, it may only emit one signal when a range of rows is selected. + * Additionally, it may on occasion emit a #GtkTreeSelection::changed signal + * when nothing has happened (mostly as a result of programmers calling + * select_row on an already selected row). + */ + +struct _GtkTreeSelectionPrivate +{ + GtkTreeView *tree_view; + GtkSelectionMode type; + GtkTreeSelectionFunc user_func; + gpointer user_data; + GDestroyNotify destroy; +}; static void gtk_tree_selection_finalize (GObject *object); static gint gtk_tree_selection_real_select_all (GtkTreeSelection *selection); @@ -36,6 +76,21 @@ static gint gtk_tree_selection_real_select_node (GtkTreeSelection *selecti GtkRBTree *tree, GtkRBNode *node, gboolean select); +static void gtk_tree_selection_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_tree_selection_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +enum +{ + PROP_0, + PROP_MODE, + N_PROPERTIES +}; enum { @@ -43,36 +98,10 @@ enum LAST_SIGNAL }; -static GObjectClass *parent_class = NULL; +static GParamSpec *properties[N_PROPERTIES]; static guint tree_selection_signals [LAST_SIGNAL] = { 0 }; -GType -gtk_tree_selection_get_type (void) -{ - static GType selection_type = 0; - - if (!selection_type) - { - static const GTypeInfo selection_info = - { - sizeof (GtkTreeSelectionClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gtk_tree_selection_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkTreeSelection), - 0, /* n_preallocs */ - (GInstanceInitFunc) gtk_tree_selection_init - }; - - selection_type = - g_type_register_static (G_TYPE_OBJECT, I_("GtkTreeSelection"), - &selection_info, 0); - } - - return selection_type; -} +G_DEFINE_TYPE (GtkTreeSelection, gtk_tree_selection, G_TYPE_OBJECT) static void gtk_tree_selection_class_init (GtkTreeSelectionClass *class) @@ -80,11 +109,44 @@ gtk_tree_selection_class_init (GtkTreeSelectionClass *class) GObjectClass *object_class; object_class = (GObjectClass*) class; - parent_class = g_type_class_peek_parent (class); object_class->finalize = gtk_tree_selection_finalize; + object_class->set_property = gtk_tree_selection_set_property; + object_class->get_property = gtk_tree_selection_get_property; class->changed = NULL; + /* Properties */ + + /** + * GtkTreeSelection:mode: + * + * Selection mode. + * See gtk_tree_selection_set_mode() for more information on this property. + * + * Since: 3.2 + */ + properties[PROP_MODE] = g_param_spec_enum ("mode", + P_("Mode"), + P_("Selection mode"), + GTK_TYPE_SELECTION_MODE, + GTK_SELECTION_SINGLE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /* Install all properties */ + g_object_class_install_properties (object_class, N_PROPERTIES, properties); + + /* Signals */ + + /** + * GtkTreeSelection::changed: + * @treeselection: the object which received the signal. + * + * Emitted whenever the selection has (possibly) changed. Please note that + * this signal is mostly a hint. It may only be emitted once when a range + * of rows are selected, and it may occasionally be emitted when nothing + * has happened. + */ tree_selection_signals[CHANGED] = g_signal_new (I_("changed"), G_OBJECT_CLASS_TYPE (object_class), @@ -93,29 +155,72 @@ gtk_tree_selection_class_init (GtkTreeSelectionClass *class) NULL, NULL, _gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); + + g_type_class_add_private (class, sizeof (GtkTreeSelectionPrivate)); } static void gtk_tree_selection_init (GtkTreeSelection *selection) { - selection->type = GTK_SELECTION_SINGLE; + GtkTreeSelectionPrivate *priv; + + selection->priv = G_TYPE_INSTANCE_GET_PRIVATE (selection, + GTK_TYPE_TREE_SELECTION, + GtkTreeSelectionPrivate); + priv = selection->priv; + + priv->type = GTK_SELECTION_SINGLE; } static void gtk_tree_selection_finalize (GObject *object) { GtkTreeSelection *selection = GTK_TREE_SELECTION (object); + GtkTreeSelectionPrivate *priv = selection->priv; - if (selection->destroy) - { - GtkDestroyNotify d = selection->destroy; + if (priv->destroy) + priv->destroy (priv->user_data); + + /* chain parent_class' handler */ + G_OBJECT_CLASS (gtk_tree_selection_parent_class)->finalize (object); +} + +static void +gtk_tree_selection_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (GTK_IS_TREE_SELECTION (object)); - selection->destroy = NULL; - d (selection->user_data); + switch (prop_id) + { + case PROP_MODE: + gtk_tree_selection_set_mode (GTK_TREE_SELECTION (object), g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } +} - /* chain parent_class' handler */ - G_OBJECT_CLASS (parent_class)->finalize (object); +static void +gtk_tree_selection_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (GTK_IS_TREE_SELECTION (object)); + + switch (prop_id) + { + case PROP_MODE: + g_value_set_enum (value, gtk_tree_selection_get_mode (GTK_TREE_SELECTION (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } /** @@ -170,11 +275,15 @@ void _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection, GtkTreeView *tree_view) { + GtkTreeSelectionPrivate *priv; + g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); if (tree_view != NULL) g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - selection->tree_view = tree_view; + priv = selection->priv; + + priv->tree_view = tree_view; } /** @@ -190,24 +299,26 @@ void gtk_tree_selection_set_mode (GtkTreeSelection *selection, GtkSelectionMode type) { + GtkTreeSelectionPrivate *priv; GtkTreeSelectionFunc tmp_func; + g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - if (selection->type == type) + priv = selection->priv; + + if (priv->type == type) return; - if (type == GTK_SELECTION_NONE) { /* We do this so that we unconditionally unset all rows */ - tmp_func = selection->user_func; - selection->user_func = NULL; + tmp_func = priv->user_func; + priv->user_func = NULL; gtk_tree_selection_unselect_all (selection); - selection->user_func = tmp_func; + priv->user_func = tmp_func; - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - selection->tree_view->priv->anchor = NULL; + _gtk_tree_view_set_anchor_path (priv->tree_view, NULL); } else if (type == GTK_SELECTION_SINGLE || type == GTK_SELECTION_BROWSE) @@ -217,28 +328,25 @@ gtk_tree_selection_set_mode (GtkTreeSelection *selection, gint selected = FALSE; GtkTreePath *anchor_path = NULL; - if (selection->tree_view->priv->anchor) + anchor_path = _gtk_tree_view_get_anchor_path (priv->tree_view); + + if (anchor_path) { - anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor); - - if (anchor_path) - { - _gtk_tree_view_find_node (selection->tree_view, - anchor_path, - &tree, - &node); - - if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) - selected = TRUE; - } + _gtk_tree_view_find_node (priv->tree_view, + anchor_path, + &tree, + &node); + + if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) + selected = TRUE; } /* We do this so that we unconditionally unset all rows */ - tmp_func = selection->user_func; - selection->user_func = NULL; + tmp_func = priv->user_func; + priv->user_func = NULL; gtk_tree_selection_unselect_all (selection); - selection->user_func = tmp_func; + priv->user_func = tmp_func; if (node && selected) _gtk_tree_selection_internal_select_node (selection, @@ -251,7 +359,9 @@ gtk_tree_selection_set_mode (GtkTreeSelection *selection, gtk_tree_path_free (anchor_path); } - selection->type = type; + priv->type = type; + + g_object_notify_by_pspec (G_OBJECT (selection), properties[PROP_MODE]); } /** @@ -268,45 +378,63 @@ gtk_tree_selection_get_mode (GtkTreeSelection *selection) { g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), GTK_SELECTION_SINGLE); - return selection->type; + return selection->priv->type; } /** * gtk_tree_selection_set_select_function: * @selection: A #GtkTreeSelection. - * @func: The selection function. - * @data: The selection function's data. - * @destroy: The destroy function for user data. May be NULL. + * @func: The selection function. May be %NULL + * @data: The selection function's data. May be %NULL + * @destroy: The destroy function for user data. May be %NULL * - * Sets the selection function. If set, this function is called before any node - * is selected or unselected, giving some control over which nodes are selected. - * The select function should return %TRUE if the state of the node may be toggled, - * and %FALSE if the state of the node should be left unchanged. - **/ + * Sets the selection function. + * + * If set, this function is called before any node is selected or unselected, + * giving some control over which nodes are selected. The select function + * should return %TRUE if the state of the node may be toggled, and %FALSE + * if the state of the node should be left unchanged. + */ void gtk_tree_selection_set_select_function (GtkTreeSelection *selection, GtkTreeSelectionFunc func, gpointer data, - GtkDestroyNotify destroy) + GDestroyNotify destroy) { + GtkTreeSelectionPrivate *priv; + g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (func != NULL); - if (selection->destroy) - { - GtkDestroyNotify d = selection->destroy; + priv = selection->priv; - selection->destroy = NULL; - d (selection->user_data); - } + if (priv->destroy) + priv->destroy (priv->user_data); - selection->user_func = func; - selection->user_data = data; - selection->destroy = destroy; + priv->user_func = func; + priv->user_data = data; + priv->destroy = destroy; } /** - * gtk_tree_selection_get_user_data: + * gtk_tree_selection_get_select_function: (skip) + * @selection: A #GtkTreeSelection. + * + * Returns the current selection function. + * + * Return value: The function. + * + * Since: 2.14 + **/ +GtkTreeSelectionFunc +gtk_tree_selection_get_select_function (GtkTreeSelection *selection) +{ + g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL); + + return selection->priv->user_func; +} + +/** + * gtk_tree_selection_get_user_data: (skip) * @selection: A #GtkTreeSelection. * * Returns the user data for the selection function. @@ -318,7 +446,7 @@ gtk_tree_selection_get_user_data (GtkTreeSelection *selection) { g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL); - return selection->user_data; + return selection->priv->user_data; } /** @@ -327,21 +455,21 @@ gtk_tree_selection_get_user_data (GtkTreeSelection *selection) * * Returns the tree view associated with @selection. * - * Return value: A #GtkTreeView + * Return value: (transfer none): A #GtkTreeView **/ GtkTreeView * gtk_tree_selection_get_tree_view (GtkTreeSelection *selection) { g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL); - return selection->tree_view; + return selection->priv->tree_view; } /** * gtk_tree_selection_get_selected: * @selection: A #GtkTreeSelection. - * @model: A pointer to set to the #GtkTreeModel, or NULL. - * @iter: The #GtkTreeIter, or NULL. + * @model: (out) (allow-none) (transfer none): A pointer to set to the #GtkTreeModel, or NULL. + * @iter: (out) (allow-none): The #GtkTreeIter, or NULL. * * Sets @iter to the currently selected node if @selection is set to * #GTK_SELECTION_SINGLE or #GTK_SELECTION_BROWSE. @iter may be NULL if you @@ -356,6 +484,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, GtkTreeModel **model, GtkTreeIter *iter) { + GtkTreeSelectionPrivate *priv; GtkRBTree *tree; GtkRBNode *node; GtkTreePath *anchor_path; @@ -363,27 +492,27 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, gboolean found_node; g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE); - g_return_val_if_fail (selection->type != GTK_SELECTION_MULTIPLE, FALSE); - g_return_val_if_fail (selection->tree_view != NULL, FALSE); + + priv = selection->priv; + + g_return_val_if_fail (priv->type != GTK_SELECTION_MULTIPLE, FALSE); + g_return_val_if_fail (priv->tree_view != NULL, FALSE); /* Clear the iter */ if (iter) memset (iter, 0, sizeof (GtkTreeIter)); if (model) - *model = selection->tree_view->priv->model; - - if (selection->tree_view->priv->anchor == NULL) - return FALSE; + *model = gtk_tree_view_get_model (priv->tree_view); - anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor); + anchor_path = _gtk_tree_view_get_anchor_path (priv->tree_view); if (anchor_path == NULL) return FALSE; retval = FALSE; - found_node = !_gtk_tree_view_find_node (selection->tree_view, + found_node = !_gtk_tree_view_find_node (priv->tree_view, anchor_path, &tree, &node); @@ -396,7 +525,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, if (iter == NULL) retval = TRUE; else - retval = gtk_tree_model_get_iter (selection->tree_view->priv->model, + retval = gtk_tree_model_get_iter (gtk_tree_view_get_model (priv->tree_view), iter, anchor_path); } @@ -415,7 +544,7 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, /** * gtk_tree_selection_get_selected_rows: * @selection: A #GtkTreeSelection. - * @model: A pointer to set to the #GtkTreeModel, or NULL. + * @model: (out) (allow-none) (transfer none): A pointer to set to the #GtkTreeModel, or %NULL. * * Creates a list of path of all selected rows. Additionally, if you are * planning on modifying the model after calling this function, you may @@ -423,12 +552,11 @@ gtk_tree_selection_get_selected (GtkTreeSelection *selection, * To do this, you can use gtk_tree_row_reference_new(). * * To free the return value, use: - * - * g_list_foreach (list, gtk_tree_path_free, NULL); - * g_list_free (list); - * + * |[ + * g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); + * ]| * - * Return value: A #GList containing a #GtkTreePath for each selected row. + * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row. * * Since: 2.2 **/ @@ -436,24 +564,29 @@ GList * gtk_tree_selection_get_selected_rows (GtkTreeSelection *selection, GtkTreeModel **model) { + GtkTreeSelectionPrivate *priv; GList *list = NULL; GtkRBTree *tree = NULL; GtkRBNode *node = NULL; GtkTreePath *path; g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL); - g_return_val_if_fail (selection->tree_view != NULL, NULL); - if (selection->tree_view->priv->tree == NULL || - selection->tree_view->priv->tree->root == NULL) - return NULL; + priv = selection->priv; + + g_return_val_if_fail (priv->tree_view != NULL, NULL); if (model) - *model = selection->tree_view->priv->model; + *model = gtk_tree_view_get_model (priv->tree_view); + + tree = _gtk_tree_view_get_rbtree (priv->tree_view); + + if (tree == NULL || tree->root == NULL) + return NULL; - if (selection->type == GTK_SELECTION_NONE) + if (priv->type == GTK_SELECTION_NONE) return NULL; - else if (selection->type != GTK_SELECTION_MULTIPLE) + else if (priv->type != GTK_SELECTION_MULTIPLE) { GtkTreeIter iter; @@ -461,7 +594,7 @@ gtk_tree_selection_get_selected_rows (GtkTreeSelection *selection, { GtkTreePath *path; - path = gtk_tree_model_get_path (selection->tree_view->priv->model, &iter); + path = gtk_tree_model_get_path (gtk_tree_view_get_model (priv->tree_view), &iter); list = g_list_append (list, path); return list; @@ -470,11 +603,7 @@ gtk_tree_selection_get_selected_rows (GtkTreeSelection *selection, return NULL; } - tree = selection->tree_view->priv->tree; - node = selection->tree_view->priv->tree->root; - - while (node->left != tree->nil) - node = node->left; + node = _gtk_rbtree_first (tree); path = gtk_tree_path_new_first (); do @@ -485,10 +614,7 @@ gtk_tree_selection_get_selected_rows (GtkTreeSelection *selection, if (node->children) { tree = node->children; - node = tree->root; - - while (node->left != tree->nil) - node = node->left; + node = _gtk_rbtree_first (tree); gtk_tree_path_append_index (path, 0); } @@ -559,19 +685,23 @@ gtk_tree_selection_count_selected_rows_helper (GtkRBTree *tree, gint gtk_tree_selection_count_selected_rows (GtkTreeSelection *selection) { + GtkTreeSelectionPrivate *priv; gint count = 0; GtkRBTree *tree; - GtkRBNode *node; g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), 0); - g_return_val_if_fail (selection->tree_view != NULL, 0); - if (selection->tree_view->priv->tree == NULL || - selection->tree_view->priv->tree->root == NULL) + priv = selection->priv; + + g_return_val_if_fail (priv->tree_view != NULL, 0); + + tree = _gtk_tree_view_get_rbtree (priv->tree_view); + + if (tree == NULL || tree->root == NULL) return 0; - if (selection->type == GTK_SELECTION_SINGLE || - selection->type == GTK_SELECTION_BROWSE) + if (priv->type == GTK_SELECTION_SINGLE || + priv->type == GTK_SELECTION_BROWSE) { if (gtk_tree_selection_get_selected (selection, NULL, NULL)) return 1; @@ -579,11 +709,7 @@ gtk_tree_selection_count_selected_rows (GtkTreeSelection *selection) return 0; } - tree = selection->tree_view->priv->tree; - node = selection->tree_view->priv->tree->root; - - _gtk_rbtree_traverse (selection->tree_view->priv->tree, - selection->tree_view->priv->tree->root, + _gtk_rbtree_traverse (tree, tree->root, G_PRE_ORDER, gtk_tree_selection_count_selected_rows_helper, &count); @@ -603,7 +729,7 @@ model_changed (gpointer data) /** * gtk_tree_selection_selected_foreach: * @selection: A #GtkTreeSelection. - * @func: The function to call for each selected node. + * @func: (scope call): The function to call for each selected node. * @data: user data to pass to the function. * * Calls a function for each selected node. Note that you cannot modify @@ -615,54 +741,60 @@ gtk_tree_selection_selected_foreach (GtkTreeSelection *selection, GtkTreeSelectionForeachFunc func, gpointer data) { + GtkTreeSelectionPrivate *priv; GtkTreePath *path; GtkRBTree *tree; GtkRBNode *node; GtkTreeIter iter; + GtkTreeModel *model; - guint inserted_id, deleted_id, reordered_id; + gulong inserted_id, deleted_id, reordered_id, changed_id; gboolean stop = FALSE; g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); - if (func == NULL || - selection->tree_view->priv->tree == NULL || - selection->tree_view->priv->tree->root == NULL) + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); + + tree = _gtk_tree_view_get_rbtree (priv->tree_view); + + if (func == NULL || tree == NULL || tree->root == NULL) return; - if (selection->type == GTK_SELECTION_SINGLE || - selection->type == GTK_SELECTION_BROWSE) + model = gtk_tree_view_get_model (priv->tree_view); + + if (priv->type == GTK_SELECTION_SINGLE || + priv->type == GTK_SELECTION_BROWSE) { - if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor)) + path = _gtk_tree_view_get_anchor_path (priv->tree_view); + + if (path) { - path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor); - gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path); - (* func) (selection->tree_view->priv->model, path, &iter, data); + gtk_tree_model_get_iter (model, &iter, path); + (* func) (model, path, &iter, data); gtk_tree_path_free (path); } return; } - tree = selection->tree_view->priv->tree; - node = selection->tree_view->priv->tree->root; - - while (node->left != tree->nil) - node = node->left; + node = _gtk_rbtree_first (tree); + + g_object_ref (model); /* connect to signals to monitor changes in treemodel */ - inserted_id = g_signal_connect_swapped (selection->tree_view->priv->model, - "row_inserted", + inserted_id = g_signal_connect_swapped (model, "row-inserted", G_CALLBACK (model_changed), &stop); - deleted_id = g_signal_connect_swapped (selection->tree_view->priv->model, - "row_deleted", + deleted_id = g_signal_connect_swapped (model, "row-deleted", G_CALLBACK (model_changed), &stop); - reordered_id = g_signal_connect_swapped (selection->tree_view->priv->model, - "rows_reordered", + reordered_id = g_signal_connect_swapped (model, "rows-reordered", G_CALLBACK (model_changed), &stop); + changed_id = g_signal_connect_swapped (priv->tree_view, "notify::model", + G_CALLBACK (model_changed), + &stop); /* find the node internally */ path = gtk_tree_path_new_first (); @@ -671,9 +803,8 @@ gtk_tree_selection_selected_foreach (GtkTreeSelection *selection, { if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) { - gtk_tree_model_get_iter (selection->tree_view->priv->model, - &iter, path); - (* func) (selection->tree_view->priv->model, path, &iter, data); + gtk_tree_model_get_iter (model, &iter, path); + (* func) (model, path, &iter, data); } if (stop) @@ -682,10 +813,7 @@ gtk_tree_selection_selected_foreach (GtkTreeSelection *selection, if (node->children) { tree = node->children; - node = tree->root; - - while (node->left != tree->nil) - node = node->left; + node = _gtk_rbtree_first (tree); gtk_tree_path_append_index (path, 0); } @@ -726,20 +854,18 @@ out: if (path) gtk_tree_path_free (path); - g_signal_handler_disconnect (selection->tree_view->priv->model, - inserted_id); - g_signal_handler_disconnect (selection->tree_view->priv->model, - deleted_id); - g_signal_handler_disconnect (selection->tree_view->priv->model, - reordered_id); + g_signal_handler_disconnect (model, inserted_id); + g_signal_handler_disconnect (model, deleted_id); + g_signal_handler_disconnect (model, reordered_id); + g_signal_handler_disconnect (priv->tree_view, changed_id); + g_object_unref (model); /* check if we have to spew a scary message */ if (stop) - g_warning - ("The model has been modified from within gtk_tree_selection_selected_foreach.\n" - "This function is for observing the selections of the tree only. If\n" - "you are trying to get all selected items from the tree, try using\n" - "gtk_tree_selection_get_selected_rows instead.\n"); + g_warning ("The model has been modified from within gtk_tree_selection_selected_foreach.\n" + "This function is for observing the selections of the tree only. If\n" + "you are trying to get all selected items from the tree, try using\n" + "gtk_tree_selection_get_selected_rows instead.\n"); } /** @@ -753,16 +879,20 @@ void gtk_tree_selection_select_path (GtkTreeSelection *selection, GtkTreePath *path) { + GtkTreeSelectionPrivate *priv; GtkRBNode *node; GtkRBTree *tree; gboolean ret; GtkTreeSelectMode mode = 0; g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); + + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); g_return_if_fail (path != NULL); - ret = _gtk_tree_view_find_node (selection->tree_view, + ret = _gtk_tree_view_find_node (priv->tree_view, path, &tree, &node); @@ -771,7 +901,7 @@ gtk_tree_selection_select_path (GtkTreeSelection *selection, ret == TRUE) return; - if (selection->type == GTK_SELECTION_MULTIPLE) + if (priv->type == GTK_SELECTION_MULTIPLE) mode = GTK_TREE_SELECT_MODE_TOGGLE; _gtk_tree_selection_internal_select_node (selection, @@ -793,15 +923,19 @@ void gtk_tree_selection_unselect_path (GtkTreeSelection *selection, GtkTreePath *path) { + GtkTreeSelectionPrivate *priv; GtkRBNode *node; GtkRBTree *tree; gboolean ret; g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); + + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); g_return_if_fail (path != NULL); - ret = _gtk_tree_view_find_node (selection->tree_view, + ret = _gtk_tree_view_find_node (priv->tree_view, path, &tree, &node); @@ -829,15 +963,21 @@ void gtk_tree_selection_select_iter (GtkTreeSelection *selection, GtkTreeIter *iter) { + GtkTreeSelectionPrivate *priv; GtkTreePath *path; + GtkTreeModel *model; g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); - g_return_if_fail (selection->tree_view->priv->model != NULL); + + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); + + model = gtk_tree_view_get_model (priv->tree_view); + g_return_if_fail (model != NULL); g_return_if_fail (iter != NULL); - path = gtk_tree_model_get_path (selection->tree_view->priv->model, - iter); + path = gtk_tree_model_get_path (model, iter); if (path == NULL) return; @@ -858,15 +998,21 @@ void gtk_tree_selection_unselect_iter (GtkTreeSelection *selection, GtkTreeIter *iter) { + GtkTreeSelectionPrivate *priv; GtkTreePath *path; + GtkTreeModel *model; g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); - g_return_if_fail (selection->tree_view->priv->model != NULL); + + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); + + model = gtk_tree_view_get_model (priv->tree_view); + g_return_if_fail (model != NULL); g_return_if_fail (iter != NULL); - path = gtk_tree_model_get_path (selection->tree_view->priv->model, - iter); + path = gtk_tree_model_get_path (model, iter); if (path == NULL) return; @@ -889,18 +1035,22 @@ gboolean gtk_tree_selection_path_is_selected (GtkTreeSelection *selection, GtkTreePath *path) { + GtkTreeSelectionPrivate *priv; GtkRBNode *node; GtkRBTree *tree; gboolean ret; g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE); + + priv = selection->priv; + g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (selection->tree_view != NULL, FALSE); + g_return_val_if_fail (priv->tree_view != NULL, FALSE); - if (selection->tree_view->priv->model == NULL) + if (gtk_tree_view_get_model (priv->tree_view) == NULL) return FALSE; - ret = _gtk_tree_view_find_node (selection->tree_view, + ret = _gtk_tree_view_find_node (priv->tree_view, path, &tree, &node); @@ -925,15 +1075,22 @@ gboolean gtk_tree_selection_iter_is_selected (GtkTreeSelection *selection, GtkTreeIter *iter) { + GtkTreeSelectionPrivate *priv; GtkTreePath *path; + GtkTreeModel *model; gboolean retval; g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE); + + priv = selection->priv; + g_return_val_if_fail (iter != NULL, FALSE); - g_return_val_if_fail (selection->tree_view != NULL, FALSE); - g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE); + g_return_val_if_fail (priv->tree_view != NULL, FALSE); + + model = gtk_tree_view_get_model (priv->tree_view); + g_return_val_if_fail (model != NULL, FALSE); - path = gtk_tree_model_get_path (selection->tree_view->priv->model, iter); + path = gtk_tree_model_get_path (model, iter); if (path == NULL) return FALSE; @@ -976,9 +1133,13 @@ select_all_helper (GtkRBTree *tree, static gint gtk_tree_selection_real_select_all (GtkTreeSelection *selection) { + GtkTreeSelectionPrivate *priv = selection->priv; struct _TempTuple *tuple; + GtkRBTree *tree; + + tree = _gtk_tree_view_get_rbtree (priv->tree_view); - if (selection->tree_view->priv->tree == NULL) + if (tree == NULL) return FALSE; /* Mark all nodes selected */ @@ -986,8 +1147,7 @@ gtk_tree_selection_real_select_all (GtkTreeSelection *selection) tuple->selection = selection; tuple->dirty = FALSE; - _gtk_rbtree_traverse (selection->tree_view->priv->tree, - selection->tree_view->priv->tree->root, + _gtk_rbtree_traverse (tree, tree->root, G_PRE_ORDER, select_all_helper, tuple); @@ -1010,13 +1170,19 @@ gtk_tree_selection_real_select_all (GtkTreeSelection *selection) void gtk_tree_selection_select_all (GtkTreeSelection *selection) { + GtkTreeSelectionPrivate *priv; + g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); - if (selection->tree_view->priv->tree == NULL || selection->tree_view->priv->model == NULL) + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); + + if (_gtk_tree_view_get_rbtree (priv->tree_view) == NULL || + gtk_tree_view_get_model (priv->tree_view) == NULL) return; - g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE); + g_return_if_fail (priv->type == GTK_SELECTION_MULTIPLE); if (gtk_tree_selection_real_select_all (selection)) g_signal_emit (selection, tree_selection_signals[CHANGED], 0); @@ -1041,27 +1207,25 @@ unselect_all_helper (GtkRBTree *tree, } } -static gint +static gboolean gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) { + GtkTreeSelectionPrivate *priv = selection->priv; struct _TempTuple *tuple; - if (selection->type == GTK_SELECTION_SINGLE || - selection->type == GTK_SELECTION_BROWSE) + if (priv->type == GTK_SELECTION_SINGLE || + priv->type == GTK_SELECTION_BROWSE) { GtkRBTree *tree = NULL; GtkRBNode *node = NULL; GtkTreePath *anchor_path; - if (selection->tree_view->priv->anchor == NULL) - return FALSE; - - anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor); + anchor_path = _gtk_tree_view_get_anchor_path (priv->tree_view); if (anchor_path == NULL) return FALSE; - _gtk_tree_view_find_node (selection->tree_view, + _gtk_tree_view_find_node (priv->tree_view, anchor_path, &tree, &node); @@ -1075,8 +1239,7 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) { if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE)) { - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - selection->tree_view->priv->anchor = NULL; + _gtk_tree_view_set_anchor_path (priv->tree_view, NULL); return TRUE; } } @@ -1084,12 +1247,14 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) } else { + GtkRBTree *tree; + tuple = g_new (struct _TempTuple, 1); tuple->selection = selection; tuple->dirty = FALSE; - _gtk_rbtree_traverse (selection->tree_view->priv->tree, - selection->tree_view->priv->tree->root, + tree = _gtk_tree_view_get_rbtree (priv->tree_view); + _gtk_rbtree_traverse (tree, tree->root, G_PRE_ORDER, unselect_all_helper, tuple); @@ -1113,10 +1278,16 @@ gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection) void gtk_tree_selection_unselect_all (GtkTreeSelection *selection) { + GtkTreeSelectionPrivate *priv; + g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); - if (selection->tree_view->priv->tree == NULL || selection->tree_view->priv->model == NULL) + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); + + if (_gtk_tree_view_get_rbtree (priv->tree_view) == NULL || + gtk_tree_view_get_model (priv->tree_view) == NULL) return; if (gtk_tree_selection_real_unselect_all (selection)) @@ -1135,6 +1306,7 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, GtkTreePath *start_path, GtkTreePath *end_path) { + GtkTreeSelectionPrivate *priv = selection->priv; GtkRBNode *start_node, *end_node; GtkRBTree *start_tree, *end_tree; GtkTreePath *anchor_path = NULL; @@ -1143,18 +1315,18 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, switch (gtk_tree_path_compare (start_path, end_path)) { case 1: - _gtk_tree_view_find_node (selection->tree_view, + _gtk_tree_view_find_node (priv->tree_view, end_path, &start_tree, &start_node); - _gtk_tree_view_find_node (selection->tree_view, + _gtk_tree_view_find_node (priv->tree_view, start_path, &end_tree, &end_node); anchor_path = start_path; break; case 0: - _gtk_tree_view_find_node (selection->tree_view, + _gtk_tree_view_find_node (priv->tree_view, start_path, &start_tree, &start_node); @@ -1163,11 +1335,11 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, anchor_path = start_path; break; case -1: - _gtk_tree_view_find_node (selection->tree_view, + _gtk_tree_view_find_node (priv->tree_view, start_path, &start_tree, &start_node); - _gtk_tree_view_find_node (selection->tree_view, + _gtk_tree_view_find_node (priv->tree_view, end_path, &end_tree, &end_node); @@ -1179,15 +1351,7 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, g_return_val_if_fail (end_node != NULL, FALSE); if (anchor_path) - { - if (selection->tree_view->priv->anchor) - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - - selection->tree_view->priv->anchor = - gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), - selection->tree_view->priv->model, - anchor_path); - } + _gtk_tree_view_set_anchor_path (priv->tree_view, anchor_path); do { @@ -1199,9 +1363,7 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, if (start_node->children) { start_tree = start_node->children; - start_node = start_tree->root; - while (start_node->left != start_tree->nil) - start_node = start_node->left; + start_node = _gtk_rbtree_first (start_tree); } else { @@ -1233,10 +1395,15 @@ gtk_tree_selection_select_range (GtkTreeSelection *selection, GtkTreePath *start_path, GtkTreePath *end_path) { + GtkTreeSelectionPrivate *priv; + g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); - g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE); - g_return_if_fail (selection->tree_view->priv->model != NULL); + + priv = selection->priv; + + g_return_if_fail (priv->tree_view != NULL); + g_return_if_fail (priv->type == GTK_SELECTION_MULTIPLE); + g_return_if_fail (gtk_tree_view_get_model (priv->tree_view) != NULL); if (gtk_tree_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path)) g_signal_emit (selection, tree_selection_signals[CHANGED], 0); @@ -1258,84 +1425,50 @@ gtk_tree_selection_unselect_range (GtkTreeSelection *selection, GtkTreePath *start_path, GtkTreePath *end_path) { - g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - g_return_if_fail (selection->tree_view != NULL); - g_return_if_fail (selection->tree_view->priv->model != NULL); - - if (gtk_tree_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path)) - g_signal_emit (selection, tree_selection_signals[CHANGED], 0); -} - -static gboolean -tree_column_is_sensitive (GtkTreeViewColumn *column, - GtkTreeModel *model, - GtkTreeIter *iter) -{ - GList *cells, *list; - gboolean sensitive; - gboolean visible; + GtkTreeSelectionPrivate *priv; - gtk_tree_view_column_cell_set_cell_data (column, model, - iter, FALSE, FALSE); + g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - cells = gtk_tree_view_column_get_cell_renderers (column); + priv = selection->priv; - list = cells; - while (list) - { - g_object_get (list->data, - "sensitive", &sensitive, - "visible", &visible, - NULL); - - if (visible && sensitive) - break; + g_return_if_fail (priv->tree_view != NULL); + g_return_if_fail (gtk_tree_view_get_model (priv->tree_view) != NULL); - list = list->next; - } - g_list_free (cells); - - return sensitive; + if (gtk_tree_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path)) + g_signal_emit (selection, tree_selection_signals[CHANGED], 0); } -static gboolean -row_is_selectable (GtkTreeSelection *selection, - GtkRBNode *node, - GtkTreePath *path) +gboolean +_gtk_tree_selection_row_is_selectable (GtkTreeSelection *selection, + GtkRBNode *node, + GtkTreePath *path) { - GList *list; + GtkTreeSelectionPrivate *priv = selection->priv; GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeViewRowSeparatorFunc separator_func; + gpointer separator_data; gboolean sensitive = FALSE; - if (!gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path)) + model = gtk_tree_view_get_model (priv->tree_view); + + _gtk_tree_view_get_row_separator_func (priv->tree_view, + &separator_func, &separator_data); + + if (!gtk_tree_model_get_iter (model, &iter, path)) sensitive = TRUE; - if (!sensitive && selection->tree_view->priv->row_separator_func) + if (!sensitive && separator_func) { /* never allow separators to be selected */ - if ((* selection->tree_view->priv->row_separator_func) (selection->tree_view->priv->model, - &iter, - selection->tree_view->priv->row_separator_data)) + if ((* separator_func) (model, &iter, separator_data)) return FALSE; } - for (list = selection->tree_view->priv->columns; list && !sensitive; list = list->next) - { - GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (list->data); - - if (!column->visible) - continue; - - sensitive = tree_column_is_sensitive (column, selection->tree_view->priv->model, &iter); - } - - if (!sensitive) - return FALSE; - - if (selection->user_func) - return (*selection->user_func) (selection, selection->tree_view->priv->model, path, + if (priv->user_func) + return (*priv->user_func) (selection, model, path, GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED), - selection->user_data); + priv->user_data); else return TRUE; } @@ -1357,26 +1490,26 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, GtkTreeSelectMode mode, gboolean override_browse_mode) { + GtkTreeSelectionPrivate *priv = selection->priv; gint flags; gint dirty = FALSE; GtkTreePath *anchor_path = NULL; - if (selection->type == GTK_SELECTION_NONE) + if (priv->type == GTK_SELECTION_NONE) return; - if (selection->tree_view->priv->anchor) - anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor); + anchor_path = _gtk_tree_view_get_anchor_path (priv->tree_view); - if (selection->type == GTK_SELECTION_SINGLE || - selection->type == GTK_SELECTION_BROWSE) + if (priv->type == GTK_SELECTION_SINGLE || + priv->type == GTK_SELECTION_BROWSE) { /* just unselect */ - if (selection->type == GTK_SELECTION_BROWSE && override_browse_mode) + if (priv->type == GTK_SELECTION_BROWSE && override_browse_mode) { dirty = gtk_tree_selection_real_unselect_all (selection); } /* Did we try to select the same node again? */ - else if (selection->type == GTK_SELECTION_SINGLE && + else if (priv->type == GTK_SELECTION_SINGLE && anchor_path && gtk_tree_path_compare (path, anchor_path) == 0) { if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE) @@ -1390,7 +1523,7 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, { /* We only want to select the new node if we can unselect the old one, * and we can select the new one. */ - dirty = row_is_selectable (selection, node, path); + dirty = _gtk_tree_selection_row_is_selectable (selection, node, path); /* if dirty is FALSE, we weren't able to select the new one, otherwise, we try to * unselect the new one @@ -1402,17 +1535,11 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, * old one, and can then select the new one */ if (dirty) { - if (selection->tree_view->priv->anchor) - { - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - selection->tree_view->priv->anchor = NULL; - } + + _gtk_tree_view_set_anchor_path (priv->tree_view, NULL); if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE)) - { - selection->tree_view->priv->anchor = - gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); - } + _gtk_tree_view_set_anchor_path (priv->tree_view, path); } } else @@ -1420,25 +1547,19 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE)) { dirty = TRUE; - if (selection->tree_view->priv->anchor) - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - selection->tree_view->priv->anchor = - gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); + _gtk_tree_view_set_anchor_path (priv->tree_view, path); } } } } - else if (selection->type == GTK_SELECTION_MULTIPLE) + else if (priv->type == GTK_SELECTION_MULTIPLE) { if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND && (anchor_path == NULL)) { - if (selection->tree_view->priv->anchor) - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); + _gtk_tree_view_set_anchor_path (priv->tree_view, path); - selection->tree_view->priv->anchor = - gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE); } else if ((mode & (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE)) == (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE)) @@ -1450,11 +1571,8 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, else if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE) { flags = node->flags; - if (selection->tree_view->priv->anchor) - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - selection->tree_view->priv->anchor = - gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); + _gtk_tree_view_set_anchor_path (priv->tree_view, path); if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED) dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE); @@ -1473,11 +1591,7 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, { dirty = gtk_tree_selection_real_unselect_all (selection); - if (selection->tree_view->priv->anchor) - gtk_tree_row_reference_free (selection->tree_view->priv->anchor); - - selection->tree_view->priv->anchor = - gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path); + _gtk_tree_view_set_anchor_path (priv->tree_view, path); dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE); } @@ -1487,7 +1601,14 @@ _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection, gtk_tree_path_free (anchor_path); if (dirty) - g_signal_emit (selection, tree_selection_signals[CHANGED], 0); + g_signal_emit (selection, tree_selection_signals[CHANGED], 0); +} + + +void +_gtk_tree_selection_emit_changed (GtkTreeSelection *selection) +{ + g_signal_emit (selection, tree_selection_signals[CHANGED], 0); } /* NOTE: Any {un,}selection ever done _MUST_ be done through this function! @@ -1499,29 +1620,36 @@ gtk_tree_selection_real_select_node (GtkTreeSelection *selection, GtkRBNode *node, gboolean select) { - gboolean selected = FALSE; + GtkTreeSelectionPrivate *priv = selection->priv; + gboolean toggle = FALSE; GtkTreePath *path = NULL; select = !! select; if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select) { - path = _gtk_tree_view_find_path (selection->tree_view, tree, node); - selected = row_is_selectable (selection, node, path); + path = _gtk_tree_path_new_from_rbtree (tree, node); + toggle = _gtk_tree_selection_row_is_selectable (selection, node, path); gtk_tree_path_free (path); } - if (selected == TRUE) + if (toggle) { - node->flags ^= GTK_RBNODE_IS_SELECTED; + if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED)) + { + GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED); + _gtk_tree_view_accessible_add_state (priv->tree_view, tree, node, GTK_CELL_RENDERER_SELECTED); + } + else + { + GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_SELECTED); + _gtk_tree_view_accessible_remove_state (priv->tree_view, tree, node, GTK_CELL_RENDERER_SELECTED); + } + + _gtk_tree_view_queue_draw_node (priv->tree_view, tree, node, NULL); - _gtk_tree_view_queue_draw_node (selection->tree_view, tree, node, NULL); - return TRUE; } return FALSE; } - -#define __GTK_TREE_SELECTION_C__ -#include "gtkaliasdef.c"