Minor fix.

Tue Dec  4 18:38:35 2001  Jonathan Blandford  <jrb@redhat.com>

	* demos/gtk-demo/main.c: (create_tree): Minor fix.

	* docs/tree-column-sizing.txt: Update

	* gtk/gtkrbtree.[ch]: Massive work to support validation.

	* gtk/gtktreemodel.c: Doc fixes.

	* gtk/gtktreeview.c: Incremental reflow added.
	* gtk/gtktreeviewcolumn.c: ditto
	* gtk/gtktreeviewcolumn.h: ditto
This commit is contained in:
Jonathan Blandford 2001-12-04 23:49:57 +00:00 committed by Jonathan Blandford
parent 57506c438b
commit d1a858c837
8 changed files with 734 additions and 594 deletions

View File

@ -1,30 +1,19 @@
The way that the GtkTreeView calculates sizing is pretty confusing.
This is written down to help keep track of it in my head, and thus help
anyone who hopes to work with the code in the future.
-jrb
HOW THE GTKTREEVIEW CALCULATES SIZE:
====================================
When the view is given a new model, the first thing it does is walk
When the view is given a new model, the first thing it does is walk
through the model at the top level, creating an GtkRBNode for each
element of the model. Each node has a height of 0. The RBTree is kept
updated as the models structure changes. Additionally, the user can
expand, collapse, and select rows at this stage. The RBTree is accurate
-- it just doesn't have a height for any row.
When the TreeView is realized, it calculates the actual height of each
row by walking the tree and measuring them. While doing so, it gets the
size of each column.
Columns are initially marked as 'dirty'. When sized,
gtk_tree_view_check_dirty_and_clean () is called on each column. This
function walks through all visible columns, and sees if they're dirty or
not. If any are dirty, it then walks the tree, calling
gtk_tree_view_calc_size on each row. gtk_tree_view_calc_size requests
the size of every dirty column in the tree. Finally, it updates the
size of the widget (including adjustments).
-- it just has a height of zero for every row.
When the widget is realized, it calls install_presize_handler, to setup
the first-run function. This is run before the expose event.
HOW THE GTKTREEVIEWCOLUMN STORES SIZE:
======================================
@ -32,23 +21,46 @@ HOW THE GTKTREEVIEWCOLUMN STORES SIZE:
There are a number of size related fields in the GtkTreeViewColumn
structure. These are all valid after realization:
sizing The sizing method to use when calculating the size
of the column. Can be grow_only, resizable, auto, and fixed.
column_type The sizing method to use when calculating the size
of the column. Can be GROW_ONLY, AUTO, and FIXED.
requested_width The width of the column as requested by the column
button_request The width as requested by the button.
width The actual width. This is requested width for all
columns but possibly the last one.
requested_width The width of the column as requested by the column.
It is the max requested width of the bcells in the
column. If the column_type is AUTO, then it is
recalculated when a column changes. Otherwise, it
only grows.
resized_width The width after the user has resized the column.
width The actual width of the column as displayed.
fixed_width The requested fixed width for the column iff it's
sizing type is set to GTK_TREE_VIEW_COLUMN_FIXED.
Used instead of requested_width in that case.
min_width The minimum width the column can be
min_width The minimum width the column can be. If set to -1,
this field is considered unset.
max_width The maximum width the column can be. This can be
overridden for the last column, if the tree_view is
actually wider than the sum of all of the columns
requested_widths.
requested_widths. If set to -1, this field is
considered unset.
use_resized_width Use resized_width to determine the size.
--
tree_view->priv->width = the width the widget wants to be, including headers.
tree_view->priv->height = the height the widget requests. It's the sum
of the width of all visible columns.
Both of these are calculated in _gtk_tree_view_update_size
--
The following invariants are true:
@ -56,12 +68,9 @@ min_width is less than or equal to width
max_width is greater than or equal to width
min_width <= max_width
(sizing == GTK_TREE_VIEW_COLUMN_FIXED) => (requested_width == fixed_width)
(column != last visible column) => width == requested_width
(column != last visible column) => width == CLAMP (requested_width, min_width, max_width)
/* Functions needed by gtktreeview for gtktreeviewcolumn */
size_request_button
set_width (for resizing resizable columns)
calculate_width

View File

@ -571,9 +571,10 @@ _gtk_rbtree_remove (GtkRBTree *tree)
GtkRBNode *
_gtk_rbtree_insert_after (GtkRBTree *tree,
GtkRBNode *current,
gint height)
_gtk_rbtree_insert_after (GtkRBTree *tree,
GtkRBNode *current,
gint height,
gboolean valid)
{
GtkRBNode *node;
gboolean right = TRUE;
@ -633,13 +634,19 @@ _gtk_rbtree_insert_after (GtkRBTree *tree,
if (gtk_debug_flags & GTK_DEBUG_TREE)
_gtk_rbtree_test (G_STRLOC, tree);
if (valid)
_gtk_rbtree_node_mark_valid (tree, node);
else
_gtk_rbtree_node_mark_invalid (tree, node);
return node;
}
GtkRBNode *
_gtk_rbtree_insert_before (GtkRBTree *tree,
GtkRBNode *current,
gint height)
_gtk_rbtree_insert_before (GtkRBTree *tree,
GtkRBNode *current,
gint height,
gboolean valid)
{
GtkRBNode *node;
gboolean left = TRUE;
@ -699,6 +706,11 @@ _gtk_rbtree_insert_before (GtkRBTree *tree,
if (gtk_debug_flags & GTK_DEBUG_TREE)
_gtk_rbtree_test (G_STRLOC, tree);
if (valid)
_gtk_rbtree_node_mark_valid (tree, node);
else
_gtk_rbtree_node_mark_invalid (tree, node);
return node;
}
@ -775,16 +787,20 @@ void
_gtk_rbtree_node_mark_valid (GtkRBTree *tree,
GtkRBNode *node)
{
if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))
if ((!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)) &&
(!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID)))
return;
GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_INVALID);
GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_COLUMN_INVALID);
do
{
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
if ((GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)) ||
(GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID)) ||
(node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID)) ||
(node->left && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) ||
(node->right && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)))
(node->left != tree->nil && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) ||
(node->right != tree->nil && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)))
return;
GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
@ -798,6 +814,34 @@ _gtk_rbtree_node_mark_valid (GtkRBTree *tree,
while (node);
}
/* Assume tree is the root node as it doesn't set DESCENDANTS_INVALID above.
*/
void
_gtk_rbtree_column_invalid (GtkRBTree *tree)
{
GtkRBNode *node;
if (tree == NULL)
return;
node = tree->root;
g_assert (node);
while (node->left != tree->nil)
node = node->left;
do
{
if (! (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID)))
GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_COLUMN_INVALID);
GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
if (node->children)
_gtk_rbtree_column_invalid (node->children);
}
while ((node = _gtk_rbtree_next (tree, node)) != NULL);
}
typedef struct _GtkRBReorder
{
GtkRBTree *children;
@ -849,6 +893,14 @@ gtk_rbtree_reorder_fixup (GtkRBTree *tree,
node->offset += node->children->root->offset;
node->parity += node->children->root->parity;
}
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
(node->right != tree->nil && GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) ||
(node->left != tree->nil && GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) ||
(node->children && GTK_RBNODE_FLAG_SET (node->children->root, GTK_RBNODE_DESCENDANTS_INVALID)))
GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
else
GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);
}
/* It basically pulls everything out of the tree, rearranges it, and puts it
@ -990,20 +1042,24 @@ _gtk_rbtree_node_find_parity (GtkRBTree *tree,
}
gint
_gtk_rbtree_find_offset (GtkRBTree *tree,
gint height,
GtkRBTree **new_tree,
GtkRBNode **new_node)
_gtk_rbtree_real_find_offset (GtkRBTree *tree,
gint height,
GtkRBTree **new_tree,
GtkRBNode **new_node)
{
GtkRBNode *tmp_node;
g_assert (tree);
if (height < 0)
{
*new_tree = NULL;
*new_node = NULL;
return 0;
}
tmp_node = tree->root;
while (tmp_node != tree->nil &&
(tmp_node->left->offset > height ||
@ -1033,20 +1089,40 @@ _gtk_rbtree_find_offset (GtkRBTree *tree,
*new_node = tmp_node;
return (height - tmp_node->left->offset);
}
return _gtk_rbtree_find_offset (tmp_node->children,
height - tmp_node->left->offset -
(tmp_node->offset -
tmp_node->left->offset -
tmp_node->right->offset -
tmp_node->children->root->offset),
new_tree,
new_node);
return _gtk_rbtree_real_find_offset (tmp_node->children,
height - tmp_node->left->offset -
(tmp_node->offset -
tmp_node->left->offset -
tmp_node->right->offset -
tmp_node->children->root->offset),
new_tree,
new_node);
}
*new_tree = tree;
*new_node = tmp_node;
return (height - tmp_node->left->offset);
}
gint
_gtk_rbtree_find_offset (GtkRBTree *tree,
gint height,
GtkRBTree **new_tree,
GtkRBNode **new_node)
{
GtkRBNode *tmp_node;
g_assert (tree);
if ((height < 0) ||
(height >= tree->root->offset))
{
*new_tree = NULL;
*new_node = NULL;
return 0;
}
_gtk_rbtree_real_find_offset (tree, height, new_tree, new_node);
}
void
_gtk_rbtree_remove_node (GtkRBTree *tree,
@ -1069,7 +1145,6 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
if (gtk_debug_flags & GTK_DEBUG_TREE)
_gtk_rbtree_test (G_STRLOC, tree);
if (node->left == tree->nil || node->right == tree->nil)
{
y = node;

View File

@ -37,8 +37,16 @@ typedef enum
GTK_RBNODE_IS_SEMI_COLLAPSED = 1 << 5,
GTK_RBNODE_IS_SEMI_EXPANDED = 1 << 6,
GTK_RBNODE_INVALID = 1 << 7,
GTK_RBNODE_DESCENDANTS_INVALID = 1 << 8,
GTK_RBNODE_NON_COLORS = GTK_RBNODE_IS_PARENT | GTK_RBNODE_IS_SELECTED | GTK_RBNODE_IS_PRELIT | GTK_RBNODE_IS_SEMI_COLLAPSED | GTK_RBNODE_IS_SEMI_EXPANDED | GTK_RBNODE_INVALID | GTK_RBNODE_DESCENDANTS_INVALID
GTK_RBNODE_COLUMN_INVALID = 1 << 8,
GTK_RBNODE_DESCENDANTS_INVALID = 1 << 9,
GTK_RBNODE_NON_COLORS = GTK_RBNODE_IS_PARENT |
GTK_RBNODE_IS_SELECTED |
GTK_RBNODE_IS_PRELIT |
GTK_RBNODE_IS_SEMI_COLLAPSED |
GTK_RBNODE_IS_SEMI_EXPANDED |
GTK_RBNODE_INVALID |
GTK_RBNODE_COLUMN_INVALID |
GTK_RBNODE_DESCENDANTS_INVALID
} GtkRBNodeColor;
typedef struct _GtkRBTree GtkRBTree;
@ -93,6 +101,7 @@ struct _GtkRBNode
GtkRBTree *children;
};
#define GTK_RBNODE_GET_COLOR(node) (node?(((node->flags&GTK_RBNODE_RED)==GTK_RBNODE_RED)?GTK_RBNODE_RED:GTK_RBNODE_BLACK):GTK_RBNODE_BLACK)
#define GTK_RBNODE_SET_COLOR(node,color) if((node->flags&color)!=color)node->flags=node->flags^(GTK_RBNODE_RED|GTK_RBNODE_BLACK)
#define GTK_RBNODE_GET_HEIGHT(node) (node->offset-(node->left->offset+node->right->offset+(node->children?node->children->root->offset:0)))
@ -109,10 +118,12 @@ void _gtk_rbtree_remove (GtkRBTree *tree);
void _gtk_rbtree_destroy (GtkRBTree *tree);
GtkRBNode *_gtk_rbtree_insert_before (GtkRBTree *tree,
GtkRBNode *node,
gint height);
gint height,
gboolean valid);
GtkRBNode *_gtk_rbtree_insert_after (GtkRBTree *tree,
GtkRBNode *node,
gint height);
gint height,
gboolean valid);
void _gtk_rbtree_remove_node (GtkRBTree *tree,
GtkRBNode *node);
void _gtk_rbtree_reorder (GtkRBTree *tree,
@ -127,6 +138,7 @@ void _gtk_rbtree_node_mark_invalid(GtkRBTree *tree,
GtkRBNode *node);
void _gtk_rbtree_node_mark_valid (GtkRBTree *tree,
GtkRBNode *node);
void _gtk_rbtree_column_invalid (GtkRBTree *tree);
gint _gtk_rbtree_node_find_offset (GtkRBTree *tree,
GtkRBNode *node);
gint _gtk_rbtree_node_find_parity (GtkRBTree *tree,

View File

@ -1093,6 +1093,16 @@ gtk_tree_model_row_has_child_toggled (GtkTreeModel *tree_model,
g_signal_emit_by_name (tree_model, "row_has_child_toggled", path, iter);
}
/**
* gtk_tree_model_row_deleted:
* @tree_model: A #GtkTreeModel
* @path: A #GtkTreePath pointing to the previous location of the deleted row.
*
* Emits the "row_deleted" signal on @tree_model. This should be called by
* models after a row has been removed. The location pointed to by @path should
* be the location that the row previously was at. It may not be a valid
* location anymore.
**/
void
gtk_tree_model_row_deleted (GtkTreeModel *tree_model,
GtkTreePath *path)

View File

@ -29,8 +29,6 @@ extern "C" {
#include <gtk/gtktreeselection.h>
#include <gtk/gtkrbtree.h>
#define TREE_VIEW_DRAG_WIDTH 6
typedef enum
@ -53,11 +51,12 @@ enum
DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT = 3,
DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT = 4
};
#define GTK_TREE_VIEW_SET_FLAG(tree_view, flag) G_STMT_START{ (tree_view->priv->flags|=flag); }G_STMT_END
#define GTK_TREE_VIEW_UNSET_FLAG(tree_view, flag) G_STMT_START{ (tree_view->priv->flags&=~(flag)); }G_STMT_END
#define GTK_TREE_VIEW_FLAG_SET(tree_view, flag) ((tree_view->priv->flags&flag)==flag)
#define TREE_VIEW_HEADER_HEIGHT(tree_view) (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE)?tree_view->priv->header_height:0)
#define TREE_VIEW_COLUMN_WIDTH(column) (CLAMP (column->width, (column->min_width!=-1)?column->min_width:column->width, (column->max_width!=-1)?column->max_width:column->width))
#define TREE_VIEW_COLUMN_REQUESTED_WIDTH(column) (CLAMP (column->requested_width, (column->min_width!=-1)?column->min_width:column->requested_width, (column->max_width!=-1)?column->max_width:column->requested_width))
#define TREE_VIEW_DRAW_EXPANDERS(tree_view) (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST)&&GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS))
/* This lovely little value is used to determine how far away from the title bar
@ -108,6 +107,8 @@ struct _GtkTreeViewPrivate
GtkTreeViewColumn *expander_column;
GtkTreeViewColumn *edited_column;
guint presize_handler_timer;
guint validate_rows_timer;
/* Focus code */
GtkTreeViewColumn *focus_column;
@ -117,7 +118,6 @@ struct _GtkTreeViewPrivate
GtkTreeRowReference *cursor;
/* Column Resizing */
GdkGC *xor_gc;
gint drag_pos;
gint x_drag;
@ -173,6 +173,7 @@ struct _GtkTreeViewPrivate
guint drag_column_window_state : 3;
/* hint to display rows in alternating colors */
guint has_rules : 1;
guint mark_rows_col_dirty : 1;
/* interactive search */
guint enable_search : 1;
@ -183,8 +184,6 @@ struct _GtkTreeViewPrivate
GtkDestroyNotify search_destroy;
};
#ifdef __GNUC__
#define TREE_VIEW_INTERNAL_ASSERT(expr, ret) G_STMT_START{ \
if (!(expr)) \
{ \
@ -202,57 +201,22 @@ struct _GtkTreeViewPrivate
return ret; \
}; }G_STMT_END
#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr) G_STMT_START{ \
if (!(expr)) \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d (%s): assertion `%s' failed.\n" \
"There is a disparity between the internal view of the GtkTreeView,\n" \
"and the GtkTreeModel. This generally means that the model has changed\n"\
"without letting the view know. Any display from now on is likely to\n" \
"be incorrect.\n", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#expr); \
return; \
}; }G_STMT_END
#else
#define TREE_VIEW_INTERNAL_ASSERT(expr, ret) G_STMT_START{ \
if (!(expr)) \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: assertion `%s' failed.\n" \
"There is a disparity between the internal view of the GtkTreeView,\n" \
"and the GtkTreeModel. This generally means that the model has changed\n"\
"without letting the view know. Any display from now on is likely to\n" \
"be incorrect.\n", \
__FILE__, \
__LINE__, \
#expr); \
return ret; \
}; }G_STMT_END
#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr) G_STMT_START{ \
if (!(expr)) \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: assertion '%s' failed.\n" \
"file %s: line %d (%s): assertion `%s' failed.\n" \
"There is a disparity between the internal view of the GtkTreeView,\n" \
"and the GtkTreeModel. This generally means that the model has changed\n"\
"without letting the view know. Any display from now on is likely to\n" \
"be incorrect.\n", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#expr); \
return; \
}; }G_STMT_END
#endif
/* functions that shouldn't be exported */
@ -268,7 +232,6 @@ gboolean _gtk_tree_view_find_node (GtkTreeView *tree_v
GtkTreePath *_gtk_tree_view_find_path (GtkTreeView *tree_view,
GtkRBTree *tree,
GtkRBNode *node);
void _gtk_tree_view_update_size (GtkTreeView *tree_view);
void _gtk_tree_view_child_move_resize (GtkTreeView *tree_view,
GtkWidget *widget,
gint x,
@ -296,7 +259,7 @@ gboolean _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column,
void _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
GtkCellEditable *editable_widget);
void _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column);
void _gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view);
GtkTreeSelection* _gtk_tree_selection_new (void);
GtkTreeSelection* _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view);

File diff suppressed because it is too large Load Diff

View File

@ -302,6 +302,7 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
tree_column->requested_width = -1;
tree_column->min_width = -1;
tree_column->max_width = -1;
tree_column->resized_width = 0;
tree_column->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY;
tree_column->visible = TRUE;
tree_column->resizable = FALSE;
@ -315,6 +316,7 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
tree_column->sort_column_id = -1;
tree_column->reorderable = FALSE;
tree_column->maybe_reordered = FALSE;
tree_column->use_resized_width = FALSE;
}
static void
@ -355,6 +357,11 @@ gtk_tree_view_column_set_property (GObject *object,
g_value_get_boolean (value));
break;
case PROP_RESIZABLE:
gtk_tree_view_column_set_resizable (tree_column,
g_value_get_boolean (value));
break;
case PROP_SIZING:
gtk_tree_view_column_set_sizing (tree_column,
g_value_get_enum (value));
@ -433,6 +440,11 @@ gtk_tree_view_column_get_property (GObject *object,
gtk_tree_view_column_get_visible (tree_column));
break;
case PROP_RESIZABLE:
g_value_set_boolean (value,
gtk_tree_view_column_get_resizable (tree_column));
break;
case PROP_WIDTH:
g_value_set_int (value,
gtk_tree_view_column_get_width (tree_column));
@ -711,8 +723,6 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
}
}
}
gtk_tree_view_column_cell_set_dirty (tree_column);
}
/* Button signal handlers
@ -787,7 +797,7 @@ gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
static void
gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
GtkTreeViewColumn *column)
GtkTreeViewColumn *column)
{
gint sort_column_id;
GtkSortType order;
@ -998,29 +1008,6 @@ _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
column->button = NULL;
}
void
_gtk_tree_view_column_set_width (GtkTreeViewColumn *tree_column,
gint width)
{
if (tree_column->min_width != -1 &&
width <= tree_column->min_width)
width = tree_column->min_width;
else if (tree_column->max_width != -1 &&
width > tree_column->max_width)
width = tree_column->max_width;
if (tree_column->width == width)
return;
tree_column->width = width;
g_object_notify (G_OBJECT (tree_column), "width");
if (tree_column->tree_view != NULL)
gtk_widget_queue_resize (tree_column->tree_view);
}
/* Public Functions */
@ -1142,6 +1129,12 @@ gtk_tree_view_column_pack_end (GtkTreeViewColumn *tree_column,
}
/**
* gtk_tree_view_column_clear:
* @tree_column: A #GtkTreeViewColumn
*
* Unsets all the mappings on all renderers on the @tree_column.
**/
void
gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
{
@ -1161,6 +1154,15 @@ gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
tree_column->cell_list = NULL;
}
/**
* gtk_tree_view_column_get_cell_renderers:
* @tree_column: A #GtkTreeViewColumn
*
* Returns a newly allocated #GList of all the cell renderers in the column, in no
* particular order. The list must be freed with g_list_free()
*
* Return value: A list of #GtkCellRenderers
**/
GList *
gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column)
{
@ -1431,6 +1433,8 @@ gtk_tree_view_column_set_resizable (GtkTreeViewColumn *tree_column,
if (tree_column->resizable == resizable)
return;
tree_column->resizable = resizable;
if (resizable && tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
@ -1537,16 +1541,21 @@ gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
return;
tree_column->fixed_width = fixed_width;
tree_column->requested_width = fixed_width;
_gtk_tree_view_column_set_width (tree_column, fixed_width);
if (tree_column->tree_view &&
GTK_WIDGET_REALIZED (tree_column->tree_view) &&
tree_column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
{
gtk_widget_queue_resize (tree_column->tree_view);
}
}
/**
* gtk_tree_view_column_get_fixed_width:
* @tree_column: a #GtkTreeViewColumn
*
* Gets the fixed width of the column. This value is only meaning may not be the
* actual width of the column on the screen, just what is requested.
* Gets the fixed width of the column. This value is only meaning may not be
* the actual width of the column on the screen, just what is requested.
*
* Return value: the fixed width of the column
**/
@ -1570,41 +1579,26 @@ void
gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
gint min_width)
{
gint real_min_width;
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
g_return_if_fail (min_width >= -1);
if (min_width == tree_column->min_width)
return;
if (tree_column->tree_view == NULL)
if (tree_column->visible &&
tree_column->tree_view != NULL &&
GTK_WIDGET_REALIZED (tree_column->tree_view))
{
tree_column->min_width = min_width;
return;
}
real_min_width = (tree_column->min_width == -1) ?
tree_column->button->requisition.width : tree_column->min_width;
/* We want to queue a resize if the either the old min_size or the
* new min_size determined the size of the column */
if (GTK_WIDGET_REALIZED (tree_column->tree_view))
{
if ((tree_column->min_width > tree_column->width) ||
(tree_column->min_width == -1 &&
tree_column->button->requisition.width > tree_column->width) ||
(min_width > tree_column->width) ||
(min_width == -1 &&
tree_column->button->requisition.width > tree_column->width))
if (min_width > tree_column->width)
gtk_widget_queue_resize (tree_column->tree_view);
}
if (tree_column->max_width != -1 && tree_column->max_width < real_min_width)
tree_column->max_width = real_min_width;
tree_column->min_width = min_width;
if (tree_column->max_width != -1 && tree_column->max_width < min_width)
{
tree_column->max_width = min_width;
g_object_notify (G_OBJECT (tree_column), "max_width");
}
g_object_notify (G_OBJECT (tree_column), "min_width");
}
@ -1633,40 +1627,32 @@ gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
* Sets the maximum width of the @tree_column. If @max_width is -1, then the
* maximum width is unset. Note, the column can actually be wider than max
* width if it's the last column in a view. In this case, the column expands to
* fill the view.
* fill any extra space.
**/
void
gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
gint max_width)
{
gint real_max_width;
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
g_return_if_fail (max_width >= -1);
if (max_width == tree_column->max_width)
return;
if (tree_column->tree_view == NULL)
if (tree_column->visible &&
tree_column->tree_view != NULL &&
GTK_WIDGET_REALIZED (tree_column->tree_view))
{
tree_column->max_width = max_width;
return;
if (max_width != -1 && max_width < tree_column->width)
gtk_widget_queue_resize (tree_column->tree_view);
}
real_max_width = tree_column->max_width == -1 ?
tree_column->button->requisition.width : tree_column->max_width;
if (tree_column->tree_view &&
GTK_WIDGET_REALIZED (tree_column->tree_view) &&
((tree_column->max_width < tree_column->width) ||
(max_width != -1 && max_width < tree_column->width)))
gtk_widget_queue_resize (tree_column->tree_view);
tree_column->max_width = max_width;
if (real_max_width > max_width)
tree_column->max_width = max_width;
if (max_width != -1 && max_width < tree_column->min_width)
{
tree_column->min_width = max_width;
g_object_notify (G_OBJECT (tree_column), "min_width");
}
g_object_notify (G_OBJECT (tree_column), "max_width");
}
@ -1692,7 +1678,7 @@ gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
* @tree_column: a #GtkTreeViewColumn
*
* Emits the "clicked" signal on the column. This function will only work if
* the user could have conceivably clicked on the button.
* @tree_column is clickable.
**/
void
gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
@ -1759,10 +1745,11 @@ gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
{
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
if (tree_column->clickable == (clickable?TRUE:FALSE))
clickable = !! clickable;
if (tree_column->clickable == clickable)
return;
tree_column->clickable = (clickable?TRUE:FALSE);
tree_column->clickable = clickable;
gtk_tree_view_column_update_button (tree_column);
g_object_notify (G_OBJECT (tree_column), "clickable");
}
@ -1773,7 +1760,7 @@ gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
*
* Returns %TRUE if the user can click on the header for the column.
*
* Return value: whether the user can click the column header
* Return value: TRUE if user can click the column header
**/
gboolean
gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
@ -2207,10 +2194,8 @@ gtk_tree_view_column_cell_render_or_focus (GtkTreeViewColumn *tree_column,
for (list = tree_column->cell_list; list; list = list->next)
{
GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
gboolean visible;
g_object_get (info->cell, "visible", &visible, NULL);
if (visible == FALSE)
if (! info->cell->visible)
continue;
if (info->expand == TRUE)
@ -2225,13 +2210,11 @@ gtk_tree_view_column_cell_render_or_focus (GtkTreeViewColumn *tree_column,
for (list = tree_column->cell_list; list; list = list->next)
{
GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
gboolean visible;
if (info->pack == GTK_PACK_END)
continue;
g_object_get (info->cell, "visible", &visible, NULL);
if (visible == FALSE)
if (! info->cell->visible)
continue;
real_cell_area.width = info->requested_width +
@ -2270,13 +2253,11 @@ gtk_tree_view_column_cell_render_or_focus (GtkTreeViewColumn *tree_column,
for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
{
GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
gboolean visible;
if (info->pack == GTK_PACK_START)
continue;
g_object_get (info->cell, "visible", &visible, NULL);
if (visible == FALSE)
if (! info->cell->visible)
continue;
real_cell_area.width = info->requested_width +
@ -2462,11 +2443,8 @@ gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
for (list = tree_column->cell_list; list; list = list->next)
{
GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
gboolean visible;
g_object_get (G_OBJECT (info->cell), "visible", &visible, NULL);
if (visible)
if (info->cell->visible)
return TRUE;
}
@ -2485,9 +2463,14 @@ gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column)
info->requested_width = 0;
}
tree_column->dirty = TRUE;
tree_column->requested_width = 0;
if (tree_column->tree_view)
gtk_widget_queue_resize (tree_column->tree_view);
if (tree_column->tree_view &&
GTK_WIDGET_REALIZED (tree_column->tree_view))
{
_gtk_tree_view_install_mark_rows_col_dirty (GTK_TREE_VIEW (tree_column->tree_view));
gtk_widget_queue_resize (tree_column->tree_view);
}
}
void

View File

@ -66,11 +66,16 @@ struct _GtkTreeViewColumn
GtkCellEditable *editable_widget;
gfloat xalign;
guint property_changed_signal;
gint spacing;
gint fixed_width;
gint width;
/* Sizing fields */
/* see gtk+/doc/tree-column-sizing.txt for more information on them */
GtkTreeViewColumnSizing column_type;
gint requested_width;
gint button_request;
gint resized_width;
gint width;
gint fixed_width;
gint min_width;
gint max_width;
@ -80,7 +85,6 @@ struct _GtkTreeViewColumn
gchar *title;
GList *cell_list;
GtkTreeViewColumnSizing column_type;
/* Sorting */
guint sort_clicked_signal;
@ -96,6 +100,7 @@ struct _GtkTreeViewColumn
guint show_sort_indicator : 1;
guint maybe_reordered : 1;
guint reorderable : 1;
guint use_resized_width : 1;
};
struct _GtkTreeViewColumnClass