summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Rietveld <kris@gtk.org>2006-12-26 16:13:02 +0000
committerKristian Rietveld <kristian@src.gnome.org>2006-12-26 16:13:02 +0000
commita3bc63b9e23081c2405a18e63a81d86458fd6e75 (patch)
tree4a0a24eefe60bb3891ea49e0dd0e50c8441e4ab4
parent0b75f7a30f45203f1dbf24ddedd26feebb686fe7 (diff)
downloadgtk+-a3bc63b9e23081c2405a18e63a81d86458fd6e75.tar.gz
Lots of scrolling fixes. Made scrolling work properly in not fully
2006-12-26 Kristian Rietveld <kris@gtk.org> Lots of scrolling fixes. Made scrolling work properly in not fully validated tree views; fixed a bunch of corner cases. * gtk/gtktreeview.c (validate_visible_area): if a row's dy is past upper - page_size, we know it is located at the end so the test for dy + height has been dropped. In the same case if area_below < 0, we know this is the last node in the tree view so area_above is page_size - height of this row. (validate_visible_area): got rid of subtracting new_height - old_height from area_{below,above}, it didn't make any sense at all and the full height of the row should be subtracted instead. (validate_visible_area): when scrolling to a given path, set the top row directly together with the dy offset, then sync that top_row to the dy. (gtk_tree_view_set_top_row): new function to directly set a top_row. (gtk_tree_view_dy_to_top_row): refactored to use gtk_tree_view_set_top_row(). (gtk_tree_view_top_row_to_dy): make sure dy >= 0 when done. (gtk_tree_view_adjustment_changed): only update our dy and top_row if the adjustment's dy actually changed.
-rw-r--r--ChangeLog23
-rw-r--r--gtk/gtktreeview.c100
2 files changed, 70 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index f559d14dd0..c4613cfe16 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2006-12-26 Kristian Rietveld <kris@gtk.org>
+
+ Lots of scrolling fixes. Made scrolling work properly in not fully
+ validated tree views; fixed a bunch of corner cases.
+
+ * gtk/gtktreeview.c (validate_visible_area): if a row's dy is past
+ upper - page_size, we know it is located at the end so the test for
+ dy + height has been dropped.
+ In the same case if area_below < 0, we know this is the last node
+ in the tree view so area_above is page_size - height of this row.
+ (validate_visible_area): got rid of subtracting new_height -
+ old_height from area_{below,above}, it didn't make any sense at
+ all and the full height of the row should be subtracted instead.
+ (validate_visible_area): when scrolling to a given path, set the
+ top row directly together with the dy offset, then sync that top_row
+ to the dy.
+ (gtk_tree_view_set_top_row): new function to directly set a top_row.
+ (gtk_tree_view_dy_to_top_row): refactored to use
+ gtk_tree_view_set_top_row().
+ (gtk_tree_view_top_row_to_dy): make sure dy >= 0 when done.
+ (gtk_tree_view_adjustment_changed): only update our dy and
+ top_row if the adjustment's dy actually changed.
+
2006-12-26 Christian Persch <chpe@cvs.gnome.org>
* gtk/gtknotebook.c: (gtk_notebook_real_insert_page):
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index c50119a554..26a73ee8a4 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -295,6 +295,9 @@ static gboolean validate_rows (GtkTreeView *tree_view);
static gboolean presize_handler_callback (gpointer data);
static void install_presize_handler (GtkTreeView *tree_view);
static void install_scroll_sync_handler (GtkTreeView *tree_view);
+static void gtk_tree_view_set_top_row (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ gint offset);
static void gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view);
static void gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view);
static void invalidate_empty_focus (GtkTreeView *tree_view);
@@ -5684,8 +5687,7 @@ validate_visible_area (GtkTreeView *tree_view)
- area_above - height;
}
else if (dy >= (tree_view->priv->vadjustment->upper -
- tree_view->priv->vadjustment->page_size)
- && dy + height <= tree_view->priv->vadjustment->upper)
+ tree_view->priv->vadjustment->page_size))
{
/* row at the end -- fixed */
area_above = dy - (tree_view->priv->vadjustment->upper -
@@ -5695,7 +5697,7 @@ validate_visible_area (GtkTreeView *tree_view)
if (area_below < 0)
{
- area_above += area_below;
+ area_above = tree_view->priv->vadjustment->page_size - height;
area_below = 0;
}
}
@@ -5802,8 +5804,6 @@ validate_visible_area (GtkTreeView *tree_view)
*/
while (node && area_below > 0)
{
- gint new_height;
-
if (node->children)
{
GtkTreeIter parent = iter;
@@ -5861,24 +5861,15 @@ validate_visible_area (GtkTreeView *tree_view)
if (!node)
break;
- new_height = GTK_RBNODE_GET_HEIGHT (node);
-
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
{
- gint old_height = new_height;
-
_gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
if (validate_row (tree_view, tree, node, &iter, path))
- {
- new_height = GTK_RBNODE_GET_HEIGHT (node);
size_changed = TRUE;
-
- area_below -= new_height - old_height;
- }
}
- area_below -= ROW_HEIGHT (tree_view, new_height);
+ area_below -= ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
}
gtk_tree_path_free (path);
@@ -5892,8 +5883,6 @@ validate_visible_area (GtkTreeView *tree_view)
/* We walk backwards */
while (area_above > 0)
{
- gint new_height;
-
_gtk_rbtree_prev_full (tree, node, &tree, &node);
if (! gtk_tree_path_prev (above_path) && node != NULL)
{
@@ -5905,23 +5894,14 @@ validate_visible_area (GtkTreeView *tree_view)
if (node == NULL)
break;
- new_height = GTK_RBNODE_GET_HEIGHT (node);
-
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
{
- gint old_height = new_height;
-
_gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
if (validate_row (tree_view, tree, node, &iter, above_path))
- {
- new_height = GTK_RBNODE_GET_HEIGHT (node);
- size_changed = TRUE;
-
- area_above -= new_height - old_height;
- }
+ size_changed = TRUE;
}
- area_above -= ROW_HEIGHT (tree_view, new_height);
+ area_above -= ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
}
/* if we scrolled to a path, we need to set the dy here,
@@ -5929,15 +5909,8 @@ validate_visible_area (GtkTreeView *tree_view)
*/
if (tree_view->priv->scroll_to_path)
{
- gint dy;
-
- if (node != NULL)
- dy = _gtk_rbtree_node_find_offset (tree, node) - area_above;
- else
- dy = 0;
-
- gtk_adjustment_set_value (tree_view->priv->vadjustment, dy);
- gtk_tree_view_dy_to_top_row (tree_view);
+ gtk_tree_view_set_top_row (tree_view, above_path, -area_above);
+ gtk_tree_view_top_row_to_dy (tree_view);
need_redraw = TRUE;
}
@@ -6278,33 +6251,49 @@ install_scroll_sync_handler (GtkTreeView *tree_view)
}
}
+static void
+gtk_tree_view_set_top_row (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ gint offset)
+{
+ gtk_tree_row_reference_free (tree_view->priv->top_row);
+
+ if (!path)
+ {
+ tree_view->priv->top_row = NULL;
+ tree_view->priv->top_row_dy = 0;
+ }
+ else
+ {
+ tree_view->priv->top_row = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
+ tree_view->priv->top_row_dy = offset;
+ }
+}
+
/* Always call this iff dy is in the visible range. If the tree is empty, then
* it's set to be NULL, and top_row_dy is 0;
*/
static void
gtk_tree_view_dy_to_top_row (GtkTreeView *tree_view)
{
+ gint offset;
GtkTreePath *path;
GtkRBTree *tree;
GtkRBNode *node;
- gtk_tree_row_reference_free (tree_view->priv->top_row);
if (tree_view->priv->tree == NULL)
- tree = NULL;
+ {
+ gtk_tree_view_set_top_row (tree_view, NULL, 0);
+ }
else
- tree_view->priv->top_row_dy = _gtk_rbtree_find_offset (tree_view->priv->tree,
- tree_view->priv->dy,
- &tree, &node);
- if (tree == NULL)
{
- tree_view->priv->top_row = NULL;
- tree_view->priv->top_row_dy = 0;
- return;
+ offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
+ tree_view->priv->dy,
+ &tree, &node);
+ path = _gtk_tree_view_find_path (tree_view, tree, node);
+ gtk_tree_view_set_top_row (tree_view, path, offset);
+ gtk_tree_path_free (path);
}
-
- path = _gtk_tree_view_find_path (tree_view, tree, node);
- tree_view->priv->top_row = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
- gtk_tree_path_free (path);
}
static void
@@ -6352,6 +6341,8 @@ gtk_tree_view_top_row_to_dy (GtkTreeView *tree_view)
if (tree_view->priv->dy + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
tree_view->priv->dy = tree_view->priv->height - tree_view->priv->vadjustment->page_size;
+ tree_view->priv->dy = MAX (0, tree_view->priv->dy);
+
gtk_adjustment_set_value (tree_view->priv->vadjustment,
(gdouble)tree_view->priv->dy);
}
@@ -10368,9 +10359,12 @@ gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
}
gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
- /* update our dy and top_row */
- tree_view->priv->dy = (int) tree_view->priv->vadjustment->value;
- gtk_tree_view_dy_to_top_row (tree_view);
+ if (tree_view->priv->dy != (int) tree_view->priv->vadjustment->value)
+ {
+ /* update our dy and top_row */
+ tree_view->priv->dy = (int) tree_view->priv->vadjustment->value;
+ gtk_tree_view_dy_to_top_row (tree_view);
+ }
}
}