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.
This commit is contained in:
Kristian Rietveld 2006-12-26 16:13:02 +00:00 committed by Kristian Rietveld
parent 0b75f7a30f
commit a3bc63b9e2
2 changed files with 71 additions and 54 deletions

View File

@ -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):

View File

@ -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;
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;
gtk_tree_view_set_top_row (tree_view, NULL, 0);
}
else
{
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);
}
}
}