*/
-#include <config.h>
+#include "config.h"
#include <string.h>
#include <gdk/gdkkeysyms.h>
#define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
#define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
-#define GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 500
+#define GTK_TREE_VIEW_TIME_MS_PER_IDLE 30
#define SCROLL_EDGE_SIZE 15
#define EXPANDER_EXTRA_PADDING 4
#define GTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT 5000
struct _TreeViewDragInfo
{
GdkModifierType start_button_mask;
- GtkTargetList *source_target_list;
+ GtkTargetList *_unused_source_target_list;
GdkDragAction source_actions;
- GtkTargetList *dest_target_list;
+ GtkTargetList *_unused_dest_target_list;
guint source_set : 1;
guint dest_set : 1;
GtkTreeIter *iter,
gint depth,
gboolean recurse);
-static gboolean gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
- GtkTreeIter *iter,
- gint depth,
- gint *height,
- GtkRBNode *node);
-static void gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
- GtkRBTree *tree,
- GtkTreeIter *iter,
- gint depth);
static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
GtkRBTree *tree,
GtkRBNode *node);
GParamSpec *pspec,
gpointer data);
static gboolean expand_collapse_timeout (gpointer data);
+static void add_expand_collapse_timeout (GtkTreeView *tree_view,
+ GtkRBTree *tree,
+ GtkRBNode *node,
+ gboolean expand);
+static void remove_expand_collapse_timeout (GtkTreeView *tree_view);
+static void cancel_arrow_animation (GtkTreeView *tree_view);
static gboolean do_expand_collapse (GtkTreeView *tree_view);
static void gtk_tree_view_stop_rubber_band (GtkTreeView *tree_view);
+static void update_prelight (GtkTreeView *tree_view,
+ int x,
+ int y);
/* interactive search */
static void gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view);
PROP_SEARCH_COLUMN,
g_param_spec_int ("search-column",
P_("Search Column"),
- P_("Model column to search through when searching through code"),
+ P_("Model column to search through during interactive search"),
-1,
G_MAXINT,
-1,
* Currently, this works only for the selection modes
* %GTK_SELECTION_SINGLE and %GTK_SELECTION_BROWSE.
*
- * This mode is primarily indended for treeviews in popups, e.g.
+ * This mode is primarily intended for treeviews in popups, e.g.
* in #GtkComboBox or #GtkEntryCompletion.
*
* Since: 2.6
* GtkTreeView:hover-expand:
*
* Enables of disables the hover expansion mode of @tree_view.
- * Hover expansion makes rows expand or collaps if the pointer moves
+ * Hover expansion makes rows expand or collapse if the pointer moves
* over them.
*
- * This mode is primarily indended for treeviews in popups, e.g.
+ * This mode is primarily intended for treeviews in popups, e.g.
* in #GtkComboBox or #GtkEntryCompletion.
*
* Since: 2.6
#define _TREE_VIEW_EXPANDER_SIZE 12
#define _TREE_VIEW_VERTICAL_SEPARATOR 2
#define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
-
+
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("expander-size",
P_("Expander Size"),
GTK_PARAM_READABLE));
/* Signals */
+ /**
+ * GtkTreeView::set-scroll-adjustments
+ * @horizontal: the horizontal #GtkAdjustment
+ * @vertical: the vertical #GtkAdjustment
+ *
+ * Set the scroll adjustments for the tree view. Usually scrolled containers
+ * like #GtkScrolledWindow will emit this signal to connect two instances
+ * of #GtkScrollbar to the scroll directions of the #GtkTreeView.
+ */
widget_class->set_scroll_adjustments_signal =
- g_signal_new (I_("set_scroll_adjustments"),
+ g_signal_new (I_("set-scroll-adjustments"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
* widget conceptual overview</link> as well as #GtkTreeSelection.
*/
tree_view_signals[ROW_ACTIVATED] =
- g_signal_new (I_("row_activated"),
+ g_signal_new (I_("row-activated"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, row_activated),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
NULL, NULL,
- _gtk_marshal_NONE__NONE,
+ _gtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
NULL, NULL,
- _gtk_marshal_NONE__NONE,
+ _gtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
tree_view_signals[MOVE_CURSOR] =
- g_signal_new (I_("move_cursor"),
+ g_signal_new (I_("move-cursor"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
G_TYPE_INT);
tree_view_signals[SELECT_ALL] =
- g_signal_new (I_("select_all"),
+ g_signal_new (I_("select-all"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, select_all),
NULL, NULL,
- _gtk_marshal_BOOLEAN__NONE,
+ _gtk_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
tree_view_signals[UNSELECT_ALL] =
- g_signal_new (I_("unselect_all"),
+ g_signal_new (I_("unselect-all"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, unselect_all),
NULL, NULL,
- _gtk_marshal_BOOLEAN__NONE,
+ _gtk_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
tree_view_signals[SELECT_CURSOR_ROW] =
- g_signal_new (I_("select_cursor_row"),
+ g_signal_new (I_("select-cursor-row"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
G_TYPE_BOOLEAN);
tree_view_signals[TOGGLE_CURSOR_ROW] =
- g_signal_new (I_("toggle_cursor_row"),
+ g_signal_new (I_("toggle-cursor-row"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
NULL, NULL,
- _gtk_marshal_BOOLEAN__NONE,
+ _gtk_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
- g_signal_new (I_("expand_collapse_cursor_row"),
+ g_signal_new (I_("expand-collapse-cursor-row"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
G_TYPE_BOOLEAN);
tree_view_signals[SELECT_CURSOR_PARENT] =
- g_signal_new (I_("select_cursor_parent"),
+ g_signal_new (I_("select-cursor-parent"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
NULL, NULL,
- _gtk_marshal_BOOLEAN__NONE,
+ _gtk_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
tree_view_signals[START_INTERACTIVE_SEARCH] =
- g_signal_new (I_("start_interactive_search"),
+ g_signal_new (I_("start-interactive-search"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkTreeViewClass, start_interactive_search),
NULL, NULL,
- _gtk_marshal_BOOLEAN__NONE,
+ _gtk_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
/* Key bindings */
GTK_MOVEMENT_PAGES, 1);
- gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move_cursor", 2,
+ gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, 1);
- gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move_cursor", 2,
+ gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, -1);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0, "move_cursor", 2,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0, "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, 1);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0, "move_cursor", 2,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0, "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, -1);
gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, -1);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
G_TYPE_INT, -1);
- gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle_cursor_row", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select_all", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK, "select_all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK, "select-all", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect_all", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK, "unselect_all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK, "unselect-all", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select_cursor_row", 1,
+ gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1,
+ gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select-cursor-row", 1,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select_cursor_row", 1,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0, "select-cursor-row", 1,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select_cursor_row", 1,
+ gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select-cursor-row", 1,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select_cursor_row", 1,
+ gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select-cursor-row", 1,
G_TYPE_BOOLEAN, TRUE);
/* expand and collapse rows */
- gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE);
gtk_binding_entry_add_signal (binding_set, GDK_asterisk, 0,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Multiply, 0,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_slash, 0,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, 0,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE);
/* Not doable on US keyboards */
- gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_Right,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Right,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_minus, 0, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_minus, 0, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE);
- gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE);
- gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_Left,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_KP_Left,
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand_collapse_cursor_row", 3,
+ "expand-collapse-cursor-row", 3,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE);
- gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK, "select_cursor_parent", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select-cursor-parent", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start_interactive_search", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start-interactive-search", 0);
- gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start-interactive-search", 0);
g_type_class_add_private (o_class, sizeof (GtkTreeViewPrivate));
}
{
tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_view, GTK_TYPE_TREE_VIEW, GtkTreeViewPrivate);
- GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
-
+ gtk_widget_set_can_focus (GTK_WIDGET (tree_view), TRUE);
gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
tree_view->priv->flags = GTK_TREE_VIEW_SHOW_EXPANDERS
tree_view->priv->tree_lines_enabled = FALSE;
tree_view->priv->tooltip_column = -1;
+
+ tree_view->priv->post_validation_flag = FALSE;
+
+ tree_view->priv->last_button_x = -1;
+ tree_view->priv->last_button_y = -1;
+
+ tree_view->priv->event_last_x = -10000;
+ tree_view->priv->event_last_y = -10000;
}
\f
static void
gtk_tree_view_finalize (GObject *object)
{
- (* G_OBJECT_CLASS (gtk_tree_view_parent_class)->finalize) (object);
+ G_OBJECT_CLASS (gtk_tree_view_parent_class)->finalize (object);
}
\f
tree_view->priv->drag_dest_row = NULL;
}
- if (tree_view->priv->last_button_press != NULL)
- {
- gtk_tree_row_reference_free (tree_view->priv->last_button_press);
- tree_view->priv->last_button_press = NULL;
- }
-
- if (tree_view->priv->last_button_press_2 != NULL)
- {
- gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
- tree_view->priv->last_button_press_2 = NULL;
- }
-
if (tree_view->priv->top_row != NULL)
{
gtk_tree_row_reference_free (tree_view->priv->top_row);
if (tree_view->priv->column_drop_func_data &&
tree_view->priv->column_drop_func_data_destroy)
{
- (* tree_view->priv->column_drop_func_data_destroy) (tree_view->priv->column_drop_func_data);
+ tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
tree_view->priv->column_drop_func_data = NULL;
}
if (tree_view->priv->destroy_count_destroy &&
tree_view->priv->destroy_count_data)
{
- (* tree_view->priv->destroy_count_destroy) (tree_view->priv->destroy_count_data);
+ tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
tree_view->priv->destroy_count_data = NULL;
}
if (tree_view->priv->search_destroy && tree_view->priv->search_user_data)
{
- (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
+ tree_view->priv->search_destroy (tree_view->priv->search_user_data);
tree_view->priv->search_user_data = NULL;
}
if (tree_view->priv->search_position_destroy && tree_view->priv->search_position_user_data)
{
- (* tree_view->priv->search_position_destroy) (tree_view->priv->search_position_user_data);
+ tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
tree_view->priv->search_position_user_data = NULL;
}
if (tree_view->priv->row_separator_destroy && tree_view->priv->row_separator_data)
{
- (* tree_view->priv->row_separator_destroy) (tree_view->priv->row_separator_data);
+ tree_view->priv->row_separator_destroy (tree_view->priv->row_separator_data);
tree_view->priv->row_separator_data = NULL;
}
tree_view->priv->vadjustment = NULL;
}
- if (GTK_OBJECT_CLASS (gtk_tree_view_parent_class)->destroy)
- (* GTK_OBJECT_CLASS (gtk_tree_view_parent_class)->destroy) (object);
+ GTK_OBJECT_CLASS (gtk_tree_view_parent_class)->destroy (object);
}
\f
{
GList *list;
- g_return_if_fail (GTK_WIDGET_MAPPED (tree_view));
+ g_return_if_fail (gtk_widget_get_mapped (GTK_WIDGET (tree_view)));
if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
{
for (list = tree_view->priv->columns; list; list = list->next)
{
column = list->data;
- if (GTK_WIDGET_VISIBLE (column->button) &&
- !GTK_WIDGET_MAPPED (column->button))
+ if (gtk_widget_get_visible (column->button) &&
+ !gtk_widget_get_mapped (column->button))
gtk_widget_map (column->button);
}
for (list = tree_view->priv->columns; list; list = list->next)
static void
gtk_tree_view_map (GtkWidget *widget)
{
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GList *tmp_list;
- GtkTreeView *tree_view;
-
- g_return_if_fail (GTK_IS_TREE_VIEW (widget));
-
- tree_view = GTK_TREE_VIEW (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
GtkTreeViewChild *child = tmp_list->data;
tmp_list = tmp_list->next;
- if (GTK_WIDGET_VISIBLE (child->widget))
+ if (gtk_widget_get_visible (child->widget))
{
- if (!GTK_WIDGET_MAPPED (child->widget))
+ if (!gtk_widget_get_mapped (child->widget))
gtk_widget_map (child->widget);
}
}
static void
gtk_tree_view_realize (GtkWidget *widget)
{
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GList *tmp_list;
- GtkTreeView *tree_view;
GdkWindowAttr attributes;
gint attributes_mask;
- g_return_if_fail (GTK_IS_TREE_VIEW (widget));
-
- tree_view = GTK_TREE_VIEW (widget);
-
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
/* Make the main, clipping window */
attributes.y = TREE_VIEW_HEADER_HEIGHT (tree_view);
attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
attributes.height = widget->allocation.height;
- attributes.event_mask = GDK_EXPOSURE_MASK |
- GDK_SCROLL_MASK |
- GDK_POINTER_MOTION_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- gtk_widget_get_events (widget);
+ attributes.event_mask = (GDK_EXPOSURE_MASK |
+ GDK_SCROLL_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ gtk_widget_get_events (widget));
tree_view->priv->bin_window = gdk_window_new (widget->window,
&attributes, attributes_mask);
attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
attributes.height = tree_view->priv->header_height;
attributes.event_mask = (GDK_EXPOSURE_MASK |
- GDK_SCROLL_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_KEY_PRESS_MASK |
- GDK_KEY_RELEASE_MASK) |
- gtk_widget_get_events (widget);
+ GDK_SCROLL_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ gtk_widget_get_events (widget));
tree_view->priv->header_window = gdk_window_new (widget->window,
&attributes, attributes_mask);
static void
gtk_tree_view_unrealize (GtkWidget *widget)
{
- GtkTreeView *tree_view;
- GtkTreeViewPrivate *priv;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+ GtkTreeViewPrivate *priv = tree_view->priv;
GList *list;
- g_return_if_fail (GTK_IS_TREE_VIEW (widget));
-
- tree_view = GTK_TREE_VIEW (widget);
- priv = tree_view->priv;
-
if (priv->scroll_timeout != 0)
{
g_source_remove (priv->scroll_timeout);
priv->open_dest_timeout = 0;
}
- if (priv->expand_collapse_timeout != 0)
- {
- g_source_remove (priv->expand_collapse_timeout);
- priv->expand_collapse_timeout = 0;
- }
+ remove_expand_collapse_timeout (tree_view);
if (priv->presize_handler_timer != 0)
{
priv->grid_line_gc = NULL;
}
- /* GtkWidget::unrealize destroys children and widget->window */
- if (GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize)
- (* GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize) (widget);
+ GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize (widget);
}
/* GtkWidget::size_request helper */
tree_view->priv->prev_width = tree_view->priv->width;
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++)
{
gtk_tree_view_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GList *tmp_list;
- g_return_if_fail (GTK_IS_TREE_VIEW (widget));
-
- tree_view = GTK_TREE_VIEW (widget);
-
- /* we validate GTK_TREE_VIEW_NUM_ROWS_PER_IDLE rows initially just to make
- * sure we have some size. In practice, with a lot of static lists, this
- * should get a good width.
+ /* we validate some rows initially just to make sure we have some size.
+ * In practice, with a lot of static lists, this should get a good width.
*/
do_validate_rows (tree_view, FALSE);
gtk_tree_view_size_request_columns (tree_view);
tmp_list = tmp_list->next;
- if (GTK_WIDGET_VISIBLE (child->widget))
+ if (gtk_widget_get_visible (child->widget))
gtk_widget_size_request (child->widget, &child_requisition);
}
}
+static int
+gtk_tree_view_calculate_width_before_expander (GtkTreeView *tree_view)
+{
+ int width = 0;
+ GList *list;
+ gboolean rtl;
+
+ rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+ for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+ list->data != tree_view->priv->expander_column;
+ list = (rtl ? list->prev : list->next))
+ {
+ GtkTreeViewColumn *column = list->data;
+
+ width += column->width;
+ }
+
+ return width;
+}
static void
invalidate_column (GtkTreeView *tree_view,
/* GtkWidget::size_allocate helper */
static void
-gtk_tree_view_size_allocate_columns (GtkWidget *widget)
+gtk_tree_view_size_allocate_columns (GtkWidget *widget,
+ gboolean *width_changed)
{
GtkTreeView *tree_view;
GList *list, *first_column, *last_column;
GtkTreeViewColumn *column;
GtkAllocation allocation;
gint width = 0;
- gint extra, extra_per_column;
+ gint extra, extra_per_column, extra_for_last;
gint full_requested_width = 0;
gint number_of_expand_columns = 0;
gboolean column_changed = FALSE;
gboolean rtl;
+ gboolean update_expand;
tree_view = GTK_TREE_VIEW (widget);
number_of_expand_columns++;
}
- extra = MAX (widget->allocation.width - full_requested_width, 0);
+ /* Only update the expand value if the width of the widget has changed,
+ * or the number of expand columns has changed, or if there are no expand
+ * columns, or if we didn't have an size-allocation yet after the
+ * last validated node.
+ */
+ update_expand = (width_changed && *width_changed == TRUE)
+ || number_of_expand_columns != tree_view->priv->last_number_of_expand_columns
+ || number_of_expand_columns == 0
+ || tree_view->priv->post_validation_flag == TRUE;
+
+ tree_view->priv->post_validation_flag = FALSE;
+
+ if (!update_expand)
+ {
+ extra = tree_view->priv->last_extra_space;
+ extra_for_last = MAX (widget->allocation.width - full_requested_width - extra, 0);
+ }
+ else
+ {
+ extra = MAX (widget->allocation.width - full_requested_width, 0);
+ extra_for_last = 0;
+
+ tree_view->priv->last_extra_space = extra;
+ }
+
if (number_of_expand_columns > 0)
extra_per_column = extra/number_of_expand_columns;
else
extra_per_column = 0;
+ if (update_expand)
+ {
+ tree_view->priv->last_extra_space_per_column = extra_per_column;
+ tree_view->priv->last_number_of_expand_columns = number_of_expand_columns;
+ }
+
for (list = (rtl ? last_column : first_column);
list != (rtl ? first_column->prev : last_column->next);
list = (rtl ? list->prev : list->next))
column->width += extra;
}
+ /* In addition to expand, the last column can get even more
+ * extra space so all available space is filled up.
+ */
+ if (extra_for_last > 0 && list == last_column)
+ column->width += extra_for_last;
+
g_object_notify (G_OBJECT (column), "width");
allocation.width = column->width;
TREE_VIEW_DRAG_WIDTH, allocation.height);
}
+ /* We change the width here. The user might have been resizing columns,
+ * so the total width of the tree view changes.
+ */
+ tree_view->priv->width = width;
+ if (width_changed)
+ *width_changed = TRUE;
+
if (column_changed)
gtk_widget_queue_draw (GTK_WIDGET (tree_view));
}
gtk_tree_view_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GList *tmp_list;
- GtkTreeView *tree_view;
gboolean width_changed = FALSE;
- gint old_width = widget->allocation.width;
-
- g_return_if_fail (GTK_IS_TREE_VIEW (widget));
+ gint old_width = widget->allocation.width;
if (allocation->width != widget->allocation.width)
width_changed = TRUE;
-
- widget->allocation = *allocation;
- tree_view = GTK_TREE_VIEW (widget);
+ widget->allocation = *allocation;
tmp_list = tree_view->priv->children;
gtk_widget_size_allocate (child->widget, &allocation);
}
+ /* We size-allocate the columns first because the width of the
+ * tree view (used in updating the adjustments below) might change.
+ */
+ gtk_tree_view_size_allocate_columns (widget, &width_changed);
tree_view->priv->hadjustment->page_size = allocation->width;
tree_view->priv->hadjustment->page_increment = allocation->width * 0.9;
tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->page_size, tree_view->priv->width);
if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)
- {
+ {
if (allocation->width < tree_view->priv->width)
- {
- if (tree_view->priv->init_hadjust_value)
- {
- tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
- tree_view->priv->init_hadjust_value = FALSE;
- }
- else if(allocation->width != old_width)
- tree_view->priv->hadjustment->value = CLAMP(tree_view->priv->hadjustment->value - allocation->width + old_width, 0, tree_view->priv->width - allocation->width);
- else
- tree_view->priv->hadjustment->value = CLAMP(tree_view->priv->width - (tree_view->priv->prev_width - tree_view->priv->hadjustment->value), 0, tree_view->priv->width - allocation->width);
- }
+ {
+ if (tree_view->priv->init_hadjust_value)
+ {
+ tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
+ tree_view->priv->init_hadjust_value = FALSE;
+ }
+ else if (allocation->width != old_width)
+ {
+ tree_view->priv->hadjustment->value = CLAMP (tree_view->priv->hadjustment->value - allocation->width + old_width, 0, tree_view->priv->width - allocation->width);
+ }
+ else
+ tree_view->priv->hadjustment->value = CLAMP (tree_view->priv->width - (tree_view->priv->prev_width - tree_view->priv->hadjustment->value), 0, tree_view->priv->width - allocation->width);
+ }
else
- {
- tree_view->priv->hadjustment->value = 0;
- tree_view->priv->init_hadjust_value = TRUE;
- }
- }
+ {
+ tree_view->priv->hadjustment->value = 0;
+ tree_view->priv->init_hadjust_value = TRUE;
+ }
+ }
else
- if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
- tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
+ if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
+ tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
gtk_adjustment_changed (tree_view->priv->hadjustment);
allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view));
}
- gtk_tree_view_size_allocate_columns (widget);
-
if (tree_view->priv->tree == NULL)
invalidate_empty_focus (tree_view);
}
}
+ if (width_changed && tree_view->priv->expander_column)
+ {
+ /* Might seem awkward, but is the best heuristic I could come up
+ * with. Only if the width of the columns before the expander
+ * changes, we will update the prelight status. It is this
+ * width that makes the expander move vertically. Always updating
+ * prelight status causes trouble with hover selections.
+ */
+ gint width_before_expander;
+
+ width_before_expander = gtk_tree_view_calculate_width_before_expander (tree_view);
+
+ if (tree_view->priv->prev_width_before_expander
+ != width_before_expander)
+ update_prelight (tree_view,
+ tree_view->priv->event_last_x,
+ tree_view->priv->event_last_y);
+
+ tree_view->priv->prev_width_before_expander = width_before_expander;
+ }
+
/* This little hack only works if we have an LTR locale, and no column has the */
if (width_changed)
{
static void
grab_focus_and_unset_draw_keyfocus (GtkTreeView *tree_view)
{
- if (!GTK_WIDGET_HAS_FOCUS (tree_view))
- gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+ GtkWidget *widget = GTK_WIDGET (tree_view);
+
+ if (gtk_widget_get_can_focus (widget) && !gtk_widget_has_focus (widget))
+ gtk_widget_grab_focus (widget);
GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
}
else
gtk_tree_model_get_iter (tree_view->priv->model, &tmpiter, path);
- is_separator = (* tree_view->priv->row_separator_func) (tree_view->priv->model,
- &tmpiter,
- tree_view->priv->row_separator_data);
+ is_separator = tree_view->priv->row_separator_func (tree_view->priv->model,
+ &tmpiter,
+ tree_view->priv->row_separator_data);
}
return is_separator;
gtk_tree_view_button_press (GtkWidget *widget,
GdkEventButton *event)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GList *list;
GtkTreeViewColumn *column = NULL;
gint i;
gboolean path_is_selectable;
gboolean rtl;
- g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- tree_view = GTK_TREE_VIEW (widget);
rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
gtk_tree_view_stop_editing (tree_view, FALSE);
gtk_widget_style_get (widget,
}
/* Test if a double click happened on the same row. */
- if (event->button == 1)
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
{
- /* We also handle triple clicks here, because a user could have done
- * a first click and a second double click on different rows.
- */
- if ((event->type == GDK_2BUTTON_PRESS
- || event->type == GDK_3BUTTON_PRESS)
- && tree_view->priv->last_button_press)
+ int double_click_time, double_click_distance;
+
+ g_object_get (gtk_settings_get_default (),
+ "gtk-double-click-time", &double_click_time,
+ "gtk-double-click-distance", &double_click_distance,
+ NULL);
+
+ /* Same conditions as _gdk_event_button_generate */
+ if (tree_view->priv->last_button_x != -1 &&
+ (event->time < tree_view->priv->last_button_time + double_click_time) &&
+ (ABS (event->x - tree_view->priv->last_button_x) <= double_click_distance) &&
+ (ABS (event->y - tree_view->priv->last_button_y) <= double_click_distance))
{
- GtkTreePath *lsc;
-
- lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
-
- if (lsc)
- {
- row_double_click = !gtk_tree_path_compare (lsc, path);
- gtk_tree_path_free (lsc);
- }
- }
+ /* We do no longer compare paths of this row and the
+ * row clicked previously. We use the double click
+ * distance to decide whether this is a valid click,
+ * allowing the mouse to slightly move over another row.
+ */
+ row_double_click = TRUE;
- if (row_double_click)
- {
- if (tree_view->priv->last_button_press)
- gtk_tree_row_reference_free (tree_view->priv->last_button_press);
- if (tree_view->priv->last_button_press_2)
- gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
- tree_view->priv->last_button_press = NULL;
- tree_view->priv->last_button_press_2 = NULL;
+ tree_view->priv->last_button_time = 0;
+ tree_view->priv->last_button_x = -1;
+ tree_view->priv->last_button_y = -1;
}
else
{
- if (tree_view->priv->last_button_press)
- gtk_tree_row_reference_free (tree_view->priv->last_button_press);
- tree_view->priv->last_button_press = tree_view->priv->last_button_press_2;
- tree_view->priv->last_button_press_2 = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
+ tree_view->priv->last_button_time = event->time;
+ tree_view->priv->last_button_x = event->x;
+ tree_view->priv->last_button_y = event->y;
}
}
gtk_grab_add (widget);
GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
- column->resized_width = column->width;
+ column->resized_width = column->width - tree_view->priv->last_extra_space_per_column;
/* block attached dnd signal handler */
drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
tree_view->priv->drag_pos = i;
tree_view->priv->x_drag = column->button->allocation.x + (rtl ? 0 : column->button->allocation.width);
- if (!GTK_WIDGET_HAS_FOCUS (widget))
+ if (!gtk_widget_has_focus (widget))
gtk_widget_grab_focus (widget);
return TRUE;
GdkEventButton *event)
{
GtkTreeView *tree_view;
+ GList *l;
gboolean rtl;
tree_view = GTK_TREE_VIEW (widget);
tree_view->priv->drag_column = NULL;
gdk_window_hide (tree_view->priv->drag_window);
- g_list_foreach (tree_view->priv->column_drag_info, (GFunc) g_free, NULL);
+ for (l = tree_view->priv->column_drag_info; l != NULL; l = l->next)
+ g_slice_free (GtkTreeViewColumnReorder, l->data);
g_list_free (tree_view->priv->column_drag_info);
tree_view->priv->column_drag_info = NULL;
tree_view->priv->cur_reorder = NULL;
gtk_tree_view_button_release (GtkWidget *widget,
GdkEventButton *event)
{
- GtkTreeView *tree_view;
-
- g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- tree_view = GTK_TREE_VIEW (widget);
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
return gtk_tree_view_button_release_drag_column (widget, event);
gtk_tree_view_grab_broken (GtkWidget *widget,
GdkEventGrabBroken *event)
{
- GtkTreeView *tree_view;
-
- g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- tree_view = GTK_TREE_VIEW (widget);
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
gtk_tree_view_button_release_drag_column (widget, (GdkEventButton *)event);
g_assert (tree_view->priv->prelight_node == NULL);
}
+static void
+update_prelight (GtkTreeView *tree_view,
+ gint x,
+ gint y)
+{
+ int new_y;
+ GtkRBTree *tree;
+ GtkRBNode *node;
+
+ if (tree_view->priv->tree == NULL)
+ return;
+
+ if (x == -10000)
+ {
+ ensure_unprelighted (tree_view);
+ return;
+ }
+
+ new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y);
+ if (new_y < 0)
+ new_y = 0;
+
+ _gtk_rbtree_find_offset (tree_view->priv->tree,
+ new_y, &tree, &node);
+
+ if (node)
+ prelight_or_select (tree_view, tree, node, x, y);
+}
+
{
column->use_resized_width = TRUE;
column->resized_width = new_width;
+ if (column->expand)
+ column->resized_width -= tree_view->priv->last_extra_space_per_column;
gtk_widget_queue_resize (widget);
}
remove_scroll_timeout (tree_view);
gtk_grab_remove (GTK_WIDGET (tree_view));
- gtk_widget_queue_draw (GTK_WIDGET (tree_view));
-
if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
{
GtkTreePath *tmp_path;
+ gtk_widget_queue_draw (GTK_WIDGET (tree_view));
+
/* The anchor path should be set to the start path */
tmp_path = _gtk_tree_view_find_path (tree_view,
tree_view->priv->rubber_band_start_tree,
(tree_view->priv->button_pressed_node != node))
node = NULL;
+ tree_view->priv->event_last_x = event->x;
+ tree_view->priv->event_last_y = event->y;
+
prelight_or_select (tree_view, tree, node, event->x, event->y);
return TRUE;
{
GdkRectangle area;
- if (!GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return;
area.x = 0;
{
gint w, h;
- if (!GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return;
gdk_drawable_get_size (tree_view->priv->bin_window, &w, &h);
gtk_tree_view_bin_expose (GtkWidget *widget,
GdkEventExpose *event)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GtkTreePath *path;
GtkRBTree *tree;
GList *list;
gboolean row_ending_details;
gboolean draw_vgrid_lines, draw_hgrid_lines;
- g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
-
rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
- tree_view = GTK_TREE_VIEW (widget);
-
gtk_widget_style_get (widget,
"horizontal-separator", &horizontal_separator,
"vertical-separator", &vertical_separator,
background_area.y + max_height);
}
- if (gtk_tree_view_is_expander_column (tree_view, column) &&
- tree_view->priv->tree_lines_enabled)
- {
- if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT
- && depth > 1)
- {
- gdk_draw_line (event->window,
- tree_view->priv->tree_line_gc,
- background_area.x + tree_view->priv->expander_size * (depth - 1.5),
- background_area.y + background_area.height / 2,
- background_area.x + tree_view->priv->expander_size * (depth - 1.1),
- background_area.y + background_area.height / 2);
- }
- else if (depth > 1)
- {
- gdk_draw_line (event->window,
- tree_view->priv->tree_line_gc,
- background_area.x + tree_view->priv->expander_size * (depth - 1.5),
- background_area.y + background_area.height / 2,
- background_area.x + tree_view->priv->expander_size * (depth - 0.5),
- background_area.y + background_area.height / 2);
- }
-
- if (depth > 1)
- {
- gint i;
- GtkRBNode *tmp_node;
- GtkRBTree *tmp_tree;
-
- if (!_gtk_rbtree_next (tree, node))
- gdk_draw_line (event->window,
- tree_view->priv->tree_line_gc,
- background_area.x + tree_view->priv->expander_size * (depth - 1.5),
- background_area.y,
- background_area.x + tree_view->priv->expander_size * (depth - 1.5),
- background_area.y + background_area.height / 2);
- else
- gdk_draw_line (event->window,
- tree_view->priv->tree_line_gc,
- background_area.x + tree_view->priv->expander_size * (depth - 1.5),
- background_area.y,
- background_area.x + tree_view->priv->expander_size * (depth - 1.5),
- background_area.y + background_area.height);
-
- tmp_node = tree->parent_node;
- tmp_tree = tree->parent_tree;
-
- for (i = depth - 2; i > 0; i--)
- {
- if (_gtk_rbtree_next (tmp_tree, tmp_node))
- gdk_draw_line (event->window,
- tree_view->priv->tree_line_gc,
- background_area.x + tree_view->priv->expander_size * (i - 0.5),
- background_area.y,
- background_area.x + tree_view->priv->expander_size * (i - 0.5),
- background_area.y + background_area.height);
-
- tmp_node = tmp_tree->parent_node;
- tmp_tree = tmp_tree->parent_tree;
- }
- }
- }
-
if (gtk_tree_view_is_expander_column (tree_view, column))
{
if (!rtl)
&event->area,
flags);
}
+
+ if (gtk_tree_view_is_expander_column (tree_view, column) &&
+ tree_view->priv->tree_lines_enabled)
+ {
+ gint x = background_area.x;
+ gint mult = rtl ? -1 : 1;
+ gint y0 = background_area.y;
+ gint y1 = background_area.y + background_area.height/2;
+ gint y2 = background_area.y + background_area.height;
+
+ if (rtl)
+ x += background_area.width - 1;
+
+ if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT
+ && depth > 1)
+ {
+ gdk_draw_line (event->window,
+ tree_view->priv->tree_line_gc,
+ x + tree_view->priv->expander_size * (depth - 1.5) * mult,
+ y1,
+ x + tree_view->priv->expander_size * (depth - 1.1) * mult,
+ y1);
+ }
+ else if (depth > 1)
+ {
+ gdk_draw_line (event->window,
+ tree_view->priv->tree_line_gc,
+ x + tree_view->priv->expander_size * (depth - 1.5) * mult,
+ y1,
+ x + tree_view->priv->expander_size * (depth - 0.5) * mult,
+ y1);
+ }
+
+ if (depth > 1)
+ {
+ gint i;
+ GtkRBNode *tmp_node;
+ GtkRBTree *tmp_tree;
+
+ if (!_gtk_rbtree_next (tree, node))
+ gdk_draw_line (event->window,
+ tree_view->priv->tree_line_gc,
+ x + tree_view->priv->expander_size * (depth - 1.5) * mult,
+ y0,
+ x + tree_view->priv->expander_size * (depth - 1.5) * mult,
+ y1);
+ else
+ gdk_draw_line (event->window,
+ tree_view->priv->tree_line_gc,
+ x + tree_view->priv->expander_size * (depth - 1.5) * mult,
+ y0,
+ x + tree_view->priv->expander_size * (depth - 1.5) * mult,
+ y2);
+
+ tmp_node = tree->parent_node;
+ tmp_tree = tree->parent_tree;
+
+ for (i = depth - 2; i > 0; i--)
+ {
+ if (_gtk_rbtree_next (tmp_tree, tmp_node))
+ gdk_draw_line (event->window,
+ tree_view->priv->tree_line_gc,
+ x + tree_view->priv->expander_size * (i - 0.5) * mult,
+ y0,
+ x + tree_view->priv->expander_size * (i - 0.5) * mult,
+ y2);
+
+ tmp_node = tmp_tree->parent_node;
+ tmp_tree = tmp_tree->parent_tree;
+ }
+ }
+ }
+
if (node == cursor && has_special_cell &&
((column == tree_view->priv->focus_column &&
GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
- GTK_WIDGET_HAS_FOCUS (widget)) ||
+ gtk_widget_has_focus (widget)) ||
(column == tree_view->priv->edited_column)))
{
_gtk_tree_view_column_cell_draw_focus (column,
&event->area,
flags);
}
+
cell_offset += column->width;
}
/* draw the big row-spanning focus rectangle, if needed */
if (!has_special_cell && node == cursor &&
GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
- GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_has_focus (widget))
{
gint tmp_y, tmp_height;
gint width;
gtk_tree_view_expose (GtkWidget *widget,
GdkEventExpose *event)
{
- GtkTreeView *tree_view;
-
- g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
-
- tree_view = GTK_TREE_VIEW (widget);
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
if (event->window == tree_view->priv->bin_window)
{
if (!tree_view->priv->column_drop_func)
return left_column;
- if (!(*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+ if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
{
left_column = cur_column;
continue;
if (!tree_view->priv->column_drop_func)
return left_column;
- if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
+ if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
return left_column;
else
return (GtkTreeViewColumn *)0x1;
if (!tree_view->priv->column_drop_func)
return left_column;
- if (!(*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+ if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
{
left_column = cur_column;
continue;
if (!tree_view->priv->column_drop_func)
return left_column;
- if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
+ if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
return left_column;
else
return (GtkTreeViewColumn *)0x1;
if (!tree_view->priv->column_drop_func)
return left_column;
- if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+ if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
return left_column;
cur_column = left_column;
if (!tree_view->priv->column_drop_func)
return NULL;
- if ((*tree_view->priv->column_drop_func) (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
+ if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
return NULL;
else
return (GtkTreeViewColumn *)0x1;
if (!tree_view->priv->column_drop_func)
return left_column;
- if ((*tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+ if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
return left_column;
cur_column = left_column;
if (!tree_view->priv->column_drop_func)
return NULL;
- if ((*tree_view->priv->column_drop_func) (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
+ if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
return NULL;
else
return (GtkTreeViewColumn *)0x1;
{
GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (focus_column->data);
- if (GTK_WIDGET_HAS_FOCUS (column->button))
+ if (gtk_widget_has_focus (column->button))
break;
}
if (GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_press_event (widget, event))
return TRUE;
+ if (tree_view->priv->search_entry_avoid_unhandled_binding)
+ {
+ tree_view->priv->search_entry_avoid_unhandled_binding = FALSE;
+ return FALSE;
+ }
+
/* We pass the event to the search_entry. If its text changes, then we start
* the typeahead find capabilities. */
- if (GTK_WIDGET_HAS_FOCUS (tree_view)
+ if (gtk_widget_has_focus (GTK_WIDGET (tree_view))
&& tree_view->priv->enable_search
&& !tree_view->priv->search_custom_entry_set)
{
gtk_widget_realize (tree_view->priv->search_window);
popup_menu_id = g_signal_connect (tree_view->priv->search_entry,
- "popup_menu", G_CALLBACK (gtk_true), NULL);
+ "popup-menu", G_CALLBACK (gtk_true),
+ NULL);
/* Move the entry off screen */
screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
if (tree_view->priv->rubber_band_status)
return TRUE;
- return (* GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_release_event) (widget, event);
+ return GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->key_release_event (widget, event);
}
/* FIXME Is this function necessary? Can I get an enter_notify event
gtk_tree_view_enter_notify (GtkWidget *widget,
GdkEventCrossing *event)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GtkRBTree *tree;
GtkRBNode *node;
gint new_y;
- g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
-
- tree_view = GTK_TREE_VIEW (widget);
-
/* Sanity check it */
if (event->window != tree_view->priv->bin_window)
return FALSE;
if (tree_view->priv->tree == NULL)
return FALSE;
+ if (event->mode == GDK_CROSSING_GRAB ||
+ event->mode == GDK_CROSSING_GTK_GRAB ||
+ event->mode == GDK_CROSSING_GTK_UNGRAB ||
+ event->mode == GDK_CROSSING_STATE_CHANGED)
+ return TRUE;
+
/* find the node internally */
new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
if (new_y < 0)
new_y = 0;
_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
+ tree_view->priv->event_last_x = event->x;
+ tree_view->priv->event_last_y = event->y;
+
if ((tree_view->priv->button_pressed_node == NULL) ||
(tree_view->priv->button_pressed_node == node))
prelight_or_select (tree_view, tree, node, event->x, event->y);
tree_view->priv->prelight_node,
NULL);
+ tree_view->priv->event_last_x = -10000;
+ tree_view->priv->event_last_y = -10000;
+
prelight_or_select (tree_view,
NULL, NULL,
-1000, -1000); /* coords not possibly over an arrow */
gboolean draw_vgrid_lines, draw_hgrid_lines;
gint focus_pad;
gint grid_line_width;
+ gboolean wide_separators;
+ gint separator_height;
/* double check the row needs validating */
if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
"horizontal-separator", &horizontal_separator,
"vertical-separator", &vertical_separator,
"grid-line-width", &grid_line_width,
+ "wide-separators", &wide_separators,
+ "separator-height", &separator_height,
NULL);
draw_vgrid_lines =
height = MAX (height, tree_view->priv->expander_size);
}
else
- height = 2 + 2 * focus_pad;
+ {
+ if (wide_separators)
+ height = separator_height + 2 * focus_pad;
+ else
+ height = 2 + 2 * focus_pad;
+ }
if (gtk_tree_view_is_expander_column (tree_view, column))
{
_gtk_rbtree_node_set_height (tree, node, height);
}
_gtk_rbtree_node_mark_valid (tree, node);
+ tree_view->priv->post_validation_flag = TRUE;
return retval;
}
while (area_above > 0)
{
_gtk_rbtree_prev_full (tree, node, &tree, &node);
- if (! gtk_tree_path_prev (above_path) && node != NULL)
- {
- gtk_tree_path_free (above_path);
- above_path = _gtk_tree_view_find_path (tree_view, tree, node);
- }
- gtk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
+
+ /* Always find the new path in the tree. We cannot just assume
+ * a gtk_tree_path_prev() is enough here, as there might be children
+ * in between this node and the previous sibling node. If this
+ * appears to be a performance hotspot in profiles, we can look into
+ * intrigate logic for keeping path, node and iter in sync like
+ * we do for forward walks. (Which will be hard because of the lacking
+ * iter_prev).
+ */
if (node == NULL)
break;
+ gtk_tree_path_free (above_path);
+ above_path = _gtk_tree_view_find_path (tree_view, tree, node);
+
+ gtk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
+
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) ||
GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))
{
gint retval = TRUE;
GtkTreePath *path = NULL;
GtkTreeIter iter;
+ GTimer *timer;
gint i = 0;
gint prev_height = -1;
return FALSE;
}
+ timer = g_timer_new ();
+ g_timer_start (timer);
+
do
{
if (! GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
i++;
}
- while (i < GTK_TREE_VIEW_NUM_ROWS_PER_IDLE);
+ while (g_timer_elapsed (timer, NULL) < GTK_TREE_VIEW_TIME_MS_PER_IDLE / 1000.);
if (!tree_view->priv->fixed_height_check)
{
gtk_adjustment_changed (tree_view->priv->vadjustment);
if (queue_resize)
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
+ gtk_widget_queue_resize (GTK_WIDGET (tree_view));
}
if (path) gtk_tree_path_free (path);
+ g_timer_destroy (timer);
return retval;
}
if (tree == NULL)
{
- tree_view->priv->top_row = NULL;
- tree_view->priv->top_row_dy = 0;
+ gtk_tree_view_set_top_row (tree_view, NULL, 0);
}
else
{
GtkRBNode *node;
int new_dy;
+ /* Avoid recursive calls */
+ if (tree_view->priv->in_top_row_to_dy)
+ return;
+
if (tree_view->priv->top_row)
path = gtk_tree_row_reference_get_path (tree_view->priv->top_row);
else
typedef struct
{
GtkTreeRowReference *dest_row;
- gboolean path_down_mode;
- gboolean empty_view_drop;
- gboolean drop_append_mode;
+ guint path_down_mode : 1;
+ guint empty_view_drop : 1;
+ guint drop_append_mode : 1;
}
DestRow;
DestRow *dr = (DestRow *)data;
gtk_tree_row_reference_free (dr->dest_row);
- g_free (dr);
+ g_slice_free (DestRow, dr);
}
-
static void
set_dest_row (GdkDragContext *context,
GtkTreeModel *model,
return;
}
- dr = g_new0 (DestRow, 1);
+ dr = g_slice_new (DestRow);
dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
- dr->path_down_mode = path_down_mode;
- dr->empty_view_drop = empty_view_drop;
- dr->drop_append_mode = drop_append_mode;
+ dr->path_down_mode = path_down_mode != FALSE;
+ dr->empty_view_drop = empty_view_drop != FALSE;
+ dr->drop_append_mode = drop_append_mode != FALSE;
g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
dr, (GDestroyNotify) dest_row_free);
return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
}
-static void
-clear_source_info (TreeViewDragInfo *di)
-{
- if (di->source_target_list)
- gtk_target_list_unref (di->source_target_list);
-
- di->source_target_list = NULL;
-}
-
-static void
-clear_dest_info (TreeViewDragInfo *di)
-{
- if (di->dest_target_list)
- gtk_target_list_unref (di->dest_target_list);
-
- di->dest_target_list = NULL;
-}
-
static void
destroy_info (TreeViewDragInfo *di)
{
- clear_source_info (di);
- clear_dest_info (di);
- g_free (di);
+ g_slice_free (TreeViewDragInfo, di);
}
static TreeViewDragInfo*
if (di == NULL)
{
- di = g_new0 (TreeViewDragInfo, 1);
+ di = g_slice_new0 (TreeViewDragInfo);
g_object_set_data_full (G_OBJECT (tree_view),
I_("gtk-tree-view-drag-info"),
return FALSE; /* no longer a drop site */
}
- *target = gtk_drag_dest_find_target (widget, context, di->dest_target_list);
+ *target = gtk_drag_dest_find_target (widget, context,
+ gtk_drag_dest_get_target_list (widget));
if (*target == GDK_NONE)
{
return FALSE;
gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view,
GdkEventMotion *event)
{
+ GtkWidget *widget = GTK_WIDGET (tree_view);
GdkDragContext *context;
TreeViewDragInfo *di;
GtkTreePath *path = NULL;
if (tree_view->priv->pressed_button < 0)
goto out;
- if (!gtk_drag_check_threshold (GTK_WIDGET (tree_view),
+ if (!gtk_drag_check_threshold (widget,
tree_view->priv->press_start_x,
tree_view->priv->press_start_y,
event->x, event->y))
retval = TRUE;
- context = gtk_drag_begin (GTK_WIDGET (tree_view),
- di->source_target_list,
+ context = gtk_drag_begin (widget,
+ gtk_drag_source_get_target_list (widget),
di->source_actions,
button,
(GdkEvent*)event);
gtk_tree_view_remove (GtkContainer *container,
GtkWidget *widget)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (container);
GtkTreeViewChild *child = NULL;
GList *tmp_list;
- g_return_if_fail (GTK_IS_TREE_VIEW (container));
-
- tree_view = GTK_TREE_VIEW (container);
-
tmp_list = tree_view->priv->children;
while (tmp_list)
{
tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
g_list_free_1 (tmp_list);
- g_free (child);
+ g_slice_free (GtkTreeViewChild, child);
return;
}
GtkCallback callback,
gpointer callback_data)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (container);
GtkTreeViewChild *child = NULL;
GtkTreeViewColumn *column;
GList *tmp_list;
- g_return_if_fail (GTK_IS_TREE_VIEW (container));
- g_return_if_fail (callback != NULL);
-
- tree_view = GTK_TREE_VIEW (container);
-
tmp_list = tree_view->priv->children;
while (tmp_list)
{
first_column = tree_view->priv->columns;
while (first_column)
{
- if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
+ if (gtk_widget_get_can_focus (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
GTK_TREE_VIEW_COLUMN (first_column->data)->visible &&
(GTK_TREE_VIEW_COLUMN (first_column->data)->clickable ||
GTK_TREE_VIEW_COLUMN (first_column->data)->reorderable))
last_column = g_list_last (tree_view->priv->columns);
while (last_column)
{
- if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
+ if (gtk_widget_get_can_focus (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
GTK_TREE_VIEW_COLUMN (last_column->data)->visible &&
(GTK_TREE_VIEW_COLUMN (last_column->data)->clickable ||
GTK_TREE_VIEW_COLUMN (last_column->data)->reorderable))
case GTK_DIR_DOWN:
if (focus_child == NULL)
{
- if (tree_view->priv->focus_column != NULL)
+ if (tree_view->priv->focus_column != NULL &&
+ gtk_widget_get_can_focus (tree_view->priv->focus_column->button))
focus_child = tree_view->priv->focus_column->button;
else
focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
column = tmp_list->data;
if (column->button &&
column->visible &&
- GTK_WIDGET_CAN_FOCUS (column->button))
+ gtk_widget_get_can_focus (column->button))
{
focus_child = column->button;
gtk_widget_grab_focus (column->button);
gtk_tree_view_focus (GtkWidget *widget,
GtkDirectionType direction)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
+ GtkContainer *container = GTK_CONTAINER (widget);
GtkWidget *focus_child;
- GtkContainer *container;
- g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
- g_return_val_if_fail (GTK_WIDGET_VISIBLE (widget), FALSE);
-
- container = GTK_CONTAINER (widget);
- tree_view = GTK_TREE_VIEW (widget);
-
- if (!GTK_WIDGET_IS_SENSITIVE (container))
+ if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_can_focus (widget))
return FALSE;
focus_child = container->focus_child;
}
/* Case 2. We don't have focus at all. */
- if (!GTK_WIDGET_HAS_FOCUS (container))
+ if (!gtk_widget_has_focus (widget))
{
if (!gtk_tree_view_header_focus (tree_view, direction, FALSE))
gtk_widget_grab_focus (widget);
static void
gtk_tree_view_grab_focus (GtkWidget *widget)
{
- (* GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->grab_focus) (widget);
+ GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->grab_focus (widget);
gtk_tree_view_focus_to_cursor (GTK_TREE_VIEW (widget));
}
gtk_tree_view_style_set (GtkWidget *widget,
GtkStyle *previous_style)
{
- GtkTreeView *tree_view;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GList *list;
GtkTreeViewColumn *column;
- g_return_if_fail (GTK_IS_TREE_VIEW (widget));
-
- tree_view = GTK_TREE_VIEW (widget);
-
if (GTK_WIDGET_REALIZED (widget))
{
gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
tree_view->priv->hadjustment = hadj;
g_object_ref_sink (tree_view->priv->hadjustment);
- g_signal_connect (tree_view->priv->hadjustment, "value_changed",
+ g_signal_connect (tree_view->priv->hadjustment, "value-changed",
G_CALLBACK (gtk_tree_view_adjustment_changed),
tree_view);
need_adjust = TRUE;
tree_view->priv->vadjustment = vadj;
g_object_ref_sink (tree_view->priv->vadjustment);
- g_signal_connect (tree_view->priv->vadjustment, "value_changed",
+ g_signal_connect (tree_view->priv->vadjustment, "value-changed",
G_CALLBACK (gtk_tree_view_adjustment_changed),
tree_view);
need_adjust = TRUE;
if (tree_view->priv->tree == NULL)
return FALSE;
- if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (tree_view)))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE;
gtk_tree_view_stop_editing (tree_view, FALSE);
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
g_return_if_fail (GTK_IS_WIDGET (child_widget));
- child = g_new (GtkTreeViewChild, 1);
+ child = g_slice_new (GtkTreeViewChild);
child->widget = child_widget;
child->x = x;
gtk_tree_view_stop_editing (tree_view, TRUE);
/* If we have a node expanded/collapsed timeout, remove it */
- if (tree_view->priv->expand_collapse_timeout != 0)
- {
- g_source_remove (tree_view->priv->expand_collapse_timeout);
- tree_view->priv->expand_collapse_timeout = 0;
-
- /* Reset node */
- GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
- GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
- tree_view->priv->expanded_collapsed_node = NULL;
- }
+ remove_expand_collapse_timeout (tree_view);
if (tree_view->priv->destroy_count_func)
{
gint child_count = 0;
if (node->children)
_gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
- (* tree_view->priv->destroy_count_func) (tree_view, path, child_count, tree_view->priv->destroy_count_data);
+ tree_view->priv->destroy_count_func (tree_view, path, child_count, tree_view->priv->destroy_count_data);
}
if (tree->root->count == 1)
g_signal_emit_by_name (tree_view->priv->selection, "changed");
}
-static void
-cancel_arrow_animation (GtkTreeView *tree_view)
-{
- if (tree_view->priv->expand_collapse_timeout)
- {
- while (do_expand_collapse (tree_view));
-
- g_source_remove (tree_view->priv->expand_collapse_timeout);
- tree_view->priv->expand_collapse_timeout = 0;
- }
-}
-
static void
gtk_tree_view_rows_reordered (GtkTreeModel *model,
GtkTreePath *parent,
gtk_tree_model_ref_node (tree_view->priv->model, iter);
temp = _gtk_rbtree_insert_after (tree, temp, 0, FALSE);
- if (tree_view->priv->fixed_height > 0)
- {
- if (GTK_RBNODE_FLAG_SET (temp, GTK_RBNODE_INVALID))
- {
- _gtk_rbtree_node_set_height (tree, temp, tree_view->priv->fixed_height);
- _gtk_rbtree_node_mark_valid (tree, temp);
- }
- }
-
- if (is_list)
- continue;
-
- if (recurse)
- {
- GtkTreeIter child;
-
- if (!path)
- path = gtk_tree_model_get_path (tree_view->priv->model, iter);
- else
- gtk_tree_path_next (path);
-
- if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
- {
- gboolean expand;
-
- g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, iter, path, &expand);
-
- if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter)
- && !expand)
- {
- 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);
- }
- }
- }
-
- if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
- {
- if ((temp->flags>K_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
- temp->flags ^= GTK_RBNODE_IS_PARENT;
- }
- }
- while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
-
- if (path)
- gtk_tree_path_free (path);
-}
-
-/* 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.
- */
-static gboolean
-gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
- GtkTreeIter *iter,
- gint depth,
- gint *height,
- GtkRBNode *node)
-{
- GtkTreeViewColumn *column;
- GList *list;
- gboolean retval = FALSE;
- gint tmpheight;
- gint horizontal_separator;
-
- gtk_widget_style_get (GTK_WIDGET (tree_view),
- "horizontal-separator", &horizontal_separator,
- NULL);
-
- if (height)
- *height = -1;
-
- for (list = tree_view->priv->columns; list; list = list->next)
- {
- gint width;
- column = list->data;
- if (column->dirty == TRUE)
- continue;
- if (height == NULL && column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
- continue;
- if (!column->visible)
- 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);
-
- if (height)
- {
- gtk_tree_view_column_cell_get_size (column,
- NULL, NULL, NULL,
- &width, &tmpheight);
- *height = MAX (*height, tmpheight);
- }
- else
- {
- gtk_tree_view_column_cell_get_size (column,
- NULL, NULL, NULL,
- &width, NULL);
- }
-
- if (gtk_tree_view_is_expander_column (tree_view, column))
- {
- int tmp = 0;
-
- tmp = horizontal_separator + width + (depth - 1) * tree_view->priv->level_indentation;
- if (TREE_VIEW_DRAW_EXPANDERS (tree_view))
- tmp += depth * tree_view->priv->expander_size;
-
- if (tmp > column->requested_width)
- {
- _gtk_tree_view_column_cell_set_dirty (column, TRUE);
- retval = TRUE;
- }
- }
- else
- {
- if (horizontal_separator + width > column->requested_width)
+ if (tree_view->priv->fixed_height > 0)
+ {
+ if (GTK_RBNODE_FLAG_SET (temp, GTK_RBNODE_INVALID))
{
- _gtk_tree_view_column_cell_set_dirty (column, TRUE);
- retval = TRUE;
+ _gtk_rbtree_node_set_height (tree, temp, tree_view->priv->fixed_height);
+ _gtk_rbtree_node_mark_valid (tree, temp);
}
- }
- }
-
- return retval;
-}
+ }
-static void
-gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
- GtkRBTree *tree,
- GtkTreeIter *iter,
- gint depth)
-{
- GtkRBNode *temp = tree->root;
- GtkTreeViewColumn *column;
- GList *list;
- GtkTreeIter child;
- gboolean is_all_dirty;
+ if (is_list)
+ continue;
- TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
+ if (recurse)
+ {
+ GtkTreeIter child;
- while (temp->left != tree->nil)
- temp = temp->left;
+ if (!path)
+ path = gtk_tree_model_get_path (tree_view->priv->model, iter);
+ else
+ gtk_tree_path_next (path);
- do
- {
- TREE_VIEW_INTERNAL_ASSERT_VOID (temp != NULL);
- is_all_dirty = TRUE;
- for (list = tree_view->priv->columns; list; list = list->next)
- {
- column = list->data;
- if (column->dirty == FALSE)
+ if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
{
- is_all_dirty = FALSE;
- break;
+ gboolean expand;
+
+ g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, iter, path, &expand);
+
+ if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter)
+ && !expand)
+ {
+ 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);
+ }
}
}
- if (is_all_dirty)
- return;
-
- gtk_tree_view_discover_dirty_iter (tree_view,
- iter,
- depth,
- NULL,
- temp);
- if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) &&
- temp->children != NULL)
- gtk_tree_view_discover_dirty (tree_view, temp->children, &child, depth + 1);
- temp = _gtk_rbtree_next (tree, temp);
+ if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
+ {
+ if ((temp->flags>K_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
+ temp->flags ^= GTK_RBNODE_IS_PARENT;
+ }
}
while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
-}
+ if (path)
+ gtk_tree_path_free (path);
+}
/* Make sure the node is visible vertically */
static void
{
gtk_binding_entry_add_signal (binding_set, keyval, modmask,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, step,
G_TYPE_INT, count);
if (add_shifted_binding)
gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, step,
G_TYPE_INT, count);
return;
gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, step,
G_TYPE_INT, count);
gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
- "move_cursor", 2,
+ "move-cursor", 2,
G_TYPE_ENUM, step,
G_TYPE_INT, count);
}
/* If it's not the column moving and func tells us to skip over the column, we continue. */
if (left_column != column && cur_column != column &&
tree_view->priv->column_drop_func &&
- ! (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
+ ! tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
{
left_column = cur_column;
continue;
}
- reorder = g_new (GtkTreeViewColumnReorder, 1);
+ reorder = g_slice_new0 (GtkTreeViewColumnReorder);
reorder->left_column = left_column;
left_column = reorder->right_column = cur_column;
/* Add the last one */
if (tree_view->priv->column_drop_func == NULL ||
((left_column != column) &&
- (* tree_view->priv->column_drop_func) (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data)))
+ tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data)))
{
- reorder = g_new (GtkTreeViewColumnReorder, 1);
+ reorder = g_slice_new0 (GtkTreeViewColumnReorder);
reorder->left_column = left_column;
reorder->right_column = NULL;
tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column))
{
for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
- g_free (tmp_list->data);
+ g_slice_free (GtkTreeViewColumnReorder, tmp_list->data);
g_list_free (tree_view->priv->column_drag_info);
tree_view->priv->column_drag_info = NULL;
return;
gboolean grab_focus = TRUE;
gboolean selectable;
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (! gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return;
cursor_path = NULL;
gint window_y;
gint vertical_separator;
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return;
if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
_gtk_rbtree_find_offset (tree_view->priv->tree, y,
&cursor_tree, &cursor_node);
- if (tree_view->priv->cursor_offset >= BACKGROUND_HEIGHT (cursor_node))
+ if (tree_view->priv->cursor_offset > BACKGROUND_HEIGHT (cursor_node))
{
_gtk_rbtree_next_full (cursor_tree, cursor_node,
&cursor_tree, &cursor_node);
if (!gtk_tree_path_compare (old_cursor_path, cursor_path))
gtk_widget_error_bell (GTK_WIDGET (tree_view));
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+
cleanup:
gtk_tree_path_free (old_cursor_path);
gtk_tree_path_free (cursor_path);
rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return;
if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
cursor_node,
NULL);
g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
}
else
{
GtkTreePath *path;
GtkTreePath *old_path;
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return;
g_return_if_fail (tree_view->priv->tree != NULL);
if (gtk_tree_path_compare (old_path, path))
{
gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
}
else
{
static gboolean
gtk_tree_view_real_select_all (GtkTreeView *tree_view)
{
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE;
if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
static gboolean
gtk_tree_view_real_unselect_all (GtkTreeView *tree_view)
{
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE;
if (tree_view->priv->selection->type != GTK_SELECTION_MULTIPLE)
gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view,
gboolean start_editing)
{
+ GtkRBTree *new_tree = NULL;
+ GtkRBNode *new_node = NULL;
GtkRBTree *cursor_tree = NULL;
GtkRBNode *cursor_node = NULL;
GtkTreePath *cursor_path = NULL;
GtkTreeSelectMode mode = 0;
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE;
if (tree_view->priv->cursor)
mode,
FALSE);
+ /* We bail out if the original (tree, node) don't exist anymore after
+ * handling the selection-changed callback. We do return TRUE because
+ * the key press has been handled at this point.
+ */
+ _gtk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node);
+
+ if (cursor_tree != new_tree || cursor_node != new_node)
+ return FALSE;
+
gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
static gboolean
gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
{
+ GtkRBTree *new_tree = NULL;
+ GtkRBNode *new_node = NULL;
GtkRBTree *cursor_tree = NULL;
GtkRBNode *cursor_node = NULL;
GtkTreePath *cursor_path = NULL;
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE;
cursor_path = NULL;
GTK_TREE_SELECT_MODE_TOGGLE,
FALSE);
+ /* We bail out if the original (tree, node) don't exist anymore after
+ * handling the selection-changed callback. We do return TRUE because
+ * the key press has been handled at this point.
+ */
+ _gtk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node);
+
+ if (cursor_tree != new_tree || cursor_node != new_node)
+ return FALSE;
+
gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
GtkRBTree *tree;
GtkRBNode *node;
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
return FALSE;
cursor_path = NULL;
GtkTreePath *cursor_path = NULL;
GdkModifierType state;
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
- return FALSE;
+ if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
+ goto out;
cursor_path = NULL;
if (tree_view->priv->cursor)
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
if (cursor_path == NULL)
- return FALSE;
+ goto out;
_gtk_tree_view_find_node (tree_view, cursor_path,
&cursor_tree, &cursor_node);
if (cursor_tree == NULL)
{
gtk_tree_path_free (cursor_path);
- return FALSE;
- }
-
- if (gtk_get_current_event_state (&state))
- {
- if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
- tree_view->priv->ctrl_pressed = TRUE;
+ goto out;
}
if (cursor_tree->parent_node)
gtk_tree_path_up (cursor_path);
+ if (gtk_get_current_event_state (&state))
+ {
+ if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+ tree_view->priv->ctrl_pressed = TRUE;
+ }
+
gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
- }
+ gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
- gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
+ gtk_widget_grab_focus (GTK_WIDGET (tree_view));
+ gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+ gtk_tree_path_free (cursor_path);
- gtk_widget_grab_focus (GTK_WIDGET (tree_view));
- gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
- gtk_tree_path_free (cursor_path);
+ tree_view->priv->ctrl_pressed = FALSE;
- tree_view->priv->ctrl_pressed = FALSE;
+ return TRUE;
+ }
- return TRUE;
+ out:
+
+ tree_view->priv->search_entry_avoid_unhandled_binding = TRUE;
+ return FALSE;
}
+
static gboolean
gtk_tree_view_search_entry_flush_timeout (GtkTreeView *tree_view)
{
gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
{
GtkWidget *frame, *vbox, *toplevel;
+ GdkScreen *screen;
if (tree_view->priv->search_custom_entry_set)
return;
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
+ screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
if (tree_view->priv->search_window != NULL)
{
else if (GTK_WINDOW (tree_view->priv->search_window)->group)
gtk_window_group_remove_window (GTK_WINDOW (tree_view->priv->search_window)->group,
GTK_WINDOW (tree_view->priv->search_window));
+ gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
return;
}
tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
if (GTK_WINDOW (toplevel)->group)
gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
GTK_WINDOW (tree_view->priv->search_window));
+ gtk_window_set_type_hint (GTK_WINDOW (tree_view->priv->search_window),
+ GDK_WINDOW_TYPE_HINT_UTILITY);
gtk_window_set_modal (GTK_WINDOW (tree_view->priv->search_window), TRUE);
- g_signal_connect (tree_view->priv->search_window, "delete_event",
+ g_signal_connect (tree_view->priv->search_window, "delete-event",
G_CALLBACK (gtk_tree_view_search_delete_event),
tree_view);
- g_signal_connect (tree_view->priv->search_window, "key_press_event",
+ g_signal_connect (tree_view->priv->search_window, "key-press-event",
G_CALLBACK (gtk_tree_view_search_key_press_event),
tree_view);
- g_signal_connect (tree_view->priv->search_window, "button_press_event",
+ g_signal_connect (tree_view->priv->search_window, "button-press-event",
G_CALLBACK (gtk_tree_view_search_button_press_event),
tree_view);
- g_signal_connect (tree_view->priv->search_window, "scroll_event",
+ g_signal_connect (tree_view->priv->search_window, "scroll-event",
G_CALLBACK (gtk_tree_view_search_scroll_event),
tree_view);
/* add entry */
tree_view->priv->search_entry = gtk_entry_new ();
gtk_widget_show (tree_view->priv->search_entry);
- g_signal_connect (tree_view->priv->search_entry, "populate_popup",
+ g_signal_connect (tree_view->priv->search_entry, "populate-popup",
G_CALLBACK (gtk_tree_view_search_disable_popdown),
tree_view);
g_signal_connect (tree_view->priv->search_entry,
"activate", G_CALLBACK (gtk_tree_view_search_activate),
tree_view);
g_signal_connect (GTK_ENTRY (tree_view->priv->search_entry)->im_context,
- "preedit_changed",
+ "preedit-changed",
G_CALLBACK (gtk_tree_view_search_preedit_changed),
tree_view);
gtk_container_add (GTK_CONTAINER (vbox),
return FALSE;
if (tree_view->priv->search_window != NULL &&
- GTK_WIDGET_VISIBLE (tree_view->priv->search_window))
+ gtk_widget_get_visible (tree_view->priv->search_window))
return TRUE;
for (list = tree_view->priv->columns; list; list = list->next)
if (! column->visible)
continue;
- if (GTK_WIDGET_HAS_FOCUS (column->button))
+ if (gtk_widget_has_focus (column->button))
{
found_focus = TRUE;
break;
}
}
- if (GTK_WIDGET_HAS_FOCUS (tree_view))
+ if (gtk_widget_has_focus (GTK_WIDGET (tree_view)))
found_focus = TRUE;
if (!found_focus)
/* The window to which widget->window is relative */
#define ALLOCATION_WINDOW(widget) \
- (GTK_WIDGET_NO_WINDOW (widget) ? \
+ (!gtk_widget_get_has_window (widget) ? \
(widget)->window : \
gdk_window_get_parent ((widget)->window))
*/
if (!GTK_WIDGET_REALIZED (widget))
{
- if (GTK_WIDGET_VISIBLE (widget))
+ if (gtk_widget_get_visible (widget))
{
GdkRectangle tmp_rectangle = widget->allocation;
tmp_rectangle.x += scroll_data->dx;
- tree_view->priv->hadjustment->value,
0);
dy = tree_view->priv->dy - (int) tree_view->priv->vadjustment->value;
- if (dy && tree_view->priv->edited_column)
+ if (dy)
{
- if (GTK_IS_WIDGET (tree_view->priv->edited_column->editable_widget))
+ update_prelight (tree_view,
+ tree_view->priv->event_last_x,
+ tree_view->priv->event_last_y - dy);
+
+ if (tree_view->priv->edited_column &&
+ GTK_IS_WIDGET (tree_view->priv->edited_column->editable_widget))
{
GList *list;
GtkWidget *widget;
if (!tree_view->priv->in_top_row_to_dy)
gtk_tree_view_dy_to_top_row (tree_view);
}
+
+ gdk_window_process_updates (tree_view->priv->header_window, TRUE);
+ gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
}
}
/**
* gtk_tree_view_set_model:
* @tree_view: A #GtkTreeNode.
- * @model: The model.
+ * @model: (allow-none): The model.
*
* Sets the model for a #GtkTreeView. If the @tree_view already has a model
- * set, it will remove it before setting the new model. If @model is %NULL,
+ * set, it will remove it before setting the new model. If @model is %NULL,
* then it will unset the old model.
**/
void
GtkTreeModel *model)
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
-
- if (model != NULL)
- g_return_if_fail (GTK_IS_TREE_MODEL (model));
+ g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
if (model == tree_view->priv->model)
return;
gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
gtk_tree_view_stop_editing (tree_view, TRUE);
- if (tree_view->priv->expand_collapse_timeout)
- {
- g_source_remove (tree_view->priv->expand_collapse_timeout);
- tree_view->priv->expand_collapse_timeout = 0;
- }
+ remove_expand_collapse_timeout (tree_view);
g_signal_handlers_disconnect_by_func (tree_view->priv->model,
gtk_tree_view_row_changed,
tree_view->priv->anchor = NULL;
gtk_tree_row_reference_free (tree_view->priv->top_row);
tree_view->priv->top_row = NULL;
- gtk_tree_row_reference_free (tree_view->priv->last_button_press);
- tree_view->priv->last_button_press = NULL;
- gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
- tree_view->priv->last_button_press_2 = NULL;
gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
tree_view->priv->scroll_to_path = NULL;
tree_view->priv->fixed_height_check = 0;
tree_view->priv->fixed_height = -1;
tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
+ tree_view->priv->last_button_x = -1;
+ tree_view->priv->last_button_y = -1;
}
tree_view->priv->model = model;
g_object_ref (tree_view->priv->model);
g_signal_connect (tree_view->priv->model,
- "row_changed",
+ "row-changed",
G_CALLBACK (gtk_tree_view_row_changed),
tree_view);
g_signal_connect (tree_view->priv->model,
- "row_inserted",
+ "row-inserted",
G_CALLBACK (gtk_tree_view_row_inserted),
tree_view);
g_signal_connect (tree_view->priv->model,
- "row_has_child_toggled",
+ "row-has-child-toggled",
G_CALLBACK (gtk_tree_view_row_has_child_toggled),
tree_view);
g_signal_connect (tree_view->priv->model,
- "row_deleted",
+ "row-deleted",
G_CALLBACK (gtk_tree_view_row_deleted),
tree_view);
g_signal_connect (tree_view->priv->model,
- "rows_reordered",
+ "rows-reordered",
G_CALLBACK (gtk_tree_view_rows_reordered),
tree_view);
/**
* gtk_tree_view_set_hadjustment:
* @tree_view: A #GtkTreeView
- * @adjustment: The #GtkAdjustment to set, or %NULL
+ * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
*
* Sets the #GtkAdjustment for the current horizontal aspect.
**/
/**
* gtk_tree_view_set_vadjustment:
* @tree_view: A #GtkTreeView
- * @adjustment: The #GtkAdjustment to set, or %NULL
+ * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
*
* Sets the #GtkAdjustment for the current vertical aspect.
**/
{
gdk_window_move_resize (tree_view->priv->bin_window, x, y + TREE_VIEW_HEADER_HEIGHT (tree_view), tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.height - + TREE_VIEW_HEADER_HEIGHT (tree_view));
- if (GTK_WIDGET_MAPPED (tree_view))
+ if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
gtk_tree_view_map_buttons (tree_view);
}
else
tree_view->priv->edited_column = NULL;
}
+ if (tree_view->priv->expander_column == column)
+ tree_view->priv->expander_column = NULL;
+
g_signal_handlers_disconnect_by_func (column,
G_CALLBACK (column_sizing_notify),
tree_view);
* Returns a #GList of all the #GtkTreeViewColumn s currently in @tree_view.
* The returned list must be freed with g_list_free ().
*
- * Return value: A list of #GtkTreeViewColumn s
+ * Return value: (element-type GtkTreeViewColumn) (transfer container): A list of #GtkTreeViewColumn s
**/
GList *
gtk_tree_view_get_columns (GtkTreeView *tree_view)
* gtk_tree_view_move_column_after:
* @tree_view: A #GtkTreeView
* @column: The #GtkTreeViewColumn to be moved.
- * @base_column: The #GtkTreeViewColumn to be moved relative to, or %NULL.
+ * @base_column: (allow-none): The #GtkTreeViewColumn to be moved relative to, or %NULL.
*
* Moves @column to be after to @base_column. If @base_column is %NULL, then
* @column is placed in the first position.
if (GTK_WIDGET_REALIZED (tree_view))
{
gtk_widget_queue_resize (GTK_WIDGET (tree_view));
- gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view));
+ gtk_tree_view_size_allocate_columns (GTK_WIDGET (tree_view), NULL);
}
g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
GtkTreeViewColumn *column)
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
- if (column != NULL)
- g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
+ g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
if (tree_view->priv->expander_column != column)
{
/**
* gtk_tree_view_set_column_drag_function:
* @tree_view: A #GtkTreeView.
- * @func: A function to determine which columns are reorderable, or %NULL.
- * @user_data: User data to be passed to @func, or %NULL
- * @destroy: Destroy notifier for @user_data, or %NULL
+ * @func: (allow-none): A function to determine which columns are reorderable, or %NULL.
+ * @user_data: (allow-none): User data to be passed to @func, or %NULL
+ * @destroy: (allow-none): Destroy notifier for @user_data, or %NULL
*
* Sets a user function for determining where a column may be dropped when
* dragged. This function is called on every column pair in turn at the
gtk_tree_view_set_column_drag_function (GtkTreeView *tree_view,
GtkTreeViewColumnDropFunc func,
gpointer user_data,
- GtkDestroyNotify destroy)
+ GDestroyNotify destroy)
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
if (tree_view->priv->column_drop_func_data_destroy)
- (* tree_view->priv->column_drop_func_data_destroy) (tree_view->priv->column_drop_func_data);
+ tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
tree_view->priv->column_drop_func = func;
tree_view->priv->column_drop_func_data = user_data;
/**
* gtk_tree_view_scroll_to_cell:
* @tree_view: A #GtkTreeView.
- * @path: The path of the row to move to, or %NULL.
- * @column: The #GtkTreeViewColumn to move horizontally to, or %NULL.
+ * @path: (allow-none): The path of the row to move to, or %NULL.
+ * @column: (allow-none): The #GtkTreeViewColumn to move horizontally to, or %NULL.
* @use_align: whether to use alignment arguments, or %FALSE.
* @row_align: The vertical alignment of the row specified by @path.
* @col_align: The horizontal alignment of the column specified by @column.
* scrolling code, we short-circuit validate_visible_area's immplementation as
* it is much slower than just going to the point.
*/
- if (! GTK_WIDGET_VISIBLE (tree_view) ||
+ if (! gtk_widget_get_visible (GTK_WIDGET (tree_view)) ||
! GTK_WIDGET_REALIZED (tree_view) ||
GTK_WIDGET_ALLOC_NEEDED (tree_view) ||
GTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, GTK_RBNODE_DESCENDANTS_INVALID))
gtk_tree_view_expand_all_emission_helper,
tree_view);
}
+
/**
* gtk_tree_view_expand_all:
* @tree_view: A #GtkTreeView.
return do_expand_collapse (data);
}
+static void
+add_expand_collapse_timeout (GtkTreeView *tree_view,
+ GtkRBTree *tree,
+ GtkRBNode *node,
+ gboolean expand)
+{
+ if (tree_view->priv->expand_collapse_timeout != 0)
+ return;
+
+ tree_view->priv->expand_collapse_timeout =
+ gdk_threads_add_timeout (50, expand_collapse_timeout, tree_view);
+ tree_view->priv->expanded_collapsed_tree = tree;
+ tree_view->priv->expanded_collapsed_node = node;
+
+ if (expand)
+ GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
+ else
+ GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
+}
+
+static void
+remove_expand_collapse_timeout (GtkTreeView *tree_view)
+{
+ if (tree_view->priv->expand_collapse_timeout)
+ {
+ g_source_remove (tree_view->priv->expand_collapse_timeout);
+ tree_view->priv->expand_collapse_timeout = 0;
+ }
+
+ if (tree_view->priv->expanded_collapsed_node != NULL)
+ {
+ GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
+ GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
+
+ tree_view->priv->expanded_collapsed_node = NULL;
+ }
+}
+
+static void
+cancel_arrow_animation (GtkTreeView *tree_view)
+{
+ if (tree_view->priv->expand_collapse_timeout)
+ {
+ while (do_expand_collapse (tree_view));
+
+ remove_expand_collapse_timeout (tree_view);
+ }
+}
+
static gboolean
do_expand_collapse (GtkTreeView *tree_view)
{
gtk_tree_path_get_depth (path) + 1,
open_all);
- if (tree_view->priv->expand_collapse_timeout)
- {
- g_source_remove (tree_view->priv->expand_collapse_timeout);
- tree_view->priv->expand_collapse_timeout = 0;
- }
-
- if (tree_view->priv->expanded_collapsed_node != NULL)
- {
- GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
- GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
-
- tree_view->priv->expanded_collapsed_node = NULL;
- }
+ remove_expand_collapse_timeout (tree_view);
if (animate)
- {
- tree_view->priv->expand_collapse_timeout = gdk_threads_add_timeout (50, expand_collapse_timeout, tree_view);
- tree_view->priv->expanded_collapsed_node = node;
- tree_view->priv->expanded_collapsed_tree = tree;
-
- GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
- }
+ add_expand_collapse_timeout (tree_view, tree, node, TRUE);
install_presize_handler (tree_view);
gtk_tree_path_down (child_path);
if (node->children)
_gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
- (* tree_view->priv->destroy_count_func) (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
+ tree_view->priv->destroy_count_func (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
gtk_tree_path_free (child_path);
}
gtk_tree_path_free (anchor_path);
}
- if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press))
- {
- GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press);
- if (gtk_tree_path_is_ancestor (path, lsc))
- {
- gtk_tree_row_reference_free (tree_view->priv->last_button_press);
- tree_view->priv->last_button_press = NULL;
- }
- gtk_tree_path_free (lsc);
- }
-
- if (gtk_tree_row_reference_valid (tree_view->priv->last_button_press_2))
- {
- GtkTreePath *lsc = gtk_tree_row_reference_get_path (tree_view->priv->last_button_press_2);
- if (gtk_tree_path_is_ancestor (path, lsc))
- {
- gtk_tree_row_reference_free (tree_view->priv->last_button_press_2);
- tree_view->priv->last_button_press_2 = NULL;
- }
- gtk_tree_path_free (lsc);
- }
+ /* Stop a pending double click */
+ tree_view->priv->last_button_x = -1;
+ tree_view->priv->last_button_y = -1;
- if (tree_view->priv->expanded_collapsed_node != NULL)
- {
- GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_EXPANDED);
- GTK_RBNODE_UNSET_FLAG (tree_view->priv->expanded_collapsed_node, GTK_RBNODE_IS_SEMI_COLLAPSED);
-
- tree_view->priv->expanded_collapsed_node = NULL;
- }
+ remove_expand_collapse_timeout (tree_view);
if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
{
}
else
_gtk_rbtree_remove (node->children);
-
- if (tree_view->priv->expand_collapse_timeout)
- {
- g_source_remove (tree_view->priv->expand_collapse_timeout);
- tree_view->priv->expand_collapse_timeout = 0;
- }
if (animate)
- {
- tree_view->priv->expand_collapse_timeout = gdk_threads_add_timeout (50, expand_collapse_timeout, tree_view);
- tree_view->priv->expanded_collapsed_node = node;
- tree_view->priv->expanded_collapsed_tree = tree;
-
- GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_EXPANDED);
- }
+ add_expand_collapse_timeout (tree_view, tree, node, FALSE);
- if (GTK_WIDGET_MAPPED (tree_view))
+ if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
{
gtk_widget_queue_resize (GTK_WIDGET (tree_view));
}
g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
- if (GTK_WIDGET_MAPPED (tree_view))
+ if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
{
/* now that we've collapsed all rows, we want to try to set the prelight
* again. To do this, we fake a motion event and send it to ourselves. */
return (node->children != NULL);
}
-static const GtkTargetEntry row_targets[] = {
- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
-};
-
-
/**
* gtk_tree_view_get_reorderable:
* @tree_view: a #GtkTreeView
* @tree_view: A #GtkTreeView.
* @reorderable: %TRUE, if the tree can be reordered.
*
- * This function is a convenience function to allow you to reorder models that
- * support the #GtkDragSourceIface and the #GtkDragDestIface. Both
- * #GtkTreeStore and #GtkListStore support these. If @reorderable is %TRUE, then
- * the user can reorder the model by dragging and dropping rows. The
- * developer can listen to these changes by connecting to the model's
- * row_inserted and row_deleted signals.
+ * This function is a convenience function to allow you to reorder
+ * models that support the #GtkDragSourceIface and the
+ * #GtkDragDestIface. Both #GtkTreeStore and #GtkListStore support
+ * these. If @reorderable is %TRUE, then the user can reorder the
+ * model by dragging and dropping rows. The developer can listen to
+ * these changes by connecting to the model's row_inserted and
+ * row_deleted signals. The reordering is implemented by setting up
+ * the tree view as a drag source and destination. Therefore, drag and
+ * drop can not be used in a reorderable view for any other purpose.
*
* This function does not give you any degree of control over the order -- any
* reordering is allowed. If more control is needed, you should probably
if (reorderable)
{
+ const GtkTargetEntry row_targets[] = {
+ { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
+ };
+
gtk_tree_view_enable_model_drag_source (tree_view,
GDK_BUTTON1_MASK,
row_targets,
gtk_tree_row_reference_free (tree_view->priv->cursor);
tree_view->priv->cursor = NULL;
- /* One cannot set the cursor on a separator. */
- if (!row_is_separator (tree_view, NULL, path))
+ /* One cannot set the cursor on a separator. Also, if
+ * _gtk_tree_view_find_node returns TRUE, it ran out of tree
+ * before finding the tree and node belonging to path. The
+ * path maps to a non-existing path and we will silently bail out.
+ * We unset tree and node to avoid further processing.
+ */
+ if (!row_is_separator (tree_view, NULL, path)
+ && _gtk_tree_view_find_node (tree_view, path, &tree, &node) == FALSE)
{
tree_view->priv->cursor =
- gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
- tree_view->priv->model,
- path);
- _gtk_tree_view_find_node (tree_view, path, &tree, &node);
+ gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
+ tree_view->priv->model,
+ path);
+ }
+ else
+ {
+ tree = NULL;
+ node = NULL;
}
if (tree != NULL)
/**
* gtk_tree_view_get_cursor:
* @tree_view: A #GtkTreeView
- * @path: A pointer to be filled with the current cursor path, or %NULL
- * @focus_column: A pointer to be filled with the current focus column, or %NULL
+ * @path: (allow-none): A pointer to be filled with the current cursor path, or %NULL
+ * @focus_column: (allow-none): A pointer to be filled with the current focus column, or %NULL
*
* Fills in @path and @focus_column with the current path and focus column. If
* the cursor isn't currently set, then *@path will be %NULL. If no column
* gtk_tree_view_set_cursor:
* @tree_view: A #GtkTreeView
* @path: A #GtkTreePath
- * @focus_column: A #GtkTreeViewColumn, or %NULL
+ * @focus_column: (allow-none): A #GtkTreeViewColumn, or %NULL
* @start_editing: %TRUE if the specified cell should start being edited.
*
* Sets the current keyboard focus to be at @path, and selects it. This is
* This function is often followed by @gtk_widget_grab_focus (@tree_view)
* in order to give keyboard focus to the widget. Please note that editing
* can only happen when the widget is realized.
+ *
+ * If @path is invalid for @model, the current cursor (if any) will be unset
+ * and the function will return without failing.
**/
void
gtk_tree_view_set_cursor (GtkTreeView *tree_view,
* gtk_tree_view_set_cursor_on_cell:
* @tree_view: A #GtkTreeView
* @path: A #GtkTreePath
- * @focus_column: A #GtkTreeViewColumn, or %NULL
- * @focus_cell: A #GtkCellRenderer, or %NULL
+ * @focus_column: (allow-none): A #GtkTreeViewColumn, or %NULL
+ * @focus_cell: (allow-none): A #GtkCellRenderer, or %NULL
* @start_editing: %TRUE if the specified cell should start being edited.
*
* Sets the current keyboard focus to be at @path, and selects it. This is
* widget. Please note that editing can only happen when the widget is
* realized.
*
+ * If @path is invalid for @model, the current cursor (if any) will be unset
+ * and the function will return without failing.
+ *
* Since: 2.2
**/
void
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
g_return_if_fail (path != NULL);
- if (focus_column)
- g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
+ g_return_if_fail (focus_column == NULL || GTK_IS_TREE_VIEW_COLUMN (focus_column));
+
+ if (!tree_view->priv->model)
+ return;
+
if (focus_cell)
{
g_return_if_fail (focus_column);
* @tree_view: A #GtkTreeView.
* @x: The x position to be identified (relative to bin_window).
* @y: The y position to be identified (relative to bin_window).
- * @path: A pointer to a #GtkTreePath pointer to be filled in, or %NULL
- * @column: A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
- * @cell_x: A pointer where the X coordinate relative to the cell can be placed, or %NULL
- * @cell_y: A pointer where the Y coordinate relative to the cell can be placed, or %NULL
+ * @path: (out) (allow-none): A pointer to a #GtkTreePath pointer to be filled in, or %NULL
+ * @column: (out) (allow-none): A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
+ * @cell_x: (out) (allow-none): A pointer where the X coordinate relative to the cell can be placed, or %NULL
+ * @cell_y: (out) (allow-none): A pointer where the Y coordinate relative to the cell can be placed, or %NULL
*
* Finds the path at the point (@x, @y), relative to bin_window coordinates
* (please see gtk_tree_view_get_bin_window()).
* with the column at that point. @cell_x and @cell_y return the coordinates
* relative to the cell background (i.e. the @background_area passed to
* gtk_cell_renderer_render()). This function is only meaningful if
- * @tree_view is realized.
+ * @tree_view is realized. Therefore this function will always return %FALSE
+ * if @tree_view is not realized or does not have a model.
*
* For converting widget coordinates (eg. the ones you get from
* GtkWidget::query-tooltip), please see
gint y_offset;
g_return_val_if_fail (tree_view != NULL, FALSE);
- g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
if (path)
*path = NULL;
if (column)
*column = NULL;
+ if (tree_view->priv->bin_window == NULL)
+ return FALSE;
+
if (tree_view->priv->tree == NULL)
return FALSE;
/**
* gtk_tree_view_get_cell_area:
* @tree_view: a #GtkTreeView
- * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
- * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordinates
+ * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
+ * @column: (allow-none): a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordinates
* @rect: rectangle to fill with cell rect
*
* Fills the bounding rectangle in bin_window coordinates for the cell at the
/**
* gtk_tree_view_get_background_area:
* @tree_view: a #GtkTreeView
- * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
- * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
+ * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
+ * @column: (allow-none): a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
* @rect: rectangle to fill with cell background rect
*
* Fills the bounding rectangle in bin_window coordinates for the cell at the
/**
* gtk_tree_view_get_visible_range:
* @tree_view: A #GtkTreeView
- * @start_path: Return location for start of region, or %NULL.
- * @end_path: Return location for end of region, or %NULL.
+ * @start_path: (allow-none): Return location for start of region, or %NULL.
+ * @end_path: (allow-none): Return location for end of region, or %NULL.
*
* Sets @start_path and @end_path to be the first and last visible path.
* Note that there may be invisible paths in between.
{
GtkRBTree *tree;
GtkRBNode *node;
-
+ gboolean retval;
+
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
if (!tree_view->priv->tree)
return FALSE;
+ retval = TRUE;
+
if (start_path)
{
_gtk_rbtree_find_offset (tree_view->priv->tree,
TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
&tree, &node);
- *start_path = _gtk_tree_view_find_path (tree_view, tree, node);
+ if (node)
+ *start_path = _gtk_tree_view_find_path (tree_view, tree, node);
+ else
+ retval = FALSE;
}
if (end_path)
y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, tree_view->priv->vadjustment->page_size) - 1;
_gtk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node);
- *end_path = _gtk_tree_view_find_path (tree_view, tree, node);
+ if (node)
+ *end_path = _gtk_tree_view_find_path (tree_view, tree, node);
+ else
+ retval = FALSE;
}
- return TRUE;
+ return retval;
}
static void
* @n_targets: the number of items in @targets
* @actions: the bitmask of possible actions for a drag from this
* widget
- *
- * Turns @tree_view into a drag source for automatic DND.
+ *
+ * Turns @tree_view into a drag source for automatic DND. Calling this
+ * method sets #GtkTreeView:reorderable to %FALSE.
**/
void
gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view,
actions);
di = ensure_info (tree_view);
- clear_source_info (di);
di->start_button_mask = start_button_mask;
- di->source_target_list = gtk_target_list_new (targets, n_targets);
di->source_actions = actions;
-
di->source_set = TRUE;
unset_reorderable (tree_view);
* @actions: the bitmask of possible actions for a drag from this
* widget
*
- * Turns @tree_view into a drop destination for automatic DND.
+ * Turns @tree_view into a drop destination for automatic DND. Calling
+ * this method sets #GtkTreeView:reorderable to %FALSE.
**/
void
gtk_tree_view_enable_model_drag_dest (GtkTreeView *tree_view,
actions);
di = ensure_info (tree_view);
- clear_dest_info (di);
-
- if (targets)
- di->dest_target_list = gtk_target_list_new (targets, n_targets);
-
di->dest_set = TRUE;
unset_reorderable (tree_view);
/**
* gtk_tree_view_unset_rows_drag_source:
* @tree_view: a #GtkTreeView
- *
- * Undoes the effect of gtk_tree_view_enable_model_drag_source().
+ *
+ * Undoes the effect of
+ * gtk_tree_view_enable_model_drag_source(). Calling this method sets
+ * #GtkTreeView:reorderable to %FALSE.
**/
void
gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
if (di->source_set)
{
gtk_drag_source_unset (GTK_WIDGET (tree_view));
- clear_source_info (di);
di->source_set = FALSE;
}
/**
* gtk_tree_view_unset_rows_drag_dest:
* @tree_view: a #GtkTreeView
- *
- * Undoes the effect of gtk_tree_view_enable_model_drag_dest().
+ *
+ * Undoes the effect of
+ * gtk_tree_view_enable_model_drag_dest(). Calling this method sets
+ * #GtkTreeView:reorderable to %FALSE.
**/
void
gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
if (di->dest_set)
{
gtk_drag_dest_unset (GTK_WIDGET (tree_view));
- clear_dest_info (di);
di->dest_set = FALSE;
}
/**
* gtk_tree_view_set_drag_dest_row:
* @tree_view: a #GtkTreeView
- * @path: The path of the row to highlight, or %NULL.
+ * @path: (allow-none): The path of the row to highlight, or %NULL.
* @pos: Specifies whether to drop before, after or into the row
*
* Sets the row that is highlighted for feedback.
/**
* gtk_tree_view_get_drag_dest_row:
* @tree_view: a #GtkTreeView
- * @path: Return location for the path of the highlighted row, or %NULL.
- * @pos: Return location for the drop position, or %NULL
+ * @path: (allow-none): Return location for the path of the highlighted row, or %NULL.
+ * @pos: (allow-none): Return location for the drop position, or %NULL
*
* Gets information about the row that is highlighted for feedback.
**/
* @tree_view: a #GtkTreeView
* @drag_x: the position to determine the destination row for
* @drag_y: the position to determine the destination row for
- * @path: Return location for the path of the highlighted row, or %NULL.
- * @pos: Return location for the drop position, or %NULL
+ * @path: (allow-none): Return location for the path of the highlighted row, or %NULL.
+ * @pos: (allow-none): Return location for the drop position, or %NULL
*
* Determines the destination row for a given position. @drag_x and
- * @drag_y are expected to be in widget coordinates.
+ * @drag_y are expected to be in widget coordinates. This function is only
+ * meaningful if @tree_view is realized. Therefore this function will always
+ * return %FALSE if @tree_view is not realized or does not have a model.
*
- * Return value: whether there is a row at the given position.
+ * Return value: whether there is a row at the given position, %TRUE if this
+ * is indeed the case.
**/
gboolean
gtk_tree_view_get_dest_row_at_pos (GtkTreeView *tree_view,
g_return_val_if_fail (tree_view != NULL, FALSE);
g_return_val_if_fail (drag_x >= 0, FALSE);
g_return_val_if_fail (drag_y >= 0, FALSE);
- g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
-
if (path)
*path = NULL;
+ if (tree_view->priv->bin_window == NULL)
+ return FALSE;
+
if (tree_view->priv->tree == NULL)
return FALSE;
/**
* gtk_tree_view_set_destroy_count_func:
* @tree_view: A #GtkTreeView
- * @func: Function to be called when a view row is destroyed, or %NULL
- * @data: User data to be passed to @func, or %NULL
- * @destroy: Destroy notifier for @data, or %NULL
+ * @func: (allow-none): Function to be called when a view row is destroyed, or %NULL
+ * @data: (allow-none): User data to be passed to @func, or %NULL
+ * @destroy: (allow-none): Destroy notifier for @data, or %NULL
*
* This function should almost never be used. It is meant for private use by
* ATK for determining the number of visible children that are removed when the
gtk_tree_view_set_destroy_count_func (GtkTreeView *tree_view,
GtkTreeDestroyCountFunc func,
gpointer data,
- GtkDestroyNotify destroy)
+ GDestroyNotify destroy)
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
if (tree_view->priv->destroy_count_destroy)
- (* tree_view->priv->destroy_count_destroy) (tree_view->priv->destroy_count_data);
+ tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
tree_view->priv->destroy_count_func = func;
tree_view->priv->destroy_count_data = data;
* @column: the column of the model to search in, or -1 to disable searching
*
* Sets @column as the column where the interactive search code should
- * search in.
+ * search in for the current model.
*
- * If the sort column is set, users can use the "start-interactive-search"
+ * If the search column is set, users can use the "start-interactive-search"
* key binding to bring up search popup. The enable-search property controls
* whether simply typing text will also start an interactive search.
*
- * Note that @column refers to a column of the model.
+ * Note that @column refers to a column of the current model. The search
+ * column is reset to -1 when the model is changed.
*/
void
gtk_tree_view_set_search_column (GtkTreeView *tree_view,
* gtk_tree_view_set_search_equal_func:
* @tree_view: A #GtkTreeView
* @search_equal_func: the compare function to use during the search
- * @search_user_data: user data to pass to @search_equal_func, or %NULL
- * @search_destroy: Destroy notifier for @search_user_data, or %NULL
+ * @search_user_data: (allow-none): user data to pass to @search_equal_func, or %NULL
+ * @search_destroy: (allow-none): Destroy notifier for @search_user_data, or %NULL
*
* Sets the compare function for the interactive search capabilities; note
* that somewhat like strcmp() returning 0 for equality
gtk_tree_view_set_search_equal_func (GtkTreeView *tree_view,
GtkTreeViewSearchEqualFunc search_equal_func,
gpointer search_user_data,
- GtkDestroyNotify search_destroy)
+ GDestroyNotify search_destroy)
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
g_return_if_fail (search_equal_func != NULL);
if (tree_view->priv->search_destroy)
- (* tree_view->priv->search_destroy) (tree_view->priv->search_user_data);
+ tree_view->priv->search_destroy (tree_view->priv->search_user_data);
tree_view->priv->search_equal_func = search_equal_func;
tree_view->priv->search_user_data = search_user_data;
* gtk_tree_view_get_search_entry:
* @tree_view: A #GtkTreeView
*
- * Returns the GtkEntry which is currently in use as interactive search
+ * Returns the #GtkEntry which is currently in use as interactive search
* entry for @tree_view. In case the built-in entry is being used, %NULL
* will be returned.
*
/**
* gtk_tree_view_set_search_entry:
* @tree_view: A #GtkTreeView
- * @entry: the entry the interactive search code of @tree_view should use or %NULL
+ * @entry: (allow-none): the entry the interactive search code of @tree_view should use or %NULL
*
* Sets the entry which the interactive search code will use for this
* @tree_view. This is useful when you want to provide a search entry
GtkEntry *entry)
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
- if (entry != NULL)
- g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (entry == NULL || GTK_IS_ENTRY (entry));
if (tree_view->priv->search_custom_entry_set)
{
tree_view);
}
- g_signal_connect (tree_view->priv->search_entry, "key_press_event",
+ g_signal_connect (tree_view->priv->search_entry, "key-press-event",
G_CALLBACK (gtk_tree_view_search_key_press_event),
tree_view);
/**
* gtk_tree_view_set_search_position_func:
* @tree_view: A #GtkTreeView
- * @func: the function to use to position the search dialog, or %NULL
+ * @func: (allow-none): the function to use to position the search dialog, or %NULL
* to use the default search position function
- * @data: user data to pass to @func, or %NULL
- * @destroy: Destroy notifier for @data, or %NULL
+ * @data: (allow-none): user data to pass to @func, or %NULL
+ * @destroy: (allow-none): Destroy notifier for @data, or %NULL
*
- * Sets the function to use when positioning the seach dialog.
+ * Sets the function to use when positioning the search dialog.
*
* Since: 2.10
**/
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
if (tree_view->priv->search_position_destroy)
- (* tree_view->priv->search_position_destroy) (tree_view->priv->search_position_user_data);
+ tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
tree_view->priv->search_position_func = func;
tree_view->priv->search_position_user_data = user_data;
tree_view->priv->typeselect_flush_timeout = 0;
}
- if (GTK_WIDGET_VISIBLE (search_dialog))
+ if (gtk_widget_get_visible (search_dialog))
{
/* send focus-in event */
send_focus_change (GTK_WIDGET (tree_view->priv->search_entry), FALSE);
retval = TRUE;
}
- if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
+ if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK))
&& (event->keyval == GDK_g || event->keyval == GDK_G))
{
if (!gtk_tree_view_search_move (widget, tree_view, TRUE))
retval = TRUE;
}
- if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
+ if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == GTK_DEFAULT_ACCEL_MOD_MASK)
&& (event->keyval == GDK_g || event->keyval == GDK_G))
{
if (!gtk_tree_view_search_move (widget, tree_view, FALSE))
{
gtk_tree_view_scroll_to_cell (tree_view, path, NULL,
TRUE, 0.5, 0.0);
- gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
gtk_tree_selection_select_iter (selection, iter);
+ gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
if (path)
gtk_tree_path_free (path);
GtkTreeView *tree_view)
{
gint ret;
- gint len;
gint count = 0;
const gchar *text;
GtkTreeIter iter;
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
text = gtk_entry_get_text (GTK_ENTRY (entry));
- len = strlen (text);
+
model = gtk_tree_view_get_model (tree_view);
selection = gtk_tree_view_get_selection (tree_view);
tree_view);
}
- if (len < 1)
+ if (*text == '\0')
return;
if (!gtk_tree_model_get_iter_first (model, &iter))
_gtk_tree_view_column_stop_editing (tree_view->priv->edited_column);
tree_view->priv->edited_column = NULL;
- if (GTK_WIDGET_HAS_FOCUS (cell_editable))
+ if (gtk_widget_has_focus (GTK_WIDGET (cell_editable)))
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
g_signal_handlers_disconnect_by_func (cell_editable,
(GdkEvent *)event);
gtk_widget_grab_focus (GTK_WIDGET (cell_editable));
- g_signal_connect (cell_editable, "remove_widget",
+ g_signal_connect (cell_editable, "remove-widget",
G_CALLBACK (gtk_tree_view_remove_widget), tree_view);
}
* @expand: %TRUE to enable hover selection mode
*
* Enables of disables the hover expansion mode of @tree_view.
- * Hover expansion makes rows expand or collaps if the pointer
+ * Hover expansion makes rows expand or collapse if the pointer
* moves over them.
*
* Since: 2.6
* gtk_tree_view_set_row_separator_func:
* @tree_view: a #GtkTreeView
* @func: a #GtkTreeViewRowSeparatorFunc
- * @data: user data to pass to @func, or %NULL
- * @destroy: destroy notifier for @data, or %NULL
+ * @data: (allow-none): user data to pass to @func, or %NULL
+ * @destroy: (allow-none): destroy notifier for @data, or %NULL
*
* Sets the row separator function, which is used to determine
* whether a row should be drawn as a separator. If the row separator
* Since: 2.6
**/
void
-gtk_tree_view_set_row_separator_func (GtkTreeView *tree_view,
- GtkTreeViewRowSeparatorFunc func,
- gpointer data,
- GtkDestroyNotify destroy)
+gtk_tree_view_set_row_separator_func (GtkTreeView *tree_view,
+ GtkTreeViewRowSeparatorFunc func,
+ gpointer data,
+ GDestroyNotify destroy)
{
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
if (tree_view->priv->row_separator_destroy)
- (* tree_view->priv->row_separator_destroy) (tree_view->priv->row_separator_data);
+ tree_view->priv->row_separator_destroy (tree_view->priv->row_separator_data);
tree_view->priv->row_separator_func = func;
tree_view->priv->row_separator_data = data;
tree_view->priv->row_separator_destroy = destroy;
+
+ /* Have the tree recalculate heights */
+ _gtk_rbtree_mark_invalid (tree_view->priv->tree);
+ gtk_widget_queue_resize (GTK_WIDGET (tree_view));
}
!priv->grid_line_gc)
{
gint line_width;
- guint8 *dash_list;
+ gint8 *dash_list;
gtk_widget_style_get (widget,
"grid-line-width", &line_width,
if (enabled && !priv->tree_line_gc)
{
gint line_width;
- guint8 *dash_list;
+ gint8 *dash_list;
gtk_widget_style_get (widget,
"tree-line-width", &line_width,
"tree-line-pattern", (gchar *)&dash_list,
* @path: a #GtkTreePath
*
* Sets the tip area of @tooltip to be the area covered by the row at @path.
+ * See also gtk_tree_view_set_tooltip_column() for a simpler alternative.
* See also gtk_tooltip_set_tip_area().
*
* Since: 2.12
* gtk_tree_view_set_tooltip_cell:
* @tree_view: a #GtkTreeView
* @tooltip: a #GtkTooltip
- * @path: a #GtkTreePath or %NULL
- * @column: a #GtkTreeViewColumn or %NULL
- * @cell: a #GtkCellRenderer or %NULL
+ * @path: (allow-none): a #GtkTreePath or %NULL
+ * @column: (allow-none): a #GtkTreeViewColumn or %NULL
+ * @cell: (allow-none): a #GtkCellRenderer or %NULL
*
* Sets the tip area of @tooltip to the area @path, @column and @cell have
* in common. For example if @path is %NULL and @column is set, the tip
* position. In such cases @path must be set to the current node under the
* mouse cursor for this function to operate correctly.
*
+ * See also gtk_tree_view_set_tooltip_column() for a simpler alternative.
+ *
* Since: 2.12
*/
void
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
-
- if (column)
- g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
-
- if (cell)
- g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
+ g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
+ g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
/* Determine x values. */
if (column && cell)
* @x: the x coordinate (relative to widget coordinates)
* @y: the y coordinate (relative to widget coordinates)
* @keyboard_tip: whether this is a keyboard tooltip or not
- * @model: a pointer to receive a #GtkTreeModel or %NULL
- * @path: a pointer to receive a #GtkTreePath or %NULL
- * @iter: a pointer to receive a #GtkTreeIter or %NULL
+ * @model: (allow-none): a pointer to receive a #GtkTreeModel or %NULL
+ * @path: (allow-none): a pointer to receive a #GtkTreePath or %NULL
+ * @iter: (allow-none): a pointer to receive a #GtkTreeIter or %NULL
*
* This function is supposed to be used in a #GtkWidget::query-tooltip
* signal handler for #GtkTreeView. The @x, @y and @keyboard_tip values
GtkTooltip *tooltip,
gpointer data)
{
- gchar *str;
+ GValue value = { 0, };
+ GValue transformed = { 0, };
GtkTreeIter iter;
GtkTreePath *path;
GtkTreeModel *model;
&model, &path, &iter))
return FALSE;
- gtk_tree_model_get (model, &iter, tree_view->priv->tooltip_column, &str, -1);
+ gtk_tree_model_get_value (model, &iter,
+ tree_view->priv->tooltip_column, &value);
- if (!str)
+ g_value_init (&transformed, G_TYPE_STRING);
+
+ if (!g_value_transform (&value, &transformed))
+ {
+ g_value_unset (&value);
+ gtk_tree_path_free (path);
+
+ return FALSE;
+ }
+
+ g_value_unset (&value);
+
+ if (!g_value_get_string (&transformed))
{
+ g_value_unset (&transformed);
gtk_tree_path_free (path);
+
return FALSE;
}
- gtk_tooltip_set_markup (tooltip, str);
+ gtk_tooltip_set_markup (tooltip, g_value_get_string (&transformed));
gtk_tree_view_set_tooltip_row (tree_view, tooltip, path);
gtk_tree_path_free (path);
- g_free (str);
+ g_value_unset (&transformed);
return TRUE;
}
* When enabled, #GtkWidget::has-tooltip will be set to %TRUE and
* @tree_view will connect a #GtkWidget::query-tooltip signal handler.
*
+ * Note that the signal handler sets the text with gtk_tooltip_set_markup(),
+ * so &, <, etc have to be escaped in the text.
+ *
* Since: 2.12
*/
void