GNOME Bugzilla – Bug 691751
Better column resizing for GtkTreeView
Last modified: 2014-06-01 14:32:41 UTC
Created attachment 233481 [details] [review] 0001-Remove-extraneous-size-request.patch There are several problems with the current support for resizable columns in GtkTreeView, which I have written some patches to fix: * There is no way to set distinct minimum and natural widths for a GtkTreeViewColumn. I propose that the "fixed-width" property be interpreted as the natural width of the column rather than the minimum width (we already have the "min-width" property for that). * Column resizing is implemented using a hidden "resized-width" property that is not visible to applications. Hence, user changes to column size are lost every time the application is closed. I propose to get rid of the "resized-width" property and instead modify the "fixed-width" and "expand" properties to get the desired column size. Applications can then preserve user-set column sizes by saving and restoring these two properties. * The code that currently handles the "resized-width" property is convoluted and causes unexpected results when the size of the entire treeview is changed (see [1]). After my patches, the code is simpler and behaves as expected (see [2]). [1] screencast before (ogv): https://www.box.com/s/gz23ksylzjp046dn8ah5 [2] screencast after (ogv): https://www.box.com/s/c6zhov1igiqss7x97k5r
Created attachment 233482 [details] [review] 0002-Kill-gtk_tree_view_size_request.patch
Created attachment 233483 [details] [review] 0003-Use-fixed-width-for-resizing.patch
Created attachment 233484 [details] [review] 0004-Minor-refactoring.patch
Created attachment 233485 [details] [review] 0005-Use-minimum-natural-size-semantics.patch
Created attachment 233486 [details] [review] 0006-Better-resize-of-expandable-columns.patch
To reiterate what I said on IRC: I have roughly no clue about that code (I suppose Kris or jrb wrote it and they - or their knowledge about this code - are long gone these days). The patches seem to make sense from a quick glance but because they don't really explain anything in somewhat longer commit messages, take that with a grain of salt. :)
[PATCH 1/6] Remove extraneous size request After “validation” (i.e., background size calculations) of some cells, size_request() was called here to update the internally cached size of the treeview. Apparently not updating the sizes leads to some kind of “inconsistency” that messes with top_row_to_dy(). In the GTK3 model for size allocation, things are more complicated. The treeview can’t just go ahead and calculate its own size any more; instead it reports both a “minimum” and a “natural” size, and it doesn’t know what size it will actually get until size_allocate(). It may be necessary to update top_row_to_dy() to deal with not knowing the exact size. [PATCH 2/6] Kill gtk_tree_view_size_request Splits up size_request() so that the height calculations are only done when get_preferred_height() is called and the width calculations are only done when get_preferred_width() is called. Since get_preferred_width() does not change the treeview->priv->width value, treeview->priv->prev_width will always be equal to it and can therefore be removed. The only place where prev_width was used is a block in gtk_tree_view_size_allocate(). This block seems to be adjusting the horizontal scrollbar to account for treeview->priv->width having been changed in size_request() and should no longer be necessary. A similar block immediately above it seems to already account for the width change in size_allocate(). [PATCH 3/6] Use fixed width for resizing Removes the hidden “resized-width” and “use-resized-width” properties from GtkTreeViewColumn and instead uses the “fixed-width” property to serve the same purpose. “fixed-width”, if set, will now override the auto-sized width (-1 is now a legal value meaning “not set”). Additional “cleanups” in this commit: 1. When the user resizes the column the “expand” property is now also set to FALSE, in order to prevent the column from suddenly jumping to a different width when the window is resized. 2. The code that translated mouse movement to column sizes has been simplified: the change in column width is now calculated directly from the distance the mouse cursor has traveled. Weird behavior that might have happened previously if the position of the column changed during resizing, is now prevented. 3. There was some lengthy logic handling the keyboard shortcuts used to resize treeview columns, which would call gtk_widget_error_bell() once the minimum or maximum width was reached. Instead of rewriting these checks I simply set the “fixed-width” property to what was requested, relying on the fact that it is already clamped between the minimum and maximum width during size allocation. I will greatly surprised if anyone notices the missing error bell. [PATCH 4/6] Minor refactoring No functional change, only moves a self-contained block of code out of size_allocate_columns() to its own function. [PATCH 5/6] Use minimum/natural size semantics Rewrites gtk_tree_view_column_request_width() and gtk_tree_view_size_allocate_columns() to respect the minimum and natural sizes that are already being returned by gtk_cell_area_context_get_preferred_width(). The convoluted logic explained (not!) by this comment has been removed: “Only update the expand value if the width of the widget has changed, or the number of expand columns has changed, or if there are no expand columns, or if we didn't have an size-allocation yet after the last validated node.” This logic seems to have been a workaround for the “jumping” behavior fixed in [PATCH 3/6] and is no longer necessary. [PATCH 6/6] Better resize of expandable columns Since [PATCH 3/6] the “expand” property is always set to FALSE when a column is resized. This commit takes a different approach and enables “expand” whenever the column is wide enough. An appropriate “fixed-width” (so that the desired width is achieved after expanding) is calculated using equations that are explained in the code.
[PATCH 1/6] Remove extraneous size request After “validation” (i.e., background size calculations) of some cells, size_request() was called here to update the internally cached size of the treeview. Apparently not updating the sizes leads to some kind of “inconsistency” that messes with top_row_to_dy(). In the GTK3 model for size allocation, things are more complicated. The treeview can’t just go ahead and calculate its own size any more; instead it reports both a “minimum” and a “natural” size, and it doesn’t know what size it will actually get until size_allocate(). It may be necessary to update top_row_to_dy() to deal with not knowing the exact size. [PATCH 2/6] Kill gtk_tree_view_size_request Splits up size_request() so that the height calculations are only done when get_preferred_height() is called and the width calculations are only done when get_preferred_width() is called. Since get_preferred_width() does not change the treeview->priv->width value, treeview->priv->prev_width will always be equal to it and can therefore be removed. The only place where prev_width was used is a block in gtk_tree_view_size_allocate(). This block seems to be adjusting the horizontal scrollbar to account for treeview->priv->width having been changed in size_request() and should no longer be necessary. A similar block immediately above it seems to already account for the width change in size_allocate(). [PATCH 3/6] Use fixed width for resizing Removes the hidden “resized-width” and “use-resized-width” properties from GtkTreeViewColumn and instead uses the “fixed-width” property to serve the same purpose. “fixed-width”, if set, will now override the auto-sized width (-1 is now a legal value meaning “not set”). Additional “cleanups” in this commit: 1. When the user resizes the column the “expand” property is now also set to FALSE, in order to prevent the column from suddenly jumping to a different width when the window is resized. 2. The code that translated mouse movement to column sizes has been simplified: the change in column width is now calculated directly from the distance the mouse cursor has traveled. Weird behavior that might have happened previously if the position of the column changed during resizing, is now prevented. 3. There was some lengthy logic handling the keyboard shortcuts used to resize treeview columns, which would call gtk_widget_error_bell() once the minimum or maximum width was reached. Instead of rewriting these checks I simply set the “fixed-width” property to what was requested, relying on the fact that it is already clamped between the minimum and maximum width during size allocation. I will be greatly surprised if anyone notices the missing error bell. [PATCH 4/6] Minor refactoring No functional change, only moves a self-contained block of code out of size_allocate_columns() to its own function. [PATCH 5/6] Use minimum/natural size semantics Rewrites gtk_tree_view_column_request_width() and gtk_tree_view_size_allocate_columns() to respect the minimum and natural sizes that are already being returned by gtk_cell_area_context_get_preferred_width(). The convoluted logic explained (not!) by this comment has been removed: “Only update the expand value if the width of the widget has changed, or the number of expand columns has changed, or if there are no expand columns, or if we didn't have an size-allocation yet after the last validated node.” This logic seems to have been a workaround for the “jumping” behavior fixed in [PATCH 3/6] and is no longer necessary. [PATCH 6/6] Better resize of expandable columns Since [PATCH 3/6] the “expand” property is always set to FALSE when a column is resized. This commit takes a different approach and enables “expand” whenever the column is wide enough. An appropriate “fixed-width” (so that the desired width is achieved after expanding) is calculated using equations that are explained in the code.
Pushed to master. Welcome as the new GtkTreeView maintainer ;)
Patch 2, 5 and 6 of this series caused various regressions and have been reverted.