]> Pileus Git - ~andy/gtk/commitdiff
Fix bug where collapsing a selected row would result in the cursor/anchor
authorJonathan Blandford <jrb@redhat.com>
Mon, 18 Jun 2001 23:44:41 +0000 (23:44 +0000)
committerJonathan Blandford <jrb@src.gnome.org>
Mon, 18 Jun 2001 23:44:41 +0000 (23:44 +0000)
Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>

* gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
where collapsing a selected row would result in the cursor/anchor
getting screwed up.

12 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtktreemodel.c
gtk/gtktreemodel.h
gtk/gtktreemodelsort.c
gtk/gtktreeview.c
tests/treestoretest.c

index 82912a0fd6a99a79e30b68643427b2af67c41cbe..feb450152282fee96f8d2d2ba4de0a957402add6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>
+
+       * gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
+       where collapsing a selected row would result in the cursor/anchor
+       getting screwed up.
+
 Fri Jun 15 18:53:48 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/gtktreesortable.c (gtk_tree_sortable_set_sort_func): Rename
index 82912a0fd6a99a79e30b68643427b2af67c41cbe..feb450152282fee96f8d2d2ba4de0a957402add6 100644 (file)
@@ -1,3 +1,9 @@
+Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>
+
+       * gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
+       where collapsing a selected row would result in the cursor/anchor
+       getting screwed up.
+
 Fri Jun 15 18:53:48 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/gtktreesortable.c (gtk_tree_sortable_set_sort_func): Rename
index 82912a0fd6a99a79e30b68643427b2af67c41cbe..feb450152282fee96f8d2d2ba4de0a957402add6 100644 (file)
@@ -1,3 +1,9 @@
+Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>
+
+       * gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
+       where collapsing a selected row would result in the cursor/anchor
+       getting screwed up.
+
 Fri Jun 15 18:53:48 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/gtktreesortable.c (gtk_tree_sortable_set_sort_func): Rename
index 82912a0fd6a99a79e30b68643427b2af67c41cbe..feb450152282fee96f8d2d2ba4de0a957402add6 100644 (file)
@@ -1,3 +1,9 @@
+Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>
+
+       * gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
+       where collapsing a selected row would result in the cursor/anchor
+       getting screwed up.
+
 Fri Jun 15 18:53:48 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/gtktreesortable.c (gtk_tree_sortable_set_sort_func): Rename
index 82912a0fd6a99a79e30b68643427b2af67c41cbe..feb450152282fee96f8d2d2ba4de0a957402add6 100644 (file)
@@ -1,3 +1,9 @@
+Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>
+
+       * gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
+       where collapsing a selected row would result in the cursor/anchor
+       getting screwed up.
+
 Fri Jun 15 18:53:48 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/gtktreesortable.c (gtk_tree_sortable_set_sort_func): Rename
index 82912a0fd6a99a79e30b68643427b2af67c41cbe..feb450152282fee96f8d2d2ba4de0a957402add6 100644 (file)
@@ -1,3 +1,9 @@
+Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>
+
+       * gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
+       where collapsing a selected row would result in the cursor/anchor
+       getting screwed up.
+
 Fri Jun 15 18:53:48 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/gtktreesortable.c (gtk_tree_sortable_set_sort_func): Rename
index 82912a0fd6a99a79e30b68643427b2af67c41cbe..feb450152282fee96f8d2d2ba4de0a957402add6 100644 (file)
@@ -1,3 +1,9 @@
+Mon Jun 18 19:41:38 2001  Jonathan Blandford  <jrb@redhat.com>
+
+       * gtk/gtktreeview.c (gtk_tree_view_real_collapse_row): Fix bug
+       where collapsing a selected row would result in the cursor/anchor
+       getting screwed up.
+
 Fri Jun 15 18:53:48 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/gtktreesortable.c (gtk_tree_sortable_set_sort_func): Rename
index 3d854d1708863ee0f2ce2fdaf7cb43357d39dd02..ed34611314ddc970ac348228ad8bbbb5d4e82851 100644 (file)
@@ -1443,6 +1443,14 @@ gtk_tree_row_reference_new_proxy (GObject      *proxy,
   return reference;
 }
 
+/**
+ * gtk_tree_row_reference_get_path:
+ * @reference: A #GtkTreeRowReference
+ * 
+ * Returns a path that the row reference currently points to, or NULL if 
+ * 
+ * Return value: A current path, or NULL.
+ **/
 GtkTreePath *
 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
 {
@@ -1457,12 +1465,37 @@ gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
   return gtk_tree_path_copy (reference->path);
 }
 
+/**
+ * gtk_tree_row_reference_valid:
+ * @reference: A #GtkTreeRowReference, or NULL
+ * 
+ * Returns TRUE if the %reference is non-NULL and refers to a current valid
+ * path.
+ * 
+ * Return value: TRUE if %reference points to a valid path.
+ **/
+gboolean
+gtk_tree_row_reference_valid (GtkTreeRowReference *reference)
+{
+  if (reference == NULL || reference->path == NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * gtk_tree_row_reference_free:
+ * @reference: A #GtkTreeRowReference, or NULL
+ * 
+ * Free's %reference.  %reference may be NULL.
+ **/
 void
 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
 {
   RowRefList *refs;
 
-  g_return_if_fail (reference != NULL);
+  if (reference == NULL)
+    return;
 
   refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING);
 
index dd7554a163d7e1ff9dd3ca8aa5d0bb7bd9d65069..37555fb3c5b24e2097732325d4d196333470da05 100644 (file)
@@ -149,8 +149,8 @@ GtkTreeRowReference *gtk_tree_row_reference_new_proxy (GObject             *prox
                                                       GtkTreeModel        *model,
                                                       GtkTreePath         *path);
 GtkTreePath         *gtk_tree_row_reference_get_path  (GtkTreeRowReference *reference);
+gboolean             gtk_tree_row_reference_valid     (GtkTreeRowReference *reference);
 void                 gtk_tree_row_reference_free      (GtkTreeRowReference *reference);
-
 /* These two functions are only needed if you created the row reference with a
  * proxy object */
 void                 gtk_tree_row_reference_inserted  (GObject     *proxy,
index cdc81a27e7dbd1af6482a98e5f53f8ce934d1f7b..d331a9e85216390ad1430af11b2e96f041310584 100644 (file)
@@ -247,7 +247,7 @@ gtk_tree_model_sort_new_with_model (GtkTreeModel      *child_model)
  * gtk_tree_model_sort_set_model:
  * @tree_model_sort: The #GtkTreeModelSort.
  * @child_model: A #GtkTreeModel, or NULL.
- * 
+ *
  * Sets the model of @tree_model_sort to be @model.  If @model is NULL, then the
  * old model is unset.
  **/
@@ -299,13 +299,13 @@ gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
                           G_CALLBACK (gtk_tree_model_sort_range_changed),
                           tree_model_sort,
                           FALSE);
-      tree_model_sort->inserted_id = 
+      tree_model_sort->inserted_id =
        g_signal_connectc (child_model,
                           "inserted",
                           G_CALLBACK (gtk_tree_model_sort_inserted),
                           tree_model_sort,
                           FALSE);
-      tree_model_sort->has_child_toggled_id = 
+      tree_model_sort->has_child_toggled_id =
        g_signal_connectc (child_model,
                           "has_child_toggled",
                           G_CALLBACK (gtk_tree_model_sort_has_child_toggled),
@@ -331,9 +331,9 @@ gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
 /**
  * gtk_tree_model_sort_get_model:
  * @tree_model: a #GtkTreeModelSort
- * 
+ *
  * Returns the model the #GtkTreeModelSort is sorting.
- * 
+ *
  * Return value: the "child model" being sorted
  **/
 GtkTreeModel*
@@ -348,11 +348,11 @@ gtk_tree_model_sort_get_model (GtkTreeModelSort  *tree_model)
  * gtk_tree_model_sort_convert_path:
  * @tree_model_sort: The #GtkTreeModelSort.
  * @child_path: A #GtkTreePath, relative to the child model.
- * 
+ *
  * Converts the @child_path to a new path, relative to the sorted position.  In other
  * words, the value found in the @tree_model_sort ->child_model at the @child_path, is
  * identical to that found in the @tree_model_sort and the return value.
- * 
+ *
  * Return value: A new path, or NULL if @child_path does not exist in @tree_model_sort
  * ->child_model.
  **/
@@ -427,7 +427,7 @@ gtk_tree_model_sort_range_changed (GtkTreeModel *s_model,
    * sorting is changed, we can check the prev and next element to see if
    * they're different.
    */
-  
+
   /* Now we need to resort things. */
   index = gtk_tree_model_sort_array_find_insert (tree_model_sort,
                                                 array,
@@ -913,7 +913,7 @@ gtk_tree_model_sort_unref_node (GtkTreeModel *tree_model,
                                GtkTreeIter  *iter)
 {
 
+
 }
 
 static gboolean
@@ -1123,7 +1123,7 @@ gtk_tree_model_sort_convert_path_real (GtkTreeModelSort *tree_model_sort,
 
   return retval;
 }
-  
+
 static void
 gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
                                 SortElt          *place)
@@ -1138,7 +1138,7 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
   if (place)
     parent_iter = & (place->iter);
 
-      
+
   n = gtk_tree_model_iter_n_children (tree_model_sort->child_model, parent_iter);
 
   if (n == 0)
index 6284e9106a4f154f0083bf75ebd84a6cc45bff63..008e7ce5b70dc32aad89b9aee3bc665447775d92 100644 (file)
@@ -266,8 +266,8 @@ static void     gtk_tree_view_add_move_binding     (GtkBindingSet    *binding_se
                                                    guint             modmask,
                                                    GtkMovementStep   step,
                                                    gint              count);
-static void     gtk_tree_view_unref_tree           (GtkTreeView      *tree_view,
-                                                   GtkRBTree        *tree);
+static gint     gtk_tree_view_unref_and_check_selection_tree (GtkTreeView      *tree_view,
+                                                             GtkRBTree        *tree);
 static void     gtk_tree_view_queue_draw_node      (GtkTreeView      *tree_view,
                                                    GtkRBTree        *tree,
                                                    GtkRBNode        *node,
@@ -950,7 +950,7 @@ gtk_tree_view_destroy (GtkObject *object)
 
   if (tree_view->priv->tree != NULL)
     {
-      gtk_tree_view_unref_tree (tree_view, tree_view->priv->tree);
+      gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
       _gtk_rbtree_free (tree_view->priv->tree);
       tree_view->priv->tree = NULL;
     }
@@ -976,12 +976,6 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->selection = NULL;
     }
 
-  if (tree_view->priv->anchor != NULL)
-    {
-      gtk_tree_row_reference_free (tree_view->priv->anchor);
-      tree_view->priv->anchor = NULL;
-    }
-
   if (tree_view->priv->scroll_to_path != NULL)
     {
       gtk_tree_path_free (tree_view->priv->scroll_to_path);
@@ -994,12 +988,7 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->drag_dest_row = NULL;
     }
 
-  if (tree_view->priv->cursor)
-    {
-      gtk_tree_row_reference_free (tree_view->priv->cursor);
-      tree_view->priv->cursor = NULL;
-    }
-
+  
   if (tree_view->priv->column_drop_func_data &&
       tree_view->priv->column_drop_func_data_destroy)
     {
@@ -1007,6 +996,12 @@ gtk_tree_view_destroy (GtkObject *object)
       tree_view->priv->column_drop_func_data = NULL;
     }
 
+  gtk_tree_row_reference_free (tree_view->priv->cursor);
+  tree_view->priv->cursor = NULL;
+
+  gtk_tree_row_reference_free (tree_view->priv->anchor);
+  tree_view->priv->anchor = NULL;
+
   if (GTK_OBJECT_CLASS (parent_class)->destroy)
     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 }
@@ -1845,6 +1840,7 @@ static void
 ensure_unprelighted (GtkTreeView *tree_view)
 {
   do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */
+  g_assert (tree_view->priv->prelight_node == NULL);
 }
 
 
@@ -2315,12 +2311,10 @@ gtk_tree_view_draw_focus (GtkWidget *widget)
   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS))
     return;
 
-  if (tree_view->priv->cursor == NULL)
+  if (! gtk_tree_row_reference_valid (tree_view->priv->cursor))
     return;
 
   cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
-  if (cursor_path == NULL)
-    return;
 
   _gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node);
 
@@ -4441,30 +4435,9 @@ gtk_tree_view_deleted (GtkTreeModel *model,
 
   gtk_tree_row_reference_deleted (G_OBJECT (data), path);
 
-  /* next, update the selection */
-  if (tree_view->priv->anchor)
-    {
-      GtkTreePath *anchor_path;
-
-      /* the row reference may not have been updated yet. If it has not,
-       * then anchor_path and path being equal indicates that the anchor
-       * row was deleted. If it has, then anchor_path == NULL indicates the
-       * the anchor row was deleted.
-       */
-
-      anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
-
-      if (anchor_path == NULL ||
-          gtk_tree_path_compare (path, anchor_path) == 0)
-       {
-         if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) &&
-              tree_view->priv->selection)
-           g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed");
-       }
-
-      if (anchor_path)
-        gtk_tree_path_free (anchor_path);
-    }
+  /* Change the selection */
+  if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+    g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed");
 
   for (list = tree_view->priv->columns; list; list = list->next)
     if (((GtkTreeViewColumn *)list->data)->visible &&
@@ -4474,8 +4447,6 @@ gtk_tree_view_deleted (GtkTreeModel *model,
   /* Ensure we don't have a dangling pointer to a dead node */
   ensure_unprelighted (tree_view);
 
-  g_assert (tree_view->priv->prelight_node == NULL);
-
   if (tree->root->count == 1)
     {
       if (tree_view->priv->tree == tree)
@@ -5207,15 +5178,16 @@ gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
                                 GTK_TYPE_INT, count);
 }
 
-static void
+static gint
 gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
                                 GtkTreeIter  *iter,
                                 GtkRBTree    *tree,
                                 GtkRBNode    *node)
 {
+  gint retval = FALSE;
   do
     {
-      g_return_if_fail (node != NULL);
+      g_return_val_if_fail (node != NULL, FALSE);
 
       if (node->children)
        {
@@ -5229,34 +5201,41 @@ gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
          while (new_node && new_node->left != new_tree->nil)
            new_node = new_node->left;
 
-         g_return_if_fail (gtk_tree_model_iter_children (model, &child, iter));
-         gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
+         g_return_val_if_fail (gtk_tree_model_iter_children (model, &child, iter), FALSE);
+         retval = retval || gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
        }
 
+      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
+       retval = TRUE;
       gtk_tree_model_unref_node (model, iter);
       node = _gtk_rbtree_next (tree, node);
     }
   while (gtk_tree_model_iter_next (model, iter));
+
+  return retval;
 }
 
-static void
-gtk_tree_view_unref_tree (GtkTreeView *tree_view,
-                         GtkRBTree   *tree)
+static gint
+gtk_tree_view_unref_and_check_selection_tree (GtkTreeView *tree_view,
+                                             GtkRBTree   *tree)
 {
   GtkTreeIter iter;
   GtkTreePath *path;
   GtkRBNode *node;
+  gint retval;
 
   node = tree->root;
   while (node && node->left != tree->nil)
     node = node->left;
 
-  g_return_if_fail (node != NULL);
+  g_return_val_if_fail (node != NULL, FALSE);
   path = _gtk_tree_view_find_path (tree_view, tree, node);
   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->priv->model),
                           &iter, path);
-  gtk_tree_view_unref_tree_helper (GTK_TREE_MODEL (tree_view->priv->model), &iter, tree, node);
+  retval = gtk_tree_view_unref_tree_helper (GTK_TREE_MODEL (tree_view->priv->model), &iter, tree, node);
   gtk_tree_path_free (path);
+
+  return retval;
 }
 
 static void
@@ -7157,9 +7136,8 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
   /* Ensure we don't have a dangling pointer to a dead node */
   ensure_unprelighted (tree_view);
 
-  g_assert (tree_view->priv->prelight_node == NULL);
-
-  gtk_tree_view_unref_tree (tree_view, node->children);
+  if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
+    g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed", 0);
   _gtk_rbtree_remove (node->children);
 
   if (GTK_WIDGET_MAPPED (tree_view))
@@ -7168,6 +7146,32 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
       _gtk_tree_view_update_size (tree_view);
     }
 
+  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);
+
+    }
+
   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
 
   return TRUE;
index c6551a197cd86d2dcc5ec42ec83882f7308e860e..6dc712da25849f950c9086d6ffa02a71d8d34a1d 100644 (file)
@@ -260,6 +260,7 @@ make_window (gint view_type)
       break;
     }
 
+  gtk_tree_view_set_rules_hint (tree_view, TRUE);
   selection = G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
   gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection), GTK_TREE_SELECTION_SINGLE);
 
@@ -342,9 +343,9 @@ make_window (gint view_type)
       iter_append (NULL, GTK_TREE_VIEW (tree_view));
       iter_append (NULL, GTK_TREE_VIEW (tree_view));
       iter_append (NULL, GTK_TREE_VIEW (tree_view));
-      gtk_widget_show_all (window);
     }
   /* Show it all */
+  gtk_widget_show_all (window);
 }
 
 int
@@ -356,7 +357,7 @@ main (int argc, char *argv[])
 
   /* FIXME: reverse this */
   make_window (0);
-  //  make_window (1);
+  make_window (1);
 
   gtk_main ();