static void gtk_tree_view_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
+ gboolean add_shifted_binding,
GtkMovementStep step,
gint count);
static gint gtk_tree_view_unref_and_check_selection_tree (GtkTreeView *tree_view,
static void gtk_tree_view_search_dialog_hide (GtkWidget *search_dialog,
GtkTreeView *tree_view);
static void gtk_tree_view_search_position_func (GtkTreeView *tree_view,
- GtkWidget *search_dialog);
+ GtkWidget *search_dialog,
+ gpointer user_data);
static void gtk_tree_view_search_disable_popdown (GtkEntry *entry,
GtkMenu *menu,
gpointer data);
};
tree_view_type =
- g_type_register_static (GTK_TYPE_CONTAINER, g_intern_static_string ("GtkTreeView"),
+ g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkTreeView"),
&tree_view_info, 0);
}
/* Signals */
widget_class->set_scroll_adjustments_signal =
- g_signal_new ("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),
GTK_TYPE_ADJUSTMENT,
GTK_TYPE_ADJUSTMENT);
+ /**
+ * GtkTreeView::row-activated:
+ * @tree_view: the object on which the signal is emitted
+ * @path: the #GtkTreePath for the activated row
+ * @column: the #GtkTreeViewColumn in which the activation occurred
+ *
+ * The "row-activated" signal is emitted when the method
+ * gtk_tree_view_row_activated() is called or the user double clicks
+ * a treeview row. It is also emitted when a non-editable row is
+ * selected and one of the keys: Space, Shift+Space, Return or
+ * Enter is pressed.
+ *
+ * For selection handling refer to the <link linkend="TreeWidget">tree
+ * widget conceptual overview</link> as well as #GtkTreeSelection.
+ */
tree_view_signals[ROW_ACTIVATED] =
- g_signal_new ("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),
GTK_TYPE_TREE_VIEW_COLUMN);
tree_view_signals[TEST_EXPAND_ROW] =
- g_signal_new ("test_expand_row",
+ g_signal_new (I_("test_expand_row"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
GTK_TYPE_TREE_PATH);
tree_view_signals[TEST_COLLAPSE_ROW] =
- g_signal_new ("test_collapse_row",
+ g_signal_new (I_("test_collapse_row"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
GTK_TYPE_TREE_PATH);
tree_view_signals[ROW_EXPANDED] =
- g_signal_new ("row_expanded",
+ g_signal_new (I_("row_expanded"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
GTK_TYPE_TREE_PATH);
tree_view_signals[ROW_COLLAPSED] =
- g_signal_new ("row_collapsed",
+ g_signal_new (I_("row_collapsed"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
GTK_TYPE_TREE_PATH);
tree_view_signals[COLUMNS_CHANGED] =
- g_signal_new ("columns_changed",
+ g_signal_new (I_("columns_changed"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
G_TYPE_NONE, 0);
tree_view_signals[CURSOR_CHANGED] =
- g_signal_new ("cursor_changed",
+ g_signal_new (I_("cursor_changed"),
G_TYPE_FROM_CLASS (o_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkTreeViewClass, cursor_changed),
G_TYPE_NONE, 0);
tree_view_signals[MOVE_CURSOR] =
- g_signal_new ("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 ("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),
G_TYPE_BOOLEAN, 0);
tree_view_signals[UNSELECT_ALL] =
- g_signal_new ("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),
G_TYPE_BOOLEAN, 0);
tree_view_signals[SELECT_CURSOR_ROW] =
- g_signal_new ("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 ("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),
G_TYPE_BOOLEAN, 0);
tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
- g_signal_new ("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 ("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),
G_TYPE_BOOLEAN, 0);
tree_view_signals[START_INTERACTIVE_SEARCH] =
- g_signal_new ("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),
G_TYPE_BOOLEAN, 0);
/* Key bindings */
- gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_tree_view_add_move_binding (binding_set, GDK_KP_Up, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KP_Up, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_tree_view_add_move_binding (binding_set, GDK_KP_Down, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KP_Down, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
+ gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK, FALSE,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_tree_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
+ gtk_tree_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK, FALSE,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_tree_view_add_move_binding (binding_set, GDK_KP_Home, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KP_Home, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_tree_view_add_move_binding (binding_set, GDK_End, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_End, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_tree_view_add_move_binding (binding_set, GDK_KP_End, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KP_End, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0, TRUE,
GTK_MOVEMENT_PAGES, -1);
- gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0, TRUE,
GTK_MOVEMENT_PAGES, -1);
- gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0, TRUE,
GTK_MOVEMENT_PAGES, 1);
- gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0, TRUE,
GTK_MOVEMENT_PAGES, 1);
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));
}
static void
gtk_tree_view_init (GtkTreeView *tree_view)
{
- tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
+ 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_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (tree_view);
tree_view->priv->enable_search = TRUE;
tree_view->priv->search_column = -1;
- tree_view->priv->search_dialog_position_func = gtk_tree_view_search_position_func;
+ tree_view->priv->search_position_func = gtk_tree_view_search_position_func;
tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
+ tree_view->priv->search_custom_entry_set = FALSE;
tree_view->priv->typeselect_flush_timeout = 0;
tree_view->priv->init_hadjust_value = TRUE;
tree_view->priv->width = 0;
case PROP_HEADERS_VISIBLE:
g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
break;
+ case PROP_HEADERS_CLICKABLE:
+ g_value_set_boolean (value, gtk_tree_view_get_headers_clickable (tree_view));
+ break;
case PROP_EXPANDER_COLUMN:
g_value_set_object (value, tree_view->priv->expander_column);
break;
static void
gtk_tree_view_finalize (GObject *object)
{
- GtkTreeView *tree_view = (GtkTreeView *) object;
-
- g_free (tree_view->priv);
-
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
}
/* GtkObject Methods
*/
+static void
+gtk_tree_view_free_rbtree (GtkTreeView *tree_view)
+{
+ _gtk_rbtree_free (tree_view->priv->tree);
+
+ tree_view->priv->tree = NULL;
+ tree_view->priv->button_pressed_node = NULL;
+ tree_view->priv->button_pressed_tree = NULL;
+ tree_view->priv->prelight_tree = NULL;
+ tree_view->priv->prelight_node = NULL;
+ tree_view->priv->expanded_collapsed_node = NULL;
+ tree_view->priv->expanded_collapsed_tree = NULL;
+}
+
static void
gtk_tree_view_destroy (GtkObject *object)
{
if (tree_view->priv->tree != NULL)
{
gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
- _gtk_rbtree_free (tree_view->priv->tree);
- tree_view->priv->tree = NULL;
+
+ gtk_tree_view_free_rbtree (tree_view);
}
if (tree_view->priv->selection != NULL)
}
}
- if (tree_view->priv->search_destroy)
+ 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_user_data = NULL;
}
- if (tree_view->priv->row_separator_destroy)
+ 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_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_data = NULL;
{
GList *tmp_list;
GtkTreeView *tree_view;
- GdkGCValues values;
GdkWindowAttr attributes;
gint attributes_mask;
&attributes, attributes_mask);
gdk_window_set_user_data (tree_view->priv->header_window, widget);
-
- values.foreground = (widget->style->white.pixel==0 ?
- widget->style->black:widget->style->white);
- values.function = GDK_XOR;
- values.subwindow_mode = GDK_INCLUDE_INFERIORS;
-
/* Add them all up. */
widget->style = gtk_style_attach (widget->style, widget->window);
gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
/* now the adjustments and window sizes are in sync, we can sync toprow/dy again */
if (tree_view->priv->height <= tree_view->priv->vadjustment->page_size)
gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
+ else if (tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
+ tree_view->priv->height - tree_view->priv->vadjustment->page_size);
else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
gtk_tree_view_top_row_to_dy (tree_view);
else
for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
list; list = (rtl ? list->prev : list->next))
{
- column = list->data;
+ GtkTreeViewColumn *candidate = list->data;
- if (!column->visible)
+ if (!candidate->visible)
continue;
- background_area.width = column->width;
+ background_area.width = candidate->width;
if ((background_area.x > (gint) event->x) ||
(background_area.x + background_area.width <= (gint) event->x))
{
}
/* we found the focus column */
+ column = candidate;
cell_area = background_area;
cell_area.width -= horizontal_separator;
cell_area.height -= vertical_separator;
GtkTreeView *tree_view;
tree_view = GTK_TREE_VIEW (widget);
- tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+ tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window);
return FALSE;
}
new_width = gtk_tree_view_new_column_width (tree_view,
tree_view->priv->drag_pos, &x);
if (x != tree_view->priv->x_drag &&
- (new_width != column->fixed_width));
+ (new_width != column->fixed_width))
{
column->use_resized_width = TRUE;
column->resized_width = new_width;
GtkRBTree *drag_highlight_tree = NULL;
GtkTreeIter iter;
gint new_y;
- gint y_offset, x_offset, cell_offset;
+ gint y_offset, cell_offset;
gint max_height;
gint depth;
GdkRectangle background_area;
GdkRectangle cell_area;
guint flags;
gint highlight_x;
+ gint expander_cell_width;
gint bin_window_width;
gint bin_window_height;
GtkTreePath *cursor_path;
max_height = ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node));
- x_offset = -event->area.x;
cell_offset = 0;
highlight_x = 0; /* should match x coord of first cell */
+ expander_cell_width = 0;
background_area.y = y_offset + event->area.y;
background_area.height = max_height;
* level of the tree we're dropping at.
*/
highlight_x = cell_area.x;
+ expander_cell_width = cell_area.width;
+
if (is_separator)
gtk_paint_hline (widget->style,
event->window,
if (highlight_y >= 0)
{
gdk_draw_line (event->window,
- widget->style->black_gc,
- highlight_x,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ rtl ? highlight_x + expander_cell_width : highlight_x,
highlight_y,
- bin_window_width - highlight_x,
+ rtl ? 0 : bin_window_width,
highlight_y);
}
}
/* We pass the event to the search_entry. If its text changes, then we start
* the typeahead find capabilities. */
- if (tree_view->priv->enable_search)
+ if (tree_view->priv->enable_search
+ && !tree_view->priv->search_custom_entry_set)
{
GdkEvent *new_event;
char *old_text;
/* Make a copy of the current text */
old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry)));
new_event = gdk_event_copy ((GdkEvent *) event);
- ((GdkEventKey *) new_event)->window = tree_view->priv->search_entry->window;
+ g_object_unref (((GdkEventKey *) new_event)->window);
+ ((GdkEventKey *) new_event)->window = g_object_ref (tree_view->priv->search_window->window);
gtk_widget_realize (tree_view->priv->search_window);
popup_menu_id = g_signal_connect (tree_view->priv->search_entry,
/* Send the event to the window. If the preedit_changed signal is emitted
* during this event, we will set priv->imcontext_changed */
tree_view->priv->imcontext_changed = FALSE;
- retval = gtk_widget_event (tree_view->priv->search_entry, new_event);
+ retval = gtk_widget_event (tree_view->priv->search_window, new_event);
+ gdk_event_free (new_event);
gtk_widget_hide (tree_view->priv->search_window);
g_signal_handler_disconnect (tree_view->priv->search_entry,
gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
gtk_tree_view_dy_to_top_row (tree_view);
}
+ else if (tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
+ {
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), tree_view->priv->height - tree_view->priv->vadjustment->page_size);
+ gtk_tree_view_dy_to_top_row (tree_view);
+ }
else
gtk_tree_view_top_row_to_dy (tree_view);
GtkTreePath *source_row)
{
g_object_set_data_full (G_OBJECT (context),
- g_intern_static_string ("gtk-tree-view-source-row"),
+ I_("gtk-tree-view-source-row"),
source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
(GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
}
if (!dest_row)
{
- g_object_set_data_full (G_OBJECT (context), g_intern_static_string ("gtk-tree-view-dest-row"),
+ g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
NULL, NULL);
return;
}
dr->empty_view_drop = empty_view_drop;
dr->drop_append_mode = drop_append_mode;
- g_object_set_data_full (G_OBJECT (context), g_intern_static_string ("gtk-tree-view-dest-row"),
+ g_object_set_data_full (G_OBJECT (context), I_("gtk-tree-view-dest-row"),
dr, (GDestroyNotify) dest_row_free);
}
GdkDragAction suggested_action)
{
g_object_set_data (G_OBJECT (context),
- g_intern_static_string ("gtk-tree-view-status-pending"),
+ I_("gtk-tree-view-status-pending"),
GINT_TO_POINTER (suggested_action));
}
di = g_new0 (TreeViewDragInfo, 1);
g_object_set_data_full (G_OBJECT (tree_view),
- g_intern_static_string ("gtk-tree-view-drag-info"),
+ I_("gtk-tree-view-drag-info"),
di,
(GDestroyNotify) destroy_info);
}
static void
remove_info (GtkTreeView *tree_view)
{
- g_object_set_data (G_OBJECT (tree_view), g_intern_static_string ("gtk-tree-view-drag-info"), NULL);
+ g_object_set_data (G_OBJECT (tree_view), I_("gtk-tree-view-drag-info"), NULL);
}
#if 0
goto done;
/* If drag_data_get does nothing, try providing row data. */
- if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
+ if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
{
gtk_tree_set_row_drag_data (selection_data,
model,
GdkDragContext *context,
guint time)
{
- TreeViewDragInfo *di;
-
- di = get_info (GTK_TREE_VIEW (widget));
-
/* unset any highlight row */
gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
NULL,
{
gboolean empty;
GtkTreePath *path = NULL;
- GtkTreeModel *model;
GtkTreeViewDropPosition pos;
GtkTreeView *tree_view;
GdkDragAction suggested_action = 0;
gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
/* we only know this *after* set_desination_row */
- model = gtk_tree_view_get_model (tree_view);
empty = tree_view->priv->empty_view_drop;
if (path == NULL && !empty)
g_timeout_add (150, scroll_row_timeout, tree_view);
}
- if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
+ if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
{
/* Request data so we can use the source row when
* determining whether to accept the drop
GtkDirectionType dir)
{
GtkWidget *focus_child;
- GtkContainer *container;
GList *last_column, *first_column;
GList *tmp_list;
return FALSE;
focus_child = GTK_CONTAINER (tree_view)->focus_child;
- container = GTK_CONTAINER (tree_view);
first_column = tree_view->priv->columns;
while (first_column)
{
for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
- break;
-
- tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+ {
+ tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
+ break;
+ }
/* If the following isn't true, then the view is smaller then the scrollpane.
*/
if (tree_view->priv->hadjustment != hadj)
{
tree_view->priv->hadjustment = hadj;
- g_object_ref (tree_view->priv->hadjustment);
- gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
+ g_object_ref_sink (tree_view->priv->hadjustment);
g_signal_connect (tree_view->priv->hadjustment, "value_changed",
G_CALLBACK (gtk_tree_view_adjustment_changed),
if (tree_view->priv->vadjustment != vadj)
{
tree_view->priv->vadjustment = vadj;
- g_object_ref (tree_view->priv->vadjustment);
- gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
+ g_object_ref_sink (tree_view->priv->vadjustment);
g_signal_connect (tree_view->priv->vadjustment, "value_changed",
G_CALLBACK (gtk_tree_view_adjustment_changed),
if (tree == NULL)
goto done;
+ /* Check if the node became insensitive, and if so, unselect it */
+ if (!_gtk_tree_selection_row_is_selectable (tree_view->priv->selection,
+ node, path))
+ gtk_tree_selection_unselect_path (tree_view->priv->selection, path);
+
if (tree_view->priv->fixed_height_mode
&& tree_view->priv->fixed_height >= 0)
{
else
x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
}
- if (x1)
- {
- *x1 = x_offset;
- }
+ *x1 = x_offset;
+
if (tmp_column && tmp_column->visible)
- {
- /* +1 because x2 isn't included in the range. */
- if (x2)
- *x2 = *x1 + tree_view->priv->expander_size + 1;
- }
+ /* +1 because x2 isn't included in the range. */
+ *x2 = *x1 + tree_view->priv->expander_size + 1;
else
- {
- /* return an empty range, the expander column is hidden */
- if (x2)
- *x2 = *x1;
- }
+ *x2 = *x1;
}
static void
gtk_tree_view_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
+ gboolean add_shifted_binding,
GtkMovementStep step,
gint count)
{
G_TYPE_ENUM, step,
G_TYPE_INT, count);
- gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
- "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,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
return;
GtkStateType state;
GtkWidget *widget;
gint x_offset = 0;
+ gint x2;
gint vertical_separator;
gint expander_size;
GtkExpanderStyle expander_style;
widget = GTK_WIDGET (tree_view);
- gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL);
+ gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, &x2);
area.x = x_offset;
area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
return TRUE;
}
+
static gboolean
gtk_tree_view_search_entry_flush_timeout (GtkTreeView *tree_view)
{
GDK_THREADS_LEAVE ();
- return TRUE;
+ return FALSE;
}
/* Cut and paste from gtkwindow.c */
{
GtkWidget *frame, *vbox, *toplevel;
+ if (tree_view->priv->search_custom_entry_set)
+ return;
+
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
if (tree_view->priv->search_window != NULL)
if (!tree_view->priv->enable_search && !keybinding)
return FALSE;
+ if (tree_view->priv->search_custom_entry_set)
+ return FALSE;
+
if (tree_view->priv->search_window != NULL &&
GTK_WIDGET_VISIBLE (tree_view->priv->search_window))
return TRUE;
gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
/* done, show it */
- tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+ tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window, tree_view->priv->search_position_user_data);
gtk_widget_show (tree_view->priv->search_window);
if (tree_view->priv->search_entry_changed_id == 0)
{
{
return gtk_tree_view_real_start_interactive_search (tree_view, TRUE);
}
+
/* this function returns the new width of the column being resized given
* the column and x position of the cursor; the x cursor position is passed
* in as a pointer and automagicly corrected if it's beyond min/max limits
tree_view->priv->model);
if (tree_view->priv->tree)
- {
- _gtk_rbtree_free (tree_view->priv->tree);
- tree_view->priv->tree = NULL;
- }
-
- tree_view->priv->prelight_node = NULL;
- tree_view->priv->prelight_tree = NULL;
- tree_view->priv->button_pressed_node = NULL;
- tree_view->priv->button_pressed_tree = NULL;
+ gtk_tree_view_free_rbtree (tree_view);
gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
tree_view->priv->drag_dest_row = NULL;
tree_view->priv->model = model;
-
if (tree_view->priv->model)
{
gint i;
g_object_notify (G_OBJECT (tree_view), "model");
+ if (tree_view->priv->selection)
+ _gtk_tree_selection_emit_changed (tree_view->priv->selection);
+
if (GTK_WIDGET_REALIZED (tree_view))
gtk_widget_queue_resize (GTK_WIDGET (tree_view));
}
}
+/**
+ * gtk_tree_view_get_headers_clickable:
+ * @tree_view: A #GtkTreeView.
+ *
+ * Returns whether all header columns are clickable.
+ *
+ * Return value: %TRUE if all header columns are clickable, otherwise %FALSE
+ *
+ * Since: 2.10
+ **/
+gboolean
+gtk_tree_view_get_headers_clickable (GtkTreeView *tree_view)
+{
+ GList *list;
+
+ g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
+
+ for (list = tree_view->priv->columns; list; list = list->next)
+ if (!GTK_TREE_VIEW_COLUMN (list->data)->clickable)
+ return FALSE;
+
+ return TRUE;
+}
+
/**
* gtk_tree_view_set_rules_hint
* @tree_view: a #GtkTreeView
g_return_val_if_fail (gtk_tree_view_column_get_sizing (column)
== GTK_TREE_VIEW_COLUMN_FIXED, -1);
- g_object_ref (column);
- gtk_object_sink (GTK_OBJECT (column));
+ g_object_ref_sink (column);
if (tree_view->priv->n_columns == 0 &&
GTK_WIDGET_REALIZED (tree_view) &&
* it is much slower than just going to the point.
*/
if (! GTK_WIDGET_VISIBLE (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))
{
GtkTreeIter temp;
gboolean expand;
+ if (animate)
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
+ "gtk-enable-animations", &animate,
+ NULL);
+
remove_auto_expand_timeout (tree_view);
if (node->children && !open_all)
gboolean collapse;
gint x, y;
GList *list;
- GdkDisplay *display;
GdkWindow *child, *parent;
+ if (animate)
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (tree_view)),
+ "gtk-enable-animations", &animate,
+ NULL);
+
remove_auto_expand_timeout (tree_view);
if (node->children == NULL)
gtk_tree_path_free (lsc);
}
+ 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;
+ }
+
if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
{
_gtk_rbtree_remove (node->children);
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;
- }
-
if (animate)
{
tree_view->priv->expand_collapse_timeout = g_timeout_add (50, expand_collapse_timeout, 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. */
- display = gdk_drawable_get_display (tree_view->priv->bin_window);
child = tree_view->priv->bin_window;
parent = gdk_window_get_parent (child);
* Sets @start_path and @end_path to be the first and last visible path.
* Note that there may be invisible paths in between.
*
+ * The paths should be freed with gtk_tree_path_free() after use.
+ *
* Returns: %TRUE, if valid paths were placed in @start_path and @end_path.
*
* Since: 2.8
* @tree_view: a #GtkTreeView
* @path: a #GtkTreePath in @tree_view
*
- * Creates a #GdkPixmap representation of the row at @path. This image is used
- * for a drag icon.
+ * Creates a #GdkPixmap representation of the row at @path.
+ * This image is used for a drag icon.
*
* Return value: a newly-allocated pixmap of the drag icon.
**/
gint bin_window_width;
gboolean is_separator = FALSE;
+ g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+ g_return_val_if_fail (path != NULL, NULL);
+
widget = GTK_WIDGET (tree_view);
+ if (!GTK_WIDGET_REALIZED (tree_view))
+ return NULL;
+
depth = gtk_tree_path_get_depth (path);
_gtk_tree_view_find_node (tree_view,
tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
}
+/**
+ * gtk_tree_view_get_search_entry:
+ * @tree_view: A #GtkTreeView
+ *
+ * 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.
+ *
+ * Return value: the entry currently in use as search entry.
+ *
+ * Since: 2.10
+ */
+GtkEntry *
+gtk_tree_view_get_search_entry (GtkTreeView *tree_view)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+ if (tree_view->priv->search_custom_entry_set)
+ return GTK_ENTRY (tree_view->priv->search_entry);
+
+ return NULL;
+}
+
+/**
+ * gtk_tree_view_set_search_entry:
+ * @tree_view: A #GtkTreeView
+ * @entry: 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
+ * in our interface at all time at a fixed position. Passing %NULL for
+ * @entry will make the interactive search code use the built-in popup
+ * entry again.
+ *
+ * Since: 2.10
+ */
+void
+gtk_tree_view_set_search_entry (GtkTreeView *tree_view,
+ GtkEntry *entry)
+{
+ g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+ if (entry != NULL)
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+
+ if (tree_view->priv->search_custom_entry_set)
+ {
+ if (tree_view->priv->search_entry_changed_id)
+ {
+ g_signal_handler_disconnect (tree_view->priv->search_entry,
+ tree_view->priv->search_entry_changed_id);
+ tree_view->priv->search_entry_changed_id = 0;
+ }
+ g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,
+ G_CALLBACK (gtk_tree_view_search_key_press_event),
+ tree_view);
+
+ g_object_unref (tree_view->priv->search_entry);
+ }
+ else if (tree_view->priv->search_window)
+ {
+ gtk_widget_destroy (tree_view->priv->search_window);
+
+ tree_view->priv->search_window = NULL;
+ }
+
+ if (entry)
+ {
+ tree_view->priv->search_entry = g_object_ref (entry);
+ tree_view->priv->search_custom_entry_set = TRUE;
+
+ if (tree_view->priv->search_entry_changed_id == 0)
+ {
+ tree_view->priv->search_entry_changed_id =
+ g_signal_connect (tree_view->priv->search_entry, "changed",
+ G_CALLBACK (gtk_tree_view_search_init),
+ tree_view);
+ }
+
+ 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_search_init (tree_view->priv->search_entry, tree_view);
+ }
+ else
+ {
+ tree_view->priv->search_entry = NULL;
+ tree_view->priv->search_custom_entry_set = FALSE;
+ }
+}
+
+/**
+ * gtk_tree_view_set_search_position_func:
+ * @tree_view: A #GtkTreeView
+ * @func: the function to use to position the search dialog
+ * @data: user data to pass to @func, or %NULL
+ * @destroy: Destroy notifier for @data, or %NULL
+ *
+ * Sets the function to use when positioning the seach dialog.
+ *
+ * Since: 2.10
+ **/
+void
+gtk_tree_view_set_search_position_func (GtkTreeView *tree_view,
+ GtkTreeViewSearchPositionFunc func,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+ g_return_if_fail (func !=NULL);
+
+ 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_func = func;
+ tree_view->priv->search_position_user_data = user_data;
+ tree_view->priv->search_position_destroy = destroy;
+ if (tree_view->priv->search_position_func == NULL)
+ tree_view->priv->search_position_func = gtk_tree_view_search_position_func;
+}
+
+/**
+ * gtk_tree_view_get_search_position_func:
+ * @tree_view: A #GtkTreeView
+ *
+ * Returns the positioning function currently in use.
+ *
+ * Return value: the currently used function for positioning the search dialog.
+ *
+ * Since: 2.10
+ */
+GtkTreeViewSearchPositionFunc
+gtk_tree_view_get_search_position_func (GtkTreeView *tree_view)
+{
+ g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
+
+ return tree_view->priv->search_position_func;
+}
+
+
static void
gtk_tree_view_search_dialog_hide (GtkWidget *search_dialog,
GtkTreeView *tree_view)
static void
gtk_tree_view_search_position_func (GtkTreeView *tree_view,
- GtkWidget *search_dialog)
+ GtkWidget *search_dialog,
+ gpointer user_data)
{
gint x, y;
gint tree_x, tree_y;
&tree_height);
gtk_widget_size_request (search_dialog, &requisition);
- if (tree_x + tree_width - requisition.width > gdk_screen_get_width (screen))
+ if (tree_x + tree_width > gdk_screen_get_width (screen))
x = gdk_screen_get_width (screen) - requisition.width;
else if (tree_x + tree_width - requisition.width < 0)
x = 0;
else
x = tree_x + tree_width - requisition.width;
- if (tree_y + tree_height > gdk_screen_get_height (screen))
+ if (tree_y + tree_height + requisition.height > gdk_screen_get_height (screen))
y = gdk_screen_get_height (screen) - requisition.height;
else if (tree_y + tree_height < 0) /* isn't really possible ... */
y = 0;
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
/* close window and cancel the search */
- if (event->keyval == GDK_Escape ||
- event->keyval == GDK_Tab)
+ if (!tree_view->priv->search_custom_entry_set
+ && (event->keyval == GDK_Escape ||
+ event->keyval == GDK_Tab ||
+ event->keyval == GDK_KP_Tab ||
+ event->keyval == GDK_ISO_Left_Tab))
{
gtk_tree_view_search_dialog_hide (widget, tree_view);
return TRUE;
retval = TRUE;
}
+ if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
+ && (event->keyval == GDK_g || event->keyval == GDK_G))
+ {
+ gtk_tree_view_search_move (widget, tree_view, TRUE);
+ retval = TRUE;
+ }
+
/* select next matching iter */
if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
{
retval = TRUE;
}
- if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK
+ if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
&& (event->keyval == GDK_g || event->keyval == GDK_G))
{
gtk_tree_view_search_move (widget, tree_view, FALSE);
}
/* renew the flush timeout */
- if (retval && tree_view->priv->typeselect_flush_timeout)
+ if (retval && tree_view->priv->typeselect_flush_timeout
+ && !tree_view->priv->search_custom_entry_set)
{
g_source_remove (tree_view->priv->typeselect_flush_timeout);
tree_view->priv->typeselect_flush_timeout =
/* search */
gtk_tree_selection_unselect_all (selection);
- if (tree_view->priv->typeselect_flush_timeout)
+ if (tree_view->priv->typeselect_flush_timeout
+ && tree_view->priv->search_custom_entry_set)
{
g_source_remove (tree_view->priv->typeselect_flush_timeout);
tree_view->priv->typeselect_flush_timeout =