diff --git a/docs/tree-column-sizing.txt b/docs/tree-column-sizing.txt index 09e872434a..879b846285 100644 --- a/docs/tree-column-sizing.txt +++ b/docs/tree-column-sizing.txt @@ -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 diff --git a/gtk/gtkrbtree.c b/gtk/gtkrbtree.c index 9b0aaf5047..9bba7ab666 100644 --- a/gtk/gtkrbtree.c +++ b/gtk/gtkrbtree.c @@ -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; @@ -632,14 +633,20 @@ _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; @@ -698,7 +705,12 @@ _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,18 +787,22 @@ 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); node = node->parent; if (node == NULL) @@ -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,19 +1042,23 @@ _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 && @@ -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; diff --git a/gtk/gtkrbtree.h b/gtk/gtkrbtree.h index 793b8691ed..9db2ae2c26 100644 --- a/gtk/gtkrbtree.h +++ b/gtk/gtkrbtree.h @@ -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>K_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, diff --git a/gtk/gtktreemodel.c b/gtk/gtktreemodel.c index 05b2c4747e..18189d5a29 100644 --- a/gtk/gtktreemodel.c +++ b/gtk/gtktreemodel.c @@ -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) diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index 241d18793b..0ce4ac9940 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -28,8 +28,6 @@ extern "C" { #include #include #include - - #define TREE_VIEW_DRAG_WIDTH 6 @@ -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)&>K_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,7 +173,8 @@ 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; gint search_column; @@ -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); diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index fdccdab76f..f9dfd99642 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -35,12 +35,14 @@ #include "gtkbindings.h" #include "gtkcontainer.h" #include "gtkentry.h" +#include "gtktreemodelsort.h" #include #include #define GTK_TREE_VIEW_SEARCH_DIALOG_KEY "gtk-tree-view-search-dialog" - +#define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5) +#define GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 50 #define SCROLL_EDGE_SIZE 15 #define EXPANDER_EXTRA_PADDING 4 @@ -249,6 +251,16 @@ static void gtk_tree_view_rows_reordered (GtkTreeModel *mode gint *new_order, gpointer data); +/* Incremental reflow */ +static gboolean validate_row (GtkTreeView *tree_view, + GtkRBTree *tree, + GtkRBNode *node, + GtkTreeIter *iter, + GtkTreePath *path); +static void validate_visible_area (GtkTreeView *tree_view); +static gboolean validate_rows_handler (GtkTreeView *tree_view); +static gboolean presize_handler_callback (gpointer data); +static void install_presize_handler (GtkTreeView *tree_view); /* Internal functions */ @@ -286,20 +298,11 @@ static gint gtk_tree_view_new_column_width (GtkTreeView gint *x); static void gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment, GtkTreeView *tree_view); -static gint gtk_tree_view_insert_iter_height (GtkTreeView *tree_view, - GtkRBTree *tree, - GtkTreeIter *iter, - gint depth); static void gtk_tree_view_build_tree (GtkTreeView *tree_view, GtkRBTree *tree, GtkTreeIter *iter, gint depth, - gboolean recurse, - gboolean calc_bounds); -static void gtk_tree_view_calc_size (GtkTreeView *priv, - GtkRBTree *tree, - GtkTreeIter *iter, - gint depth); + gboolean recurse); static gboolean gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view, GtkTreeIter *iter, gint depth, @@ -309,7 +312,6 @@ static void gtk_tree_view_discover_dirty (GtkTreeView GtkRBTree *tree, GtkTreeIter *iter, gint depth); -static void gtk_tree_view_check_dirty_and_clean (GtkTreeView *tree_view); static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view, GtkRBTree *tree, GtkRBNode *node); @@ -317,7 +319,6 @@ static void gtk_tree_view_clamp_column_visible (GtkTreeView GtkTreeViewColumn *column); static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, GdkEventMotion *event); -static void _gtk_tree_view_update_col_width (GtkTreeView *tree_view); static void gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view); static void gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view, gint count); @@ -908,9 +909,9 @@ gtk_tree_view_init (GtkTreeView *tree_view) tree_view->priv->press_start_x = -1; tree_view->priv->press_start_y = -1; tree_view->priv->reorderable = FALSE; + tree_view->priv->presize_handler_timer = 0; gtk_tree_view_set_adjustments (tree_view, NULL, NULL); tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (tree_view); - _gtk_tree_view_update_size (tree_view); tree_view->priv->enable_search = TRUE; tree_view->priv->search_column = -1; tree_view->priv->search_dialog_position_func = gtk_tree_view_search_position_func; @@ -969,10 +970,10 @@ gtk_tree_view_set_property (GObject *object, } static void -gtk_tree_view_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +gtk_tree_view_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { GtkTreeView *tree_view; @@ -1207,7 +1208,6 @@ gtk_tree_view_realize (GtkWidget *widget) tree_view = GTK_TREE_VIEW (widget); - gtk_tree_view_check_dirty_and_clean (GTK_TREE_VIEW (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); /* Make the main, clipping window */ @@ -1267,11 +1267,7 @@ gtk_tree_view_realize (GtkWidget *widget) widget->style->black:widget->style->white); values.function = GDK_XOR; values.subwindow_mode = GDK_INCLUDE_INFERIORS; - tree_view->priv->xor_gc = gdk_gc_new_with_values (widget->window, - &values, - GDK_GC_FOREGROUND | - GDK_GC_FUNCTION | - GDK_GC_SUBWINDOW); + /* Add them all up. */ widget->style = gtk_style_attach (widget->style, widget->window); gdk_window_set_background (widget->window, &widget->style->base[widget->state]); @@ -1290,9 +1286,9 @@ gtk_tree_view_realize (GtkWidget *widget) for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next) _gtk_tree_view_column_realize_button (GTK_TREE_VIEW_COLUMN (tmp_list->data)); - _gtk_tree_view_update_size (GTK_TREE_VIEW (widget)); + install_presize_handler (tree_view); -if (GTK_WIDGET_CLASS (parent_class)->map) + if (GTK_WIDGET_CLASS (parent_class)->map) (* GTK_WIDGET_CLASS (parent_class)->map) (widget); } @@ -1323,6 +1319,12 @@ gtk_tree_view_unrealize (GtkWidget *widget) gtk_timeout_remove (tree_view->priv->expand_collapse_timeout); tree_view->priv->expand_collapse_timeout = 0; } + + if (tree_view->priv->presize_handler_timer != 0) + { + gtk_timeout_remove (tree_view->priv->presize_handler_timer); + tree_view->priv->presize_handler_timer = 0; + } for (list = tree_view->priv->columns; list; list = list->next) _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data)); @@ -1349,12 +1351,6 @@ gtk_tree_view_unrealize (GtkWidget *widget) tree_view->priv->drag_highlight_window = NULL; } - if (tree_view->priv->xor_gc) - { - gdk_gc_destroy (tree_view->priv->xor_gc); - tree_view->priv->xor_gc = NULL; - } - /* GtkWidget::unrealize destroys children and widget->window */ if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); @@ -1362,11 +1358,11 @@ gtk_tree_view_unrealize (GtkWidget *widget) /* GtkWidget::size_request helper */ static void -gtk_tree_view_size_request_buttons (GtkTreeView *tree_view) +gtk_tree_view_size_request_columns (GtkTreeView *tree_view) { GList *list; - tree_view->priv->header_height = 1; + tree_view->priv->header_height = 0; if (tree_view->priv->model) { @@ -1379,15 +1375,69 @@ gtk_tree_view_size_request_buttons (GtkTreeView *tree_view) continue; column = list->data; - + gtk_widget_size_request (column->button, &requisition); - - _gtk_tree_view_column_set_width (column, MAX (column->width, requisition.width)); + column->button_request = requisition.width; tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height); } } } + +static void +gtk_tree_view_update_size (GtkTreeView *tree_view) +{ + GList *list; + GtkTreeViewColumn *column; + gint i; + + if (tree_view->priv->model == NULL) + { + tree_view->priv->width = 0; + tree_view->priv->height = 0; + return; + } + + tree_view->priv->width = 0; + /* keep this in sync with size_allocate below */ + for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++) + { + gint real_requested_width = 0; + column = list->data; + if (!column->visible) + continue; + + if (column->use_resized_width) + { + real_requested_width = column->resized_width; + } + else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED) + { + real_requested_width = column->fixed_width; + } + else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE)) + { + real_requested_width = MAX (column->requested_width, column->button_request); + } + else + { + real_requested_width = column->requested_width; + } + + if (column->min_width != -1) + real_requested_width = MAX (real_requested_width, column->min_width); + if (column->max_width != -1) + real_requested_width = MIN (real_requested_width, column->max_width); + + tree_view->priv->width += real_requested_width; + } + + if (tree_view->priv->tree == NULL) + tree_view->priv->height = 0; + else + tree_view->priv->height = tree_view->priv->tree->root->offset; +} + static void gtk_tree_view_size_request (GtkWidget *widget, GtkRequisition *requisition) @@ -1399,7 +1449,8 @@ gtk_tree_view_size_request (GtkWidget *widget, tree_view = GTK_TREE_VIEW (widget); - gtk_tree_view_size_request_buttons (tree_view); + gtk_tree_view_size_request_columns (tree_view); + gtk_tree_view_update_size (GTK_TREE_VIEW (widget)); requisition->width = tree_view->priv->width; requisition->height = tree_view->priv->height + tree_view->priv->header_height; @@ -1420,31 +1471,66 @@ gtk_tree_view_size_request (GtkWidget *widget, /* GtkWidget::size_allocate helper */ static void -gtk_tree_view_size_allocate_buttons (GtkWidget *widget) +gtk_tree_view_size_allocate_columns (GtkWidget *widget) { GtkTreeView *tree_view; - GList *list; + GList *list, *last_column; GtkTreeViewColumn *column; GtkAllocation allocation; gint width = 0; tree_view = GTK_TREE_VIEW (widget); + for (last_column = g_list_last (tree_view->priv->columns); + last_column && !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible); + last_column = last_column->prev) + ; + if (last_column == NULL) + return; + allocation.y = 0; allocation.height = tree_view->priv->header_height; - for (list = tree_view->priv->columns; list != NULL; list = list->next) + for (list = tree_view->priv->columns; list != last_column->next; list = list->next) { + gint real_requested_width = 0; column = list->data; - if (!column->visible) continue; + if (column->use_resized_width) + { + real_requested_width = column->resized_width; + } + else if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED) + { + real_requested_width = column->fixed_width; + } + else if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE)) + { + real_requested_width = MAX (column->requested_width, column->button_request); + } + else + { + real_requested_width = column->requested_width; + } + + if (column->min_width != -1) + real_requested_width = MAX (real_requested_width, column->min_width); + if (column->max_width != -1) + real_requested_width = MIN (real_requested_width, column->max_width); + allocation.x = width; + column->width = real_requested_width; + if (list == last_column && + width + real_requested_width < widget->allocation.width) + { + column->width += (widget->allocation.width - column->width - width); + } + g_object_notify (G_OBJECT (column), "width"); allocation.width = column->width; width += column->width; gtk_widget_size_allocate (column->button, &allocation); - if (column->window) gdk_window_move_resize (column->window, allocation.x + allocation.width - TREE_VIEW_DRAG_WIDTH/2, @@ -1466,8 +1552,6 @@ gtk_tree_view_size_allocate (GtkWidget *widget, tree_view = GTK_TREE_VIEW (widget); - gtk_tree_view_check_dirty_and_clean (tree_view); - tmp_list = tree_view->priv->children; while (tmp_list) @@ -1494,12 +1578,11 @@ gtk_tree_view_size_allocate (GtkWidget *widget, MAX (tree_view->priv->width, allocation->width), tree_view->priv->header_height); gdk_window_resize (tree_view->priv->bin_window, - tree_view->priv->width, + MAX (tree_view->priv->width, allocation->width), allocation->height); - _gtk_tree_view_update_col_width (tree_view); } - gtk_tree_view_size_allocate_buttons (widget); + gtk_tree_view_size_allocate_columns (widget); tree_view->priv->hadjustment->page_size = allocation->width; tree_view->priv->hadjustment->page_increment = allocation->width; @@ -1538,7 +1621,6 @@ gtk_tree_view_size_allocate (GtkWidget *widget, } tree_view->priv->scroll_to_column = NULL; } - } static gboolean @@ -1754,6 +1836,8 @@ gtk_tree_view_button_press (GtkWidget *widget, gtk_grab_add (widget); GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE); + column->resized_width = column->width; + column->use_resized_width = TRUE; /* block attached dnd signal handler */ drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"); @@ -1765,6 +1849,7 @@ gtk_tree_view_button_press (GtkWidget *widget, tree_view->priv->drag_pos = i; tree_view->priv->x_drag = (column->button->allocation.x + column->button->allocation.width); + break; } } return TRUE; @@ -1820,7 +1905,6 @@ gtk_tree_view_button_release_column_resize (GtkWidget *widget, { GtkTreeView *tree_view; gpointer drag_data; - gint width; gint x; gint i; @@ -1839,9 +1923,6 @@ gtk_tree_view_button_release_column_resize (GtkWidget *widget, gtk_grab_remove (widget); gdk_pointer_ungrab (event->time); - width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), i, &x); - _gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), i), width); - return TRUE; } @@ -2263,6 +2344,9 @@ gtk_tree_view_motion_resize_column (GtkWidget *widget, { gint x; gint new_width; + GtkTreeViewColumn *column; + + column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), GTK_TREE_VIEW (widget)->priv->drag_pos); if (event->is_hint || event->window != widget->window) gtk_widget_get_pointer (widget, &x, NULL); @@ -2271,11 +2355,13 @@ gtk_tree_view_motion_resize_column (GtkWidget *widget, new_width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), GTK_TREE_VIEW (widget)->priv->drag_pos, &x); - if (x != GTK_TREE_VIEW (widget)->priv->x_drag) - _gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), GTK_TREE_VIEW (widget)->priv->drag_pos), new_width); + if (x != GTK_TREE_VIEW (widget)->priv->x_drag && + (new_width != column->fixed_width)); + { + column->resized_width = new_width; + gtk_widget_queue_resize (widget); + } - /* FIXME: Do we need to scroll */ - _gtk_tree_view_update_size (GTK_TREE_VIEW (widget)); return FALSE; } @@ -2513,9 +2599,9 @@ gtk_tree_view_bin_expose (GtkWidget *widget, return TRUE; } - gtk_tree_view_check_dirty_and_clean (GTK_TREE_VIEW (widget)); - - new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->area.y); + validate_visible_area (tree_view); + + new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->area.y); if (new_y < 0) new_y = 0; y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node); @@ -3023,39 +3109,319 @@ gtk_tree_view_focus_out (GtkWidget *widget, return FALSE; } -/* Incremental Reflow */ + +/* Incremental Reflow + */ + +/* Returns TRUE if it updated the size + */ +static gboolean +validate_row (GtkTreeView *tree_view, + GtkRBTree *tree, + GtkRBNode *node, + GtkTreeIter *iter, + GtkTreePath *path) +{ + GtkTreeViewColumn *column; + GList *list; + gint height = 0; + gint horizontal_separator; + gint depth = gtk_tree_path_get_depth (path); + gboolean retval = FALSE; + + + /* double check the row needs validating */ + if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) && + ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID)) + return FALSE; + + gtk_widget_style_get (GTK_WIDGET (tree_view), + "horizontal_separator", &horizontal_separator, + NULL); + + for (list = tree_view->priv->columns; list; list = list->next) + { + gint tmp_width; + gint tmp_height; + + column = list->data; + + if (! column->visible) + continue; + + if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID) && !column->dirty) + continue; + + if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED) + continue; + + gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter, + GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT), + node->children?TRUE:FALSE); + gtk_tree_view_column_cell_get_size (column, + NULL, NULL, NULL, + &tmp_width, &tmp_height); + height = MAX (height, tmp_height); + + if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view)) + tmp_width = tmp_width + horizontal_separator + depth * tree_view->priv->tab_offset; + else + tmp_width = tmp_width + horizontal_separator; + + if (tmp_width > column->requested_width) + { + retval = TRUE; + column->requested_width = tmp_width; + } + } + + if (height != GTK_RBNODE_GET_HEIGHT (node)) + { + retval = TRUE; + _gtk_rbtree_node_set_height (tree, node, height); + } + _gtk_rbtree_node_mark_valid (tree, node); + + return retval; +} + static void validate_visible_area (GtkTreeView *tree_view) { + GtkTreePath *path; + GtkTreeIter iter; + GtkRBTree *tree; + GtkRBNode *node; + gint y, height, offset; + gboolean validated_area = FALSE; + + if (tree_view->priv->tree == NULL) + return; + + if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID)) + return; + + + height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view); + + y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, TREE_VIEW_HEADER_HEIGHT (tree_view)); + + offset = _gtk_rbtree_find_offset (tree_view->priv->tree, y, + &tree, &node); + if (node == NULL) + { + path = gtk_tree_path_new_root (); + _gtk_tree_view_find_node (tree_view, path, &tree, &node); + } + else + { + path = _gtk_tree_view_find_path (tree_view, tree, node); + height += offset; + } + + gtk_tree_model_get_iter (tree_view->priv->model, &iter, path); + do + { + validated_area = validate_row (tree_view, tree, node, &iter, path) || validated_area; + height -= GTK_RBNODE_GET_HEIGHT (node); + if (node->children) + { + GtkTreeIter parent = iter; + gboolean has_child; + + tree = node->children; + node = tree->root; + + g_assert (node != tree->nil); + + while (node->left != tree->nil) + node = node->left; + has_child = gtk_tree_model_iter_children (tree_view->priv->model, + &iter, + &parent); + TREE_VIEW_INTERNAL_ASSERT_VOID (has_child); + gtk_tree_path_append_index (path, 0); + } + else + { + gboolean done = FALSE; + do + { + node = _gtk_rbtree_next (tree, node); + if (node != NULL) + { + gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter); + done = TRUE; + + /* Sanity Check! */ + TREE_VIEW_INTERNAL_ASSERT_VOID (has_next); + } + else + { + GtkTreeIter parent_iter = iter; + gboolean has_parent; + + node = tree->parent_node; + tree = tree->parent_tree; + if (tree == NULL) + break; + has_parent = gtk_tree_model_iter_parent (tree_view->priv->model, + &iter, + &parent_iter); + + /* Sanity check */ + TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent); + } + } + while (!done); + } + } + while (node && height > 0); + + if (validated_area) + gtk_widget_queue_resize (GTK_WIDGET (tree_view)); } +/* Our strategy for finding nodes to validate is a little convoluted. We find + * the left-most uninvalidated node. We then try walking right, validating + * nodes. Once we find a valid node, we repeat the previous process of finding + * the first invalid node. + */ + static gboolean validate_rows_handler (GtkTreeView *tree_view) { + GtkRBTree *tree = NULL; + GtkRBNode *node = NULL; + gboolean validated_area = FALSE; + gint retval = TRUE; + GtkTreePath *path = NULL; + GtkTreeIter iter; + gint i = 0; g_assert (tree_view); + g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE); - g_return_val_if_fail (tree_view->priv->tree != NULL, TRUE); + GDK_THREADS_ENTER (); - if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID)) - return TRUE; + do + { + if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID)) + { + retval = FALSE; + goto done; + } - return TRUE; + if (path != NULL) + { + node = _gtk_rbtree_next (tree, node); + if (node != NULL) + { + TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_next (tree_view->priv->model, &iter), FALSE); + gtk_tree_path_next (path); + } + else + { + gtk_tree_path_free (path); + path = NULL; + } + } + + if (path == NULL) + { + tree = tree_view->priv->tree; + node = tree_view->priv->tree->root; + + g_assert (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID)); + + do + { + if (node->left != tree->nil && + GTK_RBNODE_FLAG_SET (node->left, GTK_RBNODE_DESCENDANTS_INVALID)) + { + node = node->left; + } + else if (node->right != tree->nil && + GTK_RBNODE_FLAG_SET (node->right, GTK_RBNODE_DESCENDANTS_INVALID)) + { + node = node->right; + } + else if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) || + GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID)) + { + break; + } + else + { + tree = node->children; + node = tree->root; + } + } + while (TRUE); + path = _gtk_tree_view_find_path (tree_view, tree, node); + gtk_tree_model_get_iter (tree_view->priv->model, &iter, path); + } + validated_area = validate_row (tree_view, tree, node, &iter, path) | validated_area; + i++; + } + while (i < GTK_TREE_VIEW_NUM_ROWS_PER_IDLE); + + done: + if (path) gtk_tree_path_free (path); + if (validated_area) + gtk_widget_queue_resize (GTK_WIDGET (tree_view)); + if (! retval) + tree_view->priv->validate_rows_timer = 0; + + GDK_THREADS_LEAVE (); + + return retval; } static gboolean presize_handler_callback (gpointer data) { + GtkTreeView *tree_view = GTK_TREE_VIEW (data); - return TRUE; + GDK_THREADS_ENTER (); + + if (tree_view->priv->mark_rows_col_dirty) + { + _gtk_rbtree_column_invalid (tree_view->priv->tree); + tree_view->priv->mark_rows_col_dirty = FALSE; + } + validate_visible_area (tree_view); + tree_view->priv->presize_handler_timer = 0; + + GDK_THREADS_LEAVE (); + + return FALSE; } static void install_presize_handler (GtkTreeView *tree_view) { + if (! tree_view->priv->presize_handler_timer) + { + tree_view->priv->presize_handler_timer = + g_idle_add_full (GTK_PRIORITY_RESIZE - 2, presize_handler_callback, tree_view, NULL); + } + if (! tree_view->priv->validate_rows_timer) + { + tree_view->priv->validate_rows_timer = + g_idle_add_full (GTK_TREE_VIEW_PRIORITY_VALIDATE, (GSourceFunc) validate_rows_handler, tree_view, NULL); + } +} + +void +_gtk_tree_view_install_mark_rows_col_dirty (GtkTreeView *tree_view) +{ + tree_view->priv->mark_rows_col_dirty = TRUE; + + install_presize_handler (tree_view); } /* Drag-and-drop */ @@ -4390,18 +4756,16 @@ _gtk_tree_view_child_move_resize (GtkTreeView *tree_view, static void gtk_tree_view_row_changed (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { GtkTreeView *tree_view = (GtkTreeView *)data; GtkRBTree *tree; GtkRBNode *node; - gint height; - gboolean dirty_marked; gboolean free_path = FALSE; gint vertical_separator; - + GList *list; g_return_if_fail (path != NULL || iter != NULL); @@ -4425,28 +4789,21 @@ gtk_tree_view_row_changed (GtkTreeModel *model, if (tree == NULL) goto done; - dirty_marked = gtk_tree_view_discover_dirty_iter (tree_view, - iter, - gtk_tree_path_get_depth (path), - &height, - node); + _gtk_rbtree_node_mark_invalid (tree, node); + for (list = tree_view->priv->columns; list; list = list->next) + { + GtkTreeViewColumn *column; - if (height != -1 && - GTK_RBNODE_GET_HEIGHT (node) != height + vertical_separator) - { - _gtk_rbtree_node_set_height (tree, node, height + vertical_separator); - gtk_widget_queue_resize (GTK_WIDGET (data)); - _gtk_tree_view_update_size (tree_view); - goto done; - } - if (dirty_marked) - { - gtk_widget_queue_resize (GTK_WIDGET (data)); - } - else - { - gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL); + column = list->data; + if (! column->visible) + continue; + + if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE) + { + gtk_tree_view_column_cell_set_dirty (column); + } } + install_presize_handler (tree_view); done: if (free_path) @@ -4463,15 +4820,10 @@ gtk_tree_view_row_inserted (GtkTreeModel *model, gint *indices; GtkRBTree *tmptree, *tree; GtkRBNode *tmpnode = NULL; - gint max_height; gint depth; gint i = 0; gboolean free_path = FALSE; - if (tree_view->priv->tree == NULL) - tree_view->priv->tree = _gtk_rbtree_new (); - - tmptree = tree = tree_view->priv->tree; g_return_if_fail (path != NULL || iter != NULL); if (path == NULL) @@ -4482,6 +4834,11 @@ gtk_tree_view_row_inserted (GtkTreeModel *model, else if (iter == NULL) gtk_tree_model_get_iter (model, iter, path); + if (tree_view->priv->tree == NULL) + tree_view->priv->tree = _gtk_rbtree_new (); + + tmptree = tree = tree_view->priv->tree; + /* Update all row-references */ gtk_tree_row_reference_inserted (G_OBJECT (data), path); depth = gtk_tree_path_get_depth (path); @@ -4528,28 +4885,23 @@ gtk_tree_view_row_inserted (GtkTreeModel *model, /* ref the node */ gtk_tree_model_ref_node (tree_view->priv->model, iter); - max_height = gtk_tree_view_insert_iter_height (tree_view, - tree, - iter, - depth); if (indices[depth - 1] == 0) { tmpnode = _gtk_rbtree_find_count (tree, 1); - _gtk_rbtree_insert_before (tree, tmpnode, max_height); + _gtk_rbtree_insert_before (tree, tmpnode, 0, FALSE); } else { tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]); - _gtk_rbtree_insert_after (tree, tmpnode, max_height); + _gtk_rbtree_insert_after (tree, tmpnode, 0, FALSE); } - - _gtk_tree_view_update_size (tree_view); + install_presize_handler (tree_view); done: if (free_path) gtk_tree_path_free (path); } -#include "gtktreemodelsort.h" + static void gtk_tree_view_row_has_child_toggled (GtkTreeModel *model, GtkTreePath *path, @@ -4699,7 +5051,7 @@ gtk_tree_view_row_deleted (GtkTreeModel *model, _gtk_rbtree_remove_node (tree, node); } - _gtk_tree_view_update_size (GTK_TREE_VIEW (data)); + gtk_widget_queue_resize (GTK_WIDGET (tree_view)); if (selection_changed) g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed"); @@ -4851,71 +5203,19 @@ gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view, } } -static gint -gtk_tree_view_insert_iter_height (GtkTreeView *tree_view, - GtkRBTree *tree, - GtkTreeIter *iter, - gint depth) -{ - GtkTreeViewColumn *column; - GList *list; - gint max_height = 0; - gint vertical_separator; - - gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL); - - /* do stuff with node */ - for (list = tree_view->priv->columns; list; list = list->next) - { - gint height = 0, width = 0; - column = list->data; - - if (!column->visible) - continue; - - if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED) - continue; - - gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter, - gtk_tree_model_iter_has_child (tree_view->priv->model, iter), - FALSE); - - gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, &width, &height); - max_height = MAX (max_height, vertical_separator + height); - - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS (tree_view)) - _gtk_tree_view_column_set_width (column, - MAX (column->width, depth * tree_view->priv->tab_offset + width)); - else - _gtk_tree_view_column_set_width (column, - MAX (column->width, width)); - } - return max_height; -} - static void gtk_tree_view_build_tree (GtkTreeView *tree_view, GtkRBTree *tree, GtkTreeIter *iter, gint depth, - gboolean recurse, - gboolean calc_bounds) + gboolean recurse) { GtkRBNode *temp = NULL; - gint max_height; do { - max_height = 0; - if (calc_bounds) - max_height = gtk_tree_view_insert_iter_height (tree_view, - tree, - iter, - depth); - gtk_tree_model_ref_node (tree_view->priv->model, iter); - temp = _gtk_rbtree_insert_after (tree, temp, max_height); + temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE); if (recurse) { GtkTreeIter child; @@ -4925,7 +5225,7 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view, temp->children = _gtk_rbtree_new (); temp->children->parent_tree = tree; temp->children->parent_node = temp; - gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse, calc_bounds); + gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse); } } if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter)) @@ -4938,74 +5238,6 @@ gtk_tree_view_build_tree (GtkTreeView *tree_view, while (gtk_tree_model_iter_next (tree_view->priv->model, iter)); } -static void -gtk_tree_view_calc_size (GtkTreeView *tree_view, - GtkRBTree *tree, - GtkTreeIter *iter, - gint depth) -{ - GtkRBNode *temp; - GtkTreeIter child; - GList *list; - GtkTreeViewColumn *column; - gint max_height; - gint vertical_separator; - gint horizontal_separator; - TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL); - - gtk_widget_style_get (GTK_WIDGET (tree_view), - "vertical_separator", &vertical_separator, - "horizontal_separator", &horizontal_separator, - NULL); - - temp = tree->root; - while (temp->left != tree->nil) - temp = temp->left; - - do - { - max_height = 0; - /* Do stuff with node */ - for (list = tree_view->priv->columns; list; list = list->next) - { - gint height = 0, width = 0; - column = list->data; - - if (!column->visible) - continue; - - gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter, - GTK_RBNODE_FLAG_SET (temp, GTK_RBNODE_IS_PARENT), - temp->children?TRUE:FALSE); - gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, &width, &height); - max_height = MAX (max_height, vertical_separator + height); - - /* FIXME: I'm getting the width of all nodes here. )-: */ - if (column->dirty == FALSE) - continue; - - if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED) - { - continue; - } - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS (tree_view)) - _gtk_tree_view_column_set_width (column, - MAX (column->width, depth * tree_view->priv->tab_offset + width + horizontal_separator)); - else - _gtk_tree_view_column_set_width (column, MAX (column->width, width + horizontal_separator)); - } - - _gtk_rbtree_node_set_height (tree, temp, max_height); - - if (temp->children != NULL && - gtk_tree_model_iter_children (tree_view->priv->model, &child, iter)) - gtk_tree_view_calc_size (tree_view, temp->children, &child, depth + 1); - temp = _gtk_rbtree_next (tree, temp); - } - while (gtk_tree_model_iter_next (tree_view->priv->model, iter)); -} - /* If height is non-NULL, then we set it to be the new height. if it's all * dirty, then height is -1. We know we'll remeasure dirty rows, anyways. */ @@ -5129,61 +5361,6 @@ gtk_tree_view_discover_dirty (GtkTreeView *tree_view, } -/** - * gtk_tree_view_check_dirty_and_clean: - * @tree_view: A #GtkTreeView - * - * Does all the actual sizing for - **/ -static void -gtk_tree_view_check_dirty_and_clean (GtkTreeView *tree_view) -{ - GtkTreePath *path; - gboolean dirty = FALSE; - GList *list; - GtkTreeViewColumn *column; - GtkTreeIter iter; - - for (list = tree_view->priv->columns; list; list = list->next) - { - column = list->data; - if (column->dirty) - { - dirty = TRUE; - if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE) - { - gint w = 1; - - if (column->button) - w = MAX (w, column->button->requisition.width); - - _gtk_tree_view_column_set_width (column, w); - } - } - } - - if (dirty == FALSE) - return; - - if (tree_view->priv->model == NULL) - return; - - path = gtk_tree_path_new_root (); - if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path)) - { - gtk_tree_view_calc_size (tree_view, tree_view->priv->tree, &iter, 1); - _gtk_tree_view_update_size (tree_view); - } - - gtk_tree_path_free (path); - - for (list = tree_view->priv->columns; list; list = list->next) - { - column = list->data; - column->dirty = FALSE; - } -} - /* Make sure the node is visible vertically */ static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view, @@ -5325,6 +5502,9 @@ gtk_tree_view_is_expander_column (GtkTreeView *tree_view, { GList *list; + if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST)) + return FALSE; + if (tree_view->priv->expander_column != NULL) { if (tree_view->priv->expander_column == column) @@ -5677,6 +5857,7 @@ gtk_tree_view_queue_draw_node (GtkTreeView *tree_view, rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node); rect.height = BACKGROUND_HEIGHT (node); + // g_print ("gtk_tree_view_queue_draw_node: (%d %d) (%d %d)\n", rect.x, rect.y, rect.width, rect.height); if (clip_rect) { @@ -5777,37 +5958,6 @@ gtk_tree_view_draw_arrow (GtkTreeView *tree_view, expander_style); } - -static void -_gtk_tree_view_update_col_width (GtkTreeView *tree_view) -{ - GList *list, *last_column; - GtkTreeViewColumn *column; - gint width = 0; - - for (last_column = g_list_last (tree_view->priv->columns); - last_column && - !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) && - GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button); - last_column = last_column->prev) - ; - - if (last_column == NULL) - return; - - for (list = tree_view->priv->columns; list != last_column; list = list->next) - { - column = GTK_TREE_VIEW_COLUMN (list->data); - if (! column->visible) - continue; - - width += column->width; - column->width = (CLAMP (column->width, (column->min_width!=-1)?column->min_width:column->width, (column->max_width!=-1)?column->max_width:column->width)); - } - column = GTK_TREE_VIEW_COLUMN (last_column->data); - column->width = MAX (GTK_WIDGET (tree_view)->allocation.width, tree_view->priv->width) - width; -} - static void gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view) @@ -6281,64 +6431,6 @@ gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view) gtk_tree_view_search_init (entry, tree_view); } -void -_gtk_tree_view_update_size (GtkTreeView *tree_view) -{ - gint width, height; - GList *list; - GtkTreeViewColumn *column; - gint vertical_separator; - gint i; - - gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL); - - if (tree_view->priv->model == NULL) - { - tree_view->priv->width = 0; - tree_view->priv->height = 0; - gtk_widget_queue_draw (GTK_WIDGET (tree_view)); - return; - } - - width = 0; - for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++) - { - column = list->data; - if (!column->visible) - continue; - width += TREE_VIEW_COLUMN_WIDTH (column); - } - - if (tree_view->priv->tree == NULL) - height = 0; - else - height = tree_view->priv->tree->root->offset + vertical_separator; - - if (tree_view->priv->width != width) - { - tree_view->priv->width = width; - tree_view->priv->hadjustment->upper = width; - gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed"); - } - - if (tree_view->priv->height != height) - { - tree_view->priv->height = height; - tree_view->priv->vadjustment->upper = tree_view->priv->height; - gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed"); - } - - if (GTK_WIDGET_REALIZED (tree_view)) - { - gdk_window_resize (tree_view->priv->bin_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), height + TREE_VIEW_HEADER_HEIGHT (tree_view)); - gdk_window_resize (tree_view->priv->header_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), tree_view->priv->header_height); - - _gtk_tree_view_update_col_width (tree_view); - } - - gtk_widget_queue_resize (GTK_WIDGET (tree_view)); -} - /* this function returns the new width of the column being resized given * the column and x position of the cursor; the x cursor position is passed * in as a pointer and automagicly corrected if it's beyond min/max limits @@ -6552,16 +6644,17 @@ gtk_tree_view_set_model (GtkTreeView *tree_view, if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path)) { tree_view->priv->tree = _gtk_rbtree_new (); - gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE, GTK_WIDGET_REALIZED (tree_view)); + gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE); } gtk_tree_path_free (path); /* FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */ } - if (GTK_WIDGET_REALIZED (tree_view)) - _gtk_tree_view_update_size (tree_view); g_object_notify (G_OBJECT (tree_view), "model"); + + if (GTK_WIDGET_REALIZED (tree_view)) + gtk_widget_queue_resize (GTK_WIDGET (tree_view)); } /** @@ -7159,9 +7252,8 @@ gtk_tree_view_move_column_after (GtkTreeView *tree_view, if (GTK_WIDGET_REALIZED (tree_view)) { - /*gtk_widget_queue_resize (GTK_WIDGET (tree_view)); */ - _gtk_tree_view_update_size (tree_view); - gtk_tree_view_size_allocate_buttons (GTK_WIDGET (tree_view)); + gtk_widget_queue_resize (GTK_WIDGET (tree_view)); + gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view)); } g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0); @@ -7432,8 +7524,7 @@ gtk_tree_view_expand_all_helper (GtkRBTree *tree, node->children, &child, gtk_tree_path_get_depth (path) + 1, - TRUE, - GTK_WIDGET_REALIZED (tree_view)); + TRUE); gtk_tree_path_free (path); } } @@ -7455,8 +7546,6 @@ gtk_tree_view_expand_all (GtkTreeView *tree_view) G_PRE_ORDER, gtk_tree_view_expand_all_helper, tree_view); - - _gtk_tree_view_update_size (tree_view); } /* Timeout to animate the expander during expands and collapses */ @@ -7609,8 +7698,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view, node->children, &temp, gtk_tree_path_get_depth (path) + 1, - open_all, - GTK_WIDGET_REALIZED (tree_view)); + open_all); if (tree_view->priv->expand_collapse_timeout) { @@ -7636,10 +7724,7 @@ gtk_tree_view_real_expand_row (GtkTreeView *tree_view, } if (GTK_WIDGET_MAPPED (tree_view)) - { - gtk_widget_queue_draw (GTK_WIDGET (tree_view)); - _gtk_tree_view_update_size (tree_view); - } + install_presize_handler (tree_view); g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_EXPANDED], 0, &iter, path); return TRUE; @@ -7778,8 +7863,7 @@ gtk_tree_view_real_collapse_row (GtkTreeView *tree_view, if (GTK_WIDGET_MAPPED (tree_view)) { - gtk_widget_queue_draw (GTK_WIDGET (tree_view)); - _gtk_tree_view_update_size (tree_view); + gtk_widget_queue_resize (GTK_WIDGET (tree_view)); } if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) @@ -9455,4 +9539,3 @@ gtk_tree_view_stop_editing (GtkTreeView *tree_view) gtk_cell_editable_editing_done (tree_view->priv->edited_column->editable_widget); gtk_cell_editable_remove_widget (tree_view->priv->edited_column->editable_widget); } - diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 849a14d9c7..c66b925b8f 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -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 diff --git a/gtk/gtktreeviewcolumn.h b/gtk/gtktreeviewcolumn.h index 726a3f7c22..c81e583f51 100644 --- a/gtk/gtktreeviewcolumn.h +++ b/gtk/gtktreeviewcolumn.h @@ -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