+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktreemodel.c, gtk/gtktreemodel.h: add GtkTreeRowReference
+ which holds a handle to a specific row (particular set of values
+ in the model, i.e. pointer-identity row).
+
+ * gtk/gtktreeview.c, gtk/gtktreeprivate.h, gtk/gtktreeselection.c:
+ use GtkTreeRowReference for anchor, cursor, and drag_dest_row.
+ Still need to use it for the src/dest row saved on the drag context.
+
2001-01-26 Havoc Pennington <hp@redhat.com>
* gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor
+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktreemodel.c, gtk/gtktreemodel.h: add GtkTreeRowReference
+ which holds a handle to a specific row (particular set of values
+ in the model, i.e. pointer-identity row).
+
+ * gtk/gtktreeview.c, gtk/gtktreeprivate.h, gtk/gtktreeselection.c:
+ use GtkTreeRowReference for anchor, cursor, and drag_dest_row.
+ Still need to use it for the src/dest row saved on the drag context.
+
2001-01-26 Havoc Pennington <hp@redhat.com>
* gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor
+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktreemodel.c, gtk/gtktreemodel.h: add GtkTreeRowReference
+ which holds a handle to a specific row (particular set of values
+ in the model, i.e. pointer-identity row).
+
+ * gtk/gtktreeview.c, gtk/gtktreeprivate.h, gtk/gtktreeselection.c:
+ use GtkTreeRowReference for anchor, cursor, and drag_dest_row.
+ Still need to use it for the src/dest row saved on the drag context.
+
2001-01-26 Havoc Pennington <hp@redhat.com>
* gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor
+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktreemodel.c, gtk/gtktreemodel.h: add GtkTreeRowReference
+ which holds a handle to a specific row (particular set of values
+ in the model, i.e. pointer-identity row).
+
+ * gtk/gtktreeview.c, gtk/gtktreeprivate.h, gtk/gtktreeselection.c:
+ use GtkTreeRowReference for anchor, cursor, and drag_dest_row.
+ Still need to use it for the src/dest row saved on the drag context.
+
2001-01-26 Havoc Pennington <hp@redhat.com>
* gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor
+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktreemodel.c, gtk/gtktreemodel.h: add GtkTreeRowReference
+ which holds a handle to a specific row (particular set of values
+ in the model, i.e. pointer-identity row).
+
+ * gtk/gtktreeview.c, gtk/gtktreeprivate.h, gtk/gtktreeselection.c:
+ use GtkTreeRowReference for anchor, cursor, and drag_dest_row.
+ Still need to use it for the src/dest row saved on the drag context.
+
2001-01-26 Havoc Pennington <hp@redhat.com>
* gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor
+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktreemodel.c, gtk/gtktreemodel.h: add GtkTreeRowReference
+ which holds a handle to a specific row (particular set of values
+ in the model, i.e. pointer-identity row).
+
+ * gtk/gtktreeview.c, gtk/gtktreeprivate.h, gtk/gtktreeselection.c:
+ use GtkTreeRowReference for anchor, cursor, and drag_dest_row.
+ Still need to use it for the src/dest row saved on the drag context.
+
2001-01-26 Havoc Pennington <hp@redhat.com>
* gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor
+2001-01-26 Havoc Pennington <hp@redhat.com>
+
+ * gtk/gtktreemodel.c, gtk/gtktreemodel.h: add GtkTreeRowReference
+ which holds a handle to a specific row (particular set of values
+ in the model, i.e. pointer-identity row).
+
+ * gtk/gtktreeview.c, gtk/gtktreeprivate.h, gtk/gtktreeselection.c:
+ use GtkTreeRowReference for anchor, cursor, and drag_dest_row.
+ Still need to use it for the src/dest row saved on the drag context.
+
2001-01-26 Havoc Pennington <hp@redhat.com>
* gtk/gtktextlayout.c (convert_color): adapt to handle PangoColor
gtk_tree_path_append_index (path, 0);
}
+struct _GtkTreeRowReference
+{
+ GtkTreeModel *model;
+ GtkTreePath *path;
+};
+
+typedef struct _RowRefList RowRefList;
+
+struct _RowRefList
+{
+ GSList *list;
+};
+
+static void
+release_row_references (gpointer data)
+{
+ RowRefList *refs = data;
+ GSList *tmp_list = NULL;
+
+ tmp_list = refs->list;
+ while (tmp_list != NULL)
+ {
+ GtkTreeRowReference *reference = tmp_list->data;
+
+ reference->model = NULL;
+
+ /* we don't free the reference, users are responsible for that. */
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+
+ g_slist_free (refs->list);
+ g_free (refs);
+}
+
+static void
+inserted_callback (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ RowRefList *refs = data;
+ GSList *tmp_list;
+
+ tmp_list = refs->list;
+
+ while (tmp_list != NULL)
+ {
+ GtkTreeRowReference *reference = tmp_list->data;
+
+ /* if reference->path == NULL then the reference was already
+ * deleted.
+ */
+
+ if (reference->path)
+ {
+ gint i;
+ gint depth = gtk_tree_path_get_depth (path);
+ gint *indices = gtk_tree_path_get_indices (path);
+ gint ref_depth = gtk_tree_path_get_depth (reference->path);
+ gint *ref_indices = gtk_tree_path_get_indices (reference->path);
+
+ for (i = 0; i < depth && i < ref_depth; i++)
+ {
+ if (indices[i] < ref_indices[i])
+ {
+ /* inserted node was before the referenced row;
+ * move referenced path down 1
+ */
+ ref_indices[i] += 1;
+ break;
+ }
+ else if (indices[i] > ref_indices[i])
+ {
+ /* inserted node was past the referenced row */
+ break;
+ }
+ else if (i == depth - 1)
+ {
+ /* referenced row or its parent was inserted, this
+ * is possible if you create the path and row reference
+ * before you actually insert the row.
+ */
+ break;
+ }
+ }
+
+ /* If we didn't break out of the for loop, the inserted path
+ * was a child of the referenced path
+ */
+ }
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+}
+
+static void
+deleted_callback (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ gpointer data)
+{
+ RowRefList *refs = data;
+ GSList *tmp_list;
+
+ tmp_list = refs->list;
+
+ while (tmp_list != NULL)
+ {
+ GtkTreeRowReference *reference = tmp_list->data;
+
+ /* if reference->path == NULL then the reference was already
+ * deleted.
+ */
+
+ if (reference->path)
+ {
+ gint i;
+ gint depth = gtk_tree_path_get_depth (path);
+ gint *indices = gtk_tree_path_get_indices (path);
+ gint ref_depth = gtk_tree_path_get_depth (reference->path);
+ gint *ref_indices = gtk_tree_path_get_indices (reference->path);
+
+ for (i = 0; i < depth && i < ref_depth; i++)
+ {
+ if (indices[i] < ref_indices[i])
+ {
+ /* deleted node was before the referenced row;
+ * move referenced path up 1
+ */
+ ref_indices[i] -= 1;
+ break;
+ }
+ else if (indices[i] > ref_indices[i])
+ {
+ /* deleted node is past the referenced row */
+ break;
+ }
+ else if (i == depth - 1)
+ {
+ /* referenced row or its parent was deleted, mark it
+ * invalid
+ */
+ gtk_tree_path_free (reference->path);
+ reference->path = NULL;
+ break;
+ }
+ }
+
+ /* If we didn't break out of the for loop, the deleted path
+ * was a child of the referenced path
+ */
+ }
+
+ tmp_list = g_slist_next (tmp_list);
+ }
+}
+
+static void
+reordered_callback (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ gint *new_order,
+ gpointer data)
+{
+
+ /* FIXME */
+}
+
+static void
+connect_ref_callbacks (GtkTreeModel *model,
+ RowRefList *refs)
+{
+ g_signal_connect_data (G_OBJECT (model),
+ "inserted",
+ (GCallback) inserted_callback,
+ refs,
+ NULL,
+ FALSE,
+ FALSE);
+
+ g_signal_connect_data (G_OBJECT (model),
+ "deleted",
+ (GCallback) deleted_callback,
+ refs,
+ NULL,
+ FALSE,
+ FALSE);
+
+#if 0
+ /* FIXME */
+ g_signal_connect_data (G_OBJECT (model),
+ "reordered",
+ (GCallback) reordered_callback,
+ refs,
+ NULL,
+ FALSE,
+ FALSE);
+#endif
+}
+
+static void
+disconnect_ref_callbacks (GtkTreeModel *model,
+ RowRefList *refs)
+{
+ g_signal_handlers_disconnect_matched (G_OBJECT (model),
+ G_SIGNAL_MATCH_DATA,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ refs);
+}
+
+GtkTreeRowReference*
+gtk_tree_row_reference_new (GtkTreeModel *model,
+ GtkTreePath *path)
+{
+ GtkTreeRowReference *reference;
+ RowRefList *refs;
+
+ reference = g_new (GtkTreeRowReference, 1);
+
+ reference->model = model;
+ reference->path = gtk_tree_path_copy (path);
+
+ refs = g_object_get_data (G_OBJECT (model),
+ "gtk-tree-row-refs");
+
+ if (refs == NULL)
+ {
+ refs = g_new (RowRefList, 1);
+ refs->list = NULL;
+ connect_ref_callbacks (model, refs);
+ g_object_set_data_full (G_OBJECT (model),
+ "gtk-tree-row-refs",
+ refs,
+ release_row_references);
+ }
+
+ refs->list = g_slist_prepend (refs->list, reference);
+
+ return reference;
+}
+
+GtkTreePath*
+gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
+{
+ g_return_val_if_fail (reference != NULL, NULL);
+
+ if (reference->model == NULL)
+ return NULL;
+
+ if (reference->path == NULL)
+ return NULL;
+
+ return gtk_tree_path_copy (reference->path);
+}
+
+void
+gtk_tree_row_reference_free (GtkTreeRowReference *reference)
+{
+ RowRefList *refs;
+
+ g_return_if_fail (reference != NULL);
+
+ if (reference->model)
+ {
+ refs = g_object_get_data (G_OBJECT (reference->model),
+ "gtk-tree-row-refs");
+
+ if (refs == NULL)
+ {
+ g_warning (G_STRLOC": bad row reference, model has no outstanding row references");
+ return;
+ }
+
+ refs->list = g_slist_remove (refs->list, reference);
+
+ if (refs->list == NULL)
+ {
+ disconnect_ref_callbacks (reference->model, refs);
+ g_object_set_data (G_OBJECT (reference->model),
+ "gtk-tree-row-refs",
+ NULL);
+ }
+ }
+
+ if (reference->path)
+ gtk_tree_path_free (reference->path);
+
+ g_free (reference);
+}
/**
* gtk_tree_iter_copy:
#define GTK_TREE_MODEL_GET_IFACE(obj) ((GtkTreeModelIface *)g_type_interface_peek (((GTypeInstance *)GTK_TREE_MODEL (obj))->g_class, GTK_TYPE_TREE_MODEL))
-typedef struct _GtkTreeIter GtkTreeIter;
-typedef struct _GtkTreePath GtkTreePath;
-typedef struct _GtkTreeModel GtkTreeModel; /* Dummy typedef */
-typedef struct _GtkTreeModelIface GtkTreeModelIface;
+typedef struct _GtkTreeIter GtkTreeIter;
+typedef struct _GtkTreePath GtkTreePath;
+typedef struct _GtkTreeRowReference GtkTreeRowReference;
+typedef struct _GtkTreeModel GtkTreeModel; /* Dummy typedef */
+typedef struct _GtkTreeModelIface GtkTreeModelIface;
typedef enum
gboolean gtk_tree_path_up (GtkTreePath *path);
void gtk_tree_path_down (GtkTreePath *path);
+/* Row reference (an object that tracks model changes so it refers to the
+ * same row always; a path refers to a position, not a fixed row)
+ */
+
+GtkTreeRowReference *gtk_tree_row_reference_new (GtkTreeModel *model,
+ GtkTreePath *path);
+/* returns NULL if the row was deleted or the model was destroyed. */
+GtkTreePath *gtk_tree_row_reference_get_path (GtkTreeRowReference *reference);
+void gtk_tree_row_reference_free (GtkTreeRowReference *reference);
+
/* GtkTreeIter operations */
GtkTreeIter *gtk_tree_iter_copy (GtkTreeIter *iter);
gint expander_column;
/* Selection stuff */
- GtkTreePath *anchor;
- GtkTreePath *cursor;
+ GtkTreeRowReference *anchor;
+ GtkTreeRowReference *cursor;
/* Column Resizing */
GdkCursor *cursor_drag;
guint scroll_timeout;
/* Row drag-and-drop */
- GtkTreePath *drag_dest_row;
+ GtkTreeRowReference *drag_dest_row;
GtkTreeViewDropPosition drag_dest_pos;
guint open_dest_timeout;
if (selection->tree_view->priv->anchor)
{
- _gtk_tree_view_find_node (selection->tree_view,
- selection->tree_view->priv->anchor,
- &tree,
- &node);
-
- if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
- selected = TRUE;
+ GtkTreePath *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_path_free (anchor_path);
+ }
}
/* FIXME: if user_func is set, then it needs to unconditionally unselect
* all.
{
GtkRBTree *tree;
GtkRBNode *node;
-
+ GtkTreePath *anchor_path;
+ gboolean retval;
+
g_return_val_if_fail (selection != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
if (selection->tree_view->priv->anchor == NULL)
return FALSE;
- else if (iter == NULL)
- return TRUE;
+
+ anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
+
+ if (anchor_path == NULL)
+ return FALSE;
+
+ if (iter == NULL)
+ {
+ gtk_tree_path_free (anchor_path);
+ return TRUE;
+ }
g_return_val_if_fail (selection->tree_view != NULL, FALSE);
g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
+ retval = FALSE;
+
if (!_gtk_tree_view_find_node (selection->tree_view,
- selection->tree_view->priv->anchor,
- &tree,
- &node) &&
+ anchor_path,
+ &tree,
+ &node) &&
! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
- /* We don't want to return the anchor if it isn't actually selected.
- */
- return FALSE;
+ {
+ /* We don't want to return the anchor if it isn't actually selected.
+ */
+ retval = FALSE;
+ }
+ else
+ {
+ retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
+ iter,
+ anchor_path);
+ }
- return gtk_tree_model_get_iter (selection->tree_view->priv->model,
- iter,
- selection->tree_view->priv->anchor);
+ gtk_tree_path_free (anchor_path);
+
+ return retval;
}
/**
{
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);
+
+ if (anchor_path == NULL)
+ return FALSE;
+
_gtk_tree_view_find_node (selection->tree_view,
- selection->tree_view->priv->anchor,
+ anchor_path,
&tree,
&node);
+
+ gtk_tree_path_free (anchor_path);
+
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
{
gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
{
gint flags;
gint dirty = FALSE;
+ GtkTreePath *anchor_path = NULL;
- if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (selection->tree_view->priv->anchor == NULL))
+ if (selection->tree_view->priv->anchor)
+ anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
+
+ if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (anchor_path == NULL))
{
- selection->tree_view->priv->anchor = gtk_tree_path_copy (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 (selection->tree_view->priv->model,
+ path);
dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
}
else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
{
gtk_tree_selection_select_range (selection,
- selection->tree_view->priv->anchor,
+ anchor_path,
path);
}
else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
dirty = gtk_tree_selection_real_unselect_all (selection);
if (selection->tree_view->priv->anchor)
- gtk_tree_path_free (selection->tree_view->priv->anchor);
- selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
+ gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
+
+ selection->tree_view->priv->anchor =
+ gtk_tree_row_reference_new (selection->tree_view->priv->model,
+ path);
if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
{
dirty = gtk_tree_selection_real_unselect_all (selection);
dirty |= gtk_tree_selection_real_select_range (selection,
- selection->tree_view->priv->anchor,
+ anchor_path,
path);
}
else
{
dirty = gtk_tree_selection_real_unselect_all (selection);
+
if (selection->tree_view->priv->anchor)
- gtk_tree_path_free (selection->tree_view->priv->anchor);
- selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
+ gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
+
+ selection->tree_view->priv->anchor =
+ gtk_tree_row_reference_new (selection->tree_view->priv->model,
+ path);
+
dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
}
+ if (anchor_path)
+ gtk_tree_path_free (anchor_path);
+
if (dirty)
gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
}
gtk_tree_path_free (tree_view->priv->scroll_to_path);
if (tree_view->priv->drag_dest_row)
- gtk_tree_path_free (tree_view->priv->drag_dest_row);
+ gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
g_free (tree_view->priv);
if (G_OBJECT_CLASS (parent_class)->finalize)
gboolean last_selected;
gint highlight_x;
gint bin_window_width;
+ GtkTreePath *cursor_path;
+ GtkTreePath *drag_dest_path;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
depth = gtk_tree_path_get_depth (path);
gtk_tree_path_free (path);
+ cursor_path = NULL;
+ drag_dest_path = NULL;
+
if (tree_view->priv->cursor)
- _gtk_tree_view_find_node (tree_view, tree_view->priv->cursor, &cursor_tree, &cursor);
+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+
+ if (cursor_path)
+ _gtk_tree_view_find_node (tree_view, cursor_path,
+ &cursor_tree, &cursor);
if (tree_view->priv->drag_dest_row)
- _gtk_tree_view_find_node (tree_view, tree_view->priv->drag_dest_row,
+ drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
+
+ if (drag_dest_path)
+ _gtk_tree_view_find_node (tree_view, drag_dest_path,
&drag_highlight_tree, &drag_highlight);
gdk_drawable_get_size (tree_view->priv->bin_window,
case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
gtk_tree_view_draw_node_focus_rect (widget,
- tree_view->priv->drag_dest_row);
+ drag_dest_path);
break;
}
}
while (y_offset < event->area.height);
+ if (cursor_path)
+ gtk_tree_path_free (cursor_path);
+
+ if (drag_dest_path)
+ gtk_tree_path_free (drag_dest_path);
+
return TRUE;
}
gtk_tree_view_draw_focus (GtkWidget *widget)
{
GtkTreeView *tree_view;
-
+ GtkTreePath *cursor_path;
+
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW (widget));
if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS))
return;
+
if (tree_view->priv->cursor == NULL)
return;
- gtk_tree_view_draw_node_focus_rect (widget, tree_view->priv->cursor);
+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+ if (cursor_path == NULL)
+ return;
+
+ gtk_tree_view_draw_node_focus_rect (widget, cursor_path);
}
GdkEvent *event;
GtkRBTree *cursor_tree;
GtkRBNode *cursor_node;
-
+ GtkTreePath *cursor_path;
+
g_return_val_if_fail (container != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TREE_VIEW (container), FALSE);
g_return_val_if_fail (GTK_WIDGET_VISIBLE (container), FALSE);
/* if there is no keyboard focus yet, we select the first node
*/
- if (tree_view->priv->cursor == NULL)
- tree_view->priv->cursor = gtk_tree_path_new_root ();
+ cursor_path = NULL;
+
+ if (tree_view->priv->cursor)
+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+
+ if (cursor_path == NULL)
+ {
+ GtkTreePath *tmp_path = gtk_tree_path_new_root ();
+
+ if (tree_view->priv->cursor)
+ gtk_tree_row_reference_free (tree_view->priv->cursor);
+
+ tree_view->priv->cursor =
+ gtk_tree_row_reference_new (tree_view->priv->model,
+ tmp_path);
+ cursor_path = tmp_path;
+ }
+
gtk_tree_selection_select_path (tree_view->priv->selection,
- tree_view->priv->cursor);
- /* FIXME make this more efficient */
- gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+ cursor_path);
+
+ gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+
+ gtk_tree_path_free (cursor_path);
+
return TRUE;
}
}
tree_view->priv->selection =
_gtk_tree_selection_new_with_tree_view (tree_view);
- if (tree_view->priv->cursor == NULL)
- tree_view->priv->cursor = gtk_tree_path_new_root ();
+ cursor_path = NULL;
+ if (tree_view->priv->cursor)
+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+
+ if (cursor_path == NULL)
+ {
+ GtkTreePath *tmp_path = gtk_tree_path_new_root ();
+
+ if (tree_view->priv->cursor)
+ gtk_tree_row_reference_free (tree_view->priv->cursor);
+
+ tree_view->priv->cursor =
+ gtk_tree_row_reference_new (tree_view->priv->model,
+ tmp_path);
+ cursor_path = tmp_path;
+ }
gtk_tree_selection_select_path (tree_view->priv->selection,
- tree_view->priv->cursor);
- /* FIXME make this more efficient */
- gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+ cursor_path);
+
+ gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+
+ gtk_tree_path_free (cursor_path);
+
return TRUE;
}
+ cursor_path = NULL;
+ if (tree_view->priv->cursor)
+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
+
/* Case 3. We have focus already, but no cursor. We pick the first one
- * and run with it. */
- if (tree_view->priv->cursor == NULL)
+ * and run with it.
+ */
+
+ if (cursor_path == NULL)
{
- /* We lost our cursor somehow. Arbitrarily select the first node, and
- * return
- */
- tree_view->priv->cursor = gtk_tree_path_new_root ();
-
+ GtkTreePath *tmp_path = gtk_tree_path_new_root ();
+
+ if (tree_view->priv->cursor)
+ gtk_tree_row_reference_free (tree_view->priv->cursor);
+
+ tree_view->priv->cursor =
+ gtk_tree_row_reference_new (tree_view->priv->model,
+ tmp_path);
+ cursor_path = tmp_path;
+
gtk_tree_selection_select_path (tree_view->priv->selection,
- tree_view->priv->cursor);
- gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
- 0.0);
- /* FIXME make this more efficient */
- gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+ cursor_path);
+
+ gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+
+ gtk_tree_path_free (cursor_path);
+
return TRUE;
}
-
- /* Case 3. We have focus already. Move the cursor. */
+ /* Case 4. We have focus already. Move the cursor. */
if (direction == GTK_DIR_LEFT)
{
gfloat val;
val = MAX (val, 0.0);
gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->hadjustment), val);
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+
+ gtk_tree_path_free (cursor_path);
+
return TRUE;
}
if (direction == GTK_DIR_RIGHT)
val = MIN (tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size, val);
gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->hadjustment), val);
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+
+ gtk_tree_path_free (cursor_path);
+
return TRUE;
}
+
cursor_tree = NULL;
cursor_node = NULL;
- _gtk_tree_view_find_node (tree_view, tree_view->priv->cursor,
+ _gtk_tree_view_find_node (tree_view, cursor_path,
&cursor_tree,
&cursor_node);
+
+ /* undraw the old row */
+ gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+
+ gtk_tree_path_free (cursor_path);
+ cursor_path = NULL;
+
+ if (tree_view->priv->cursor)
+ {
+ gtk_tree_row_reference_free (tree_view->priv->cursor);
+ tree_view->priv->cursor = NULL;
+ }
+
switch (direction)
{
case GTK_DIR_TAB_BACKWARD:
if (event)
gdk_event_free (event);
- gtk_tree_path_free (tree_view->priv->cursor);
+
+ cursor_path = _gtk_tree_view_find_path (tree_view,
+ cursor_tree,
+ cursor_node);
- tree_view->priv->cursor = _gtk_tree_view_find_path (tree_view,
- cursor_tree,
- cursor_node);
- if (tree_view->priv->cursor)
- _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
- cursor_node,
- cursor_tree,
- tree_view->priv->cursor,
- state);
+ if (cursor_path)
+ {
+ _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
+ cursor_node,
+ cursor_tree,
+ cursor_path,
+ state);
+
+ tree_view->priv->cursor = gtk_tree_row_reference_new (tree_view->priv->model,
+ cursor_path);
+
+
+ /* draw the newly-selected row */
+ gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+
+ gtk_tree_path_free (cursor_path);
+ }
+
gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
- /* FIXME make this more efficient */
- gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+
return TRUE;
}
if (tree == NULL)
return;
- /* next, update the selection */
- if (tree_view->priv->anchor)
- {
- gint *select_indices = gtk_tree_path_get_indices (tree_view->priv->anchor);
- gint select_depth = gtk_tree_path_get_depth (tree_view->priv->anchor);
-
- for (i = 0; i < depth && i < select_depth; i++)
- {
- if (indices[i] < select_indices[i])
- {
- select_indices[i]++;
- break;
- }
- else if (indices[i] > select_indices[i])
- break;
- else if (i == depth - 1)
- {
- select_indices[i]++;
- break;
- }
- }
- }
-
/* ref the node */
gtk_tree_model_ref_iter (tree_view->priv->model, iter);
max_height = gtk_tree_view_insert_iter_height (tree_view,
/* next, update the selection */
if (tree_view->priv->anchor)
{
- gint i;
- gint depth = gtk_tree_path_get_depth (path);
- gint *indices = gtk_tree_path_get_indices (path);
- gint select_depth = gtk_tree_path_get_depth (tree_view->priv->anchor);
- gint *select_indices = gtk_tree_path_get_indices (tree_view->priv->anchor);
+ GtkTreePath *anchor_path;
- if (gtk_tree_path_compare (path, tree_view->priv->anchor) == 0)
+ /* 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)
+ tree_view->priv->selection)
gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->selection),
"selection_changed");
}
- else
- {
- for (i = 0; i < depth && i < select_depth; i++)
- {
- if (indices[i] < select_indices[i])
- {
- select_indices[i] = MAX (select_indices[i], 0);
- break;
- }
- else if (indices[i] > select_indices[i])
- break;
- else if (i == depth - 1)
- {
- select_indices[i] = MAX (select_indices[i], 0);
- break;
- }
- }
- }
+
+ if (anchor_path)
+ gtk_tree_path_free (anchor_path);
}
for (list = tree_view->priv->columns; list; list = list->next)
#endif
if (tree_view->priv->drag_dest_row)
- gtk_tree_path_free (tree_view->priv->drag_dest_row);
+ gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_MODEL_SETUP);
}
GtkTreePath *path,
GtkTreeViewDropPosition pos)
{
+ GtkTreePath *current_dest;
/* Note; this function is exported to allow a custom DND
* implementation, so it can't touch TreeViewDragInfo
*/
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
- g_print ("drag dest row %p -> %p\n", tree_view->priv->drag_dest_row, path);
+ current_dest = NULL;
if (tree_view->priv->drag_dest_row)
+ current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
+
+ if (current_dest)
{
- gtk_tree_view_queue_draw_path (tree_view, tree_view->priv->drag_dest_row, NULL);
- gtk_tree_path_free (tree_view->priv->drag_dest_row);
+ gtk_tree_view_queue_draw_path (tree_view, current_dest, NULL);
+ gtk_tree_path_free (current_dest);
}
+ if (tree_view->priv->drag_dest_row)
+ gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
+
tree_view->priv->drag_dest_pos = pos;
if (path)
{
- tree_view->priv->drag_dest_row = gtk_tree_path_copy (path);
- gtk_tree_view_queue_draw_path (tree_view, tree_view->priv->drag_dest_row, NULL);
+ tree_view->priv->drag_dest_row =
+ gtk_tree_row_reference_new (tree_view->priv->model,
+ path);
+ gtk_tree_view_queue_draw_path (tree_view, path, NULL);
}
else
tree_view->priv->drag_dest_row = NULL;
if (path)
{
if (tree_view->priv->drag_dest_row)
- *path = gtk_tree_path_copy (tree_view->priv->drag_dest_row);
+ *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
else
*path = NULL;
}
open_row_timeout (gpointer data)
{
GtkTreeView *tree_view = data;
+ GtkTreePath *dest_path = NULL;
+ GtkTreeViewDropPosition pos;
- if (tree_view->priv->drag_dest_row &&
- (tree_view->priv->drag_dest_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
- tree_view->priv->drag_dest_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
+ gtk_tree_view_get_drag_dest_row (tree_view,
+ &dest_path,
+ &pos);
+
+ if (dest_path &&
+ (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
+ pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
{
gtk_tree_view_expand_row (tree_view,
- tree_view->priv->drag_dest_row,
+ dest_path,
FALSE);
tree_view->priv->open_dest_timeout = 0;
+
+ gtk_tree_path_free (dest_path);
+
return FALSE;
}
else
- return TRUE;
+ {
+ if (dest_path)
+ gtk_tree_path_free (dest_path);
+ return TRUE;
+ }
}
/* Returns TRUE if event should not be propagated to parent widgets */
{
GtkTreePath *path = NULL;
GtkTreeViewDropPosition pos;
+ GtkTreeViewDropPosition old_pos;
TreeViewDragInfo *di;
GtkWidget *widget;
-
+ GtkTreePath *old_dest_path = NULL;
+
*suggested_action = 0;
widget = GTK_WIDGET (tree_view);
/* If we left the current row's "open" zone, unset the timeout for
* opening the row
*/
- if (tree_view->priv->drag_dest_row &&
- (gtk_tree_path_compare (path, tree_view->priv->drag_dest_row) != 0 ||
+ gtk_tree_view_get_drag_dest_row (tree_view,
+ &old_dest_path,
+ &old_pos);
+
+ if (old_dest_path &&
+ (gtk_tree_path_compare (path, old_dest_path) != 0 ||
!(pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
remove_open_timeout (tree_view);
+
+ if (old_dest_path)
+ gtk_tree_path_free (old_dest_path);
if (TRUE /* FIXME if the location droppable predicate */)
{