*/
+#include <config.h>
#include <string.h>
#include <gdk/gdkkeysyms.h>
#include "gtkentry.h"
#include "gtktreemodelsort.h"
-#define GTK_TREE_VIEW_SEARCH_DIALOG_KEY "gtk-tree-view-search-dialog"
-
#define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
#define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
#define GTK_TREE_VIEW_NUM_ROWS_PER_IDLE 500
GdkEventButton *event);
static gboolean gtk_tree_view_button_release (GtkWidget *widget,
GdkEventButton *event);
+#if 0
+static gboolean gtk_tree_view_configure (GtkWidget *widget,
+ GdkEventConfigure *event);
+#endif
+
static void gtk_tree_view_set_focus_child (GtkContainer *container,
GtkWidget *child);
static gint gtk_tree_view_focus_out (GtkWidget *widget,
static gboolean do_expand_collapse (GtkTreeView *tree_view);
/* interactive search */
-static void gtk_tree_view_search_dialog_destroy (GtkWidget *search_dialog,
+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);
widget_class->size_allocate = gtk_tree_view_size_allocate;
widget_class->button_press_event = gtk_tree_view_button_press;
widget_class->button_release_event = gtk_tree_view_button_release;
+ /*widget_class->configure_event = gtk_tree_view_configure;*/
widget_class->motion_notify_event = gtk_tree_view_motion;
widget_class->expose_event = gtk_tree_view_expose;
widget_class->key_press_event = gtk_tree_view_key_press;
g_object_class_install_property (o_class,
PROP_MODEL,
g_param_spec_object ("model",
- _("TreeView Model"),
- _("The model for the tree view"),
+ P_("TreeView Model"),
+ P_("The model for the tree view"),
GTK_TYPE_TREE_MODEL,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_HADJUSTMENT,
g_param_spec_object ("hadjustment",
- _("Horizontal Adjustment"),
- _("Horizontal Adjustment for the widget"),
+ P_("Horizontal Adjustment"),
+ P_("Horizontal Adjustment for the widget"),
GTK_TYPE_ADJUSTMENT,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_VADJUSTMENT,
g_param_spec_object ("vadjustment",
- _("Vertical Adjustment"),
- _("Vertical Adjustment for the widget"),
+ P_("Vertical Adjustment"),
+ P_("Vertical Adjustment for the widget"),
GTK_TYPE_ADJUSTMENT,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_HEADERS_VISIBLE,
g_param_spec_boolean ("headers_visible",
- _("Visible"),
- _("Show the column header buttons"),
+ P_("Visible"),
+ P_("Show the column header buttons"),
TRUE,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_HEADERS_CLICKABLE,
g_param_spec_boolean ("headers_clickable",
- _("Headers Clickable"),
- _("Column headers respond to click events"),
+ P_("Headers Clickable"),
+ P_("Column headers respond to click events"),
FALSE,
G_PARAM_WRITABLE));
g_object_class_install_property (o_class,
PROP_EXPANDER_COLUMN,
g_param_spec_object ("expander_column",
- _("Expander Column"),
- _("Set the column for the expander column"),
+ P_("Expander Column"),
+ P_("Set the column for the expander column"),
GTK_TYPE_TREE_VIEW_COLUMN,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_REORDERABLE,
g_param_spec_boolean ("reorderable",
- _("Reorderable"),
- _("View is reorderable"),
+ P_("Reorderable"),
+ P_("View is reorderable"),
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_RULES_HINT,
g_param_spec_boolean ("rules_hint",
- _("Rules Hint"),
- _("Set a hint to the theme engine to draw rows in alternating colors"),
+ P_("Rules Hint"),
+ P_("Set a hint to the theme engine to draw rows in alternating colors"),
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_ENABLE_SEARCH,
g_param_spec_boolean ("enable_search",
- _("Enable Search"),
- _("View allows user to search through columns interactively"),
+ P_("Enable Search"),
+ P_("View allows user to search through columns interactively"),
TRUE,
G_PARAM_READWRITE));
g_object_class_install_property (o_class,
PROP_SEARCH_COLUMN,
g_param_spec_int ("search_column",
- _("Search Column"),
- _("Model column to search through when searching through code"),
+ P_("Search Column"),
+ P_("Model column to search through when searching through code"),
-1,
G_MAXINT,
0,
g_object_class_install_property (o_class,
PROP_FIXED_HEIGHT_MODE,
g_param_spec_boolean ("fixed_height_mode",
- _("Fixed Height Mode"),
- _("Speeds up GtkTreeView by assuming that all rows have the same height"),
+ P_("Fixed Height Mode"),
+ P_("Speeds up GtkTreeView by assuming that all rows have the same height"),
FALSE,
G_PARAM_READWRITE));
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("expander_size",
- _("Expander Size"),
- _("Size of the expander arrow"),
+ P_("Expander Size"),
+ P_("Size of the expander arrow"),
0,
G_MAXINT,
_TREE_VIEW_EXPANDER_SIZE,
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("vertical_separator",
- _("Vertical Separator Width"),
- _("Vertical space between cells. Must be an even number"),
+ P_("Vertical Separator Width"),
+ P_("Vertical space between cells. Must be an even number"),
0,
G_MAXINT,
_TREE_VIEW_VERTICAL_SEPARATOR,
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("horizontal_separator",
- _("Horizontal Separator Width"),
- _("Horizontal space between cells. Must be an even number"),
+ P_("Horizontal Separator Width"),
+ P_("Horizontal space between cells. Must be an even number"),
0,
G_MAXINT,
_TREE_VIEW_HORIZONTAL_SEPARATOR,
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boolean ("allow_rules",
- _("Allow Rules"),
- _("Allow drawing of alternating color rows"),
+ P_("Allow Rules"),
+ P_("Allow drawing of alternating color rows"),
TRUE,
G_PARAM_READABLE));
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boolean ("indent_expanders",
- _("Indent Expanders"),
- _("Make the expanders indented"),
+ P_("Indent Expanders"),
+ P_("Make the expanders indented"),
TRUE,
G_PARAM_READABLE));
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boxed ("even_row_color",
- _("Even Row Color"),
- _("Color to use for even rows"),
+ P_("Even Row Color"),
+ P_("Color to use for even rows"),
GDK_TYPE_COLOR,
G_PARAM_READABLE));
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boxed ("odd_row_color",
- _("Odd Row Color"),
- _("Color to use for odd rows"),
+ P_("Odd Row Color"),
+ P_("Color to use for odd rows"),
GDK_TYPE_COLOR,
G_PARAM_READABLE));
/* expand and collapse rows */
gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
- G_TYPE_BOOLEAN, TRUE,
+ 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,
- G_TYPE_BOOLEAN, TRUE,
+ 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,
- G_TYPE_BOOLEAN, TRUE,
+ 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,
- G_TYPE_BOOLEAN, TRUE,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ 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,
- G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE,
G_TYPE_BOOLEAN, FALSE,
G_TYPE_BOOLEAN, TRUE);
gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK,
tree_view->priv->search_column = -1;
tree_view->priv->search_dialog_position_func = gtk_tree_view_search_position_func;
tree_view->priv->search_equal_func = gtk_tree_view_search_equal_func;
+ tree_view->priv->init_hadjust_value = TRUE;
+ tree_view->priv->width = 0;
}
\f
tree_view->priv->anchor = NULL;
/* destroy interactive search dialog */
- search_dialog = g_object_get_data (G_OBJECT (tree_view),
- GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
- if (search_dialog)
- gtk_tree_view_search_dialog_destroy (search_dialog,
- tree_view);
+ if (tree_view->priv->search_window)
+ {
+ gtk_widget_destroy (tree_view->priv->search_window);
+ tree_view->priv->search_window = NULL;
+ tree_view->priv->search_entry = NULL;
+ }
if (tree_view->priv->search_destroy)
{
if (tree_view->priv->model == NULL)
{
tree_view->priv->width = 0;
+ tree_view->priv->prev_width = 0;
tree_view->priv->height = 0;
return;
}
+ 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++)
GtkTreeView *tree_view;
gboolean width_changed = FALSE;
gboolean dy_changed = FALSE;
+ gint old_width = widget->allocation.width;
g_return_if_fail (GTK_IS_TREE_VIEW (widget));
tree_view->priv->hadjustment->lower = 0;
tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->page_size, tree_view->priv->width);
- 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 (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);
+ }
+ else
+ {
+ 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);
+
gtk_adjustment_changed (tree_view->priv->hadjustment);
tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
if (tree_view->priv->vadjustment->value + allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view) > tree_view->priv->height)
{
- dy_changed = TRUE;
+ double before = tree_view->priv->vadjustment->value;
gtk_adjustment_set_value (tree_view->priv->vadjustment,
MAX (tree_view->priv->height - tree_view->priv->vadjustment->page_size, 0));
+ if (before != tree_view->priv->vadjustment->value)
+ dy_changed = TRUE;
}
gtk_adjustment_changed (tree_view->priv->vadjustment);
"horizontal_separator", &horizontal_separator,
NULL);
- /* put this separate, because the user might remove the latest
- * treeview node in the focus-in-event callback. If so, the code
- * flow won't enter the second if.
+
+ /* Because grab_focus can cause reentrancy, we delay grab_focus until after
+ * we're done handling the button press.
*/
if (event->window == tree_view->priv->bin_window &&
tree_view->priv->tree != NULL)
{
- if (!GTK_WIDGET_HAS_FOCUS (widget))
- gtk_widget_grab_focus (widget);
- GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
}
if (event->window == tree_view->priv->bin_window &&
event->x,
event->y);
}
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+ GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
return TRUE;
}
y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
if (node == NULL)
- /* We clicked in dead space */
- return TRUE;
+ {
+ /* We clicked in dead space */
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+ GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+ return TRUE;
+ }
/* Get the path and the node */
path = _gtk_tree_view_find_path (tree_view, tree, node);
if (column == NULL)
{
gtk_tree_path_free (path);
-
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+ GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
return FALSE;
}
tree_view->priv->focus_column = column;
/* decide if we edit */
- if (event->type == GDK_BUTTON_PRESS &&
+ if (event->type == GDK_BUTTON_PRESS && event->button == 1 &&
!(event->state & gtk_accelerator_get_default_mod_mask ()))
{
GtkTreePath *anchor;
/* Save press to possibly begin a drag
*/
grab_widget = gtk_grab_get_current ();
- if ((grab_widget == NULL || grab_widget == GTK_WIDGET (tree_view)) &&
+ if ((grab_widget == NULL || grab_widget == widget) &&
!column_handled_click &&
tree_view->priv->pressed_button < 0)
{
}
}
- GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
-
if (row_double_click)
{
gtk_grab_remove (widget);
gtk_tree_path_free (path);
+ if (!GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_widget_grab_focus (widget);
+ GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
+
return TRUE;
}
gtk_tree_view_column_get_sizing (column) != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
{
_gtk_tree_view_column_autosize (tree_view, column);
- break;
+ return TRUE;
}
if (gdk_pointer_grab (column->window, FALSE,
tree_view->priv->drag_pos = i;
tree_view->priv->x_drag = column->button->allocation.x + (rtl ? 0 : column->button->allocation.width);
- break;
+ return TRUE;
}
}
- return TRUE;
+ return FALSE;
}
/* GtkWidget::button_release_event helper */
return TRUE;
}
+#if 0
+static gboolean
+gtk_tree_view_configure (GtkWidget *widget,
+ GdkEventConfigure *event)
+{
+ GtkTreeView *tree_view;
+
+ tree_view = GTK_TREE_VIEW (widget);
+ tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+
+ return FALSE;
+}
+#endif
/* GtkWidget::motion_event function set.
*/
gboolean allow_rules;
gboolean has_special_cell;
gboolean rtl;
+ gint n_visible_columns;
g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
gdk_drawable_get_size (tree_view->priv->bin_window,
&bin_window_width, NULL);
+
+ n_visible_columns = 0;
+ for (list = tree_view->priv->columns; list; list = list->next)
+ {
+ if (! GTK_TREE_VIEW_COLUMN (list->data)->visible)
+ continue;
+ n_visible_columns ++;
+ }
+
+ /* Find the last column */
for (last_column = rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns);
last_column &&
!(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
}
if (column->show_sort_indicator)
- flags |= GTK_CELL_RENDERER_SORTED;
+ flags |= GTK_CELL_RENDERER_SORTED;
else
flags &= ~GTK_CELL_RENDERER_SORTED;
*/
if (allow_rules && tree_view->priv->has_rules)
{
- if (flags & GTK_CELL_RENDERER_SORTED)
+ if ((flags & GTK_CELL_RENDERER_SORTED) &&
+ n_visible_columns >= 3)
{
if (parity)
detail = "cell_odd_ruled_sorted";
}
else
{
- if (flags & GTK_CELL_RENDERER_SORTED)
+ if ((flags & GTK_CELL_RENDERER_SORTED) &&
+ n_visible_columns >= 3)
{
if (parity)
detail = "cell_odd_sorted";
}
}
- return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
+ if ((* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event))
+ return TRUE;
+
+ return FALSE;
}
/* FIXME Is this function necessary? Can I get an enter_notify event
gtk_tree_view_focus_out (GtkWidget *widget,
GdkEventFocus *event)
{
- GtkWidget *search_dialog;
+ GtkTreeView *tree_view;
+
+ tree_view = GTK_TREE_VIEW (widget);
gtk_widget_queue_draw (widget);
/* destroy interactive search dialog */
- search_dialog = g_object_get_data (G_OBJECT (widget),
- GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
- if (search_dialog)
- gtk_tree_view_search_dialog_destroy (search_dialog, GTK_TREE_VIEW (widget));
+ if (tree_view->priv->search_window)
+ gtk_tree_view_search_dialog_hide (tree_view->priv->search_window, tree_view);
return FALSE;
}
GtkRBNode *tmpnode = NULL;
gint depth;
gint i = 0;
+ gint height;
gboolean free_path = FALSE;
g_return_if_fail (path != NULL || iter != NULL);
if (tree == NULL)
goto done;
+ if (tree_view->priv->fixed_height_mode
+ && tree_view->priv->fixed_height >= 0)
+ height = tree_view->priv->fixed_height;
+ else
+ height = 0;
+
/* ref the node */
gtk_tree_model_ref_node (tree_view->priv->model, iter);
if (indices[depth - 1] == 0)
{
tmpnode = _gtk_rbtree_find_count (tree, 1);
- _gtk_rbtree_insert_before (tree, tmpnode, 0, FALSE);
+ _gtk_rbtree_insert_before (tree, tmpnode, height, FALSE);
}
else
{
tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
- _gtk_rbtree_insert_after (tree, tmpnode, 0, FALSE);
- }
-
- if (tree_view->priv->fixed_height_mode
- && tree_view->priv->fixed_height >= 0)
- _gtk_rbtree_node_set_height (tree, tmpnode, tree_view->priv->fixed_height);
+ _gtk_rbtree_insert_after (tree, tmpnode, height, FALSE);
+ }
done:
install_presize_handler (tree_view);
cancel_arrow_animation (GtkTreeView *tree_view)
{
if (tree_view->priv->expand_collapse_timeout)
- while (do_expand_collapse (tree_view));
- tree_view->priv->expand_collapse_timeout = 0;
+ {
+ 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_widget_grab_focus (GTK_WIDGET (tree_view));
gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
+ if (!logical
+ && gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL)
+ expand = !expand;
+
if (expand)
gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
else
gdk_event_free (fevent);
}
-static gboolean
-gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
+static void
+gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view)
{
- GtkWidget *window;
- GtkWidget *entry;
- GtkWidget *search_dialog;
-
- if (! GTK_WIDGET_HAS_FOCUS (tree_view))
- return FALSE;
-
- if (tree_view->priv->enable_search == FALSE ||
- tree_view->priv->search_column < 0)
- return FALSE;
-
- search_dialog = g_object_get_data (G_OBJECT (tree_view),
- GTK_TREE_VIEW_SEARCH_DIALOG_KEY);
- if (search_dialog)
- return FALSE;
+ if (tree_view->priv->search_window != NULL)
+ return;
- /* set up window */
- window = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_window_set_title (GTK_WINDOW (window), "search dialog");
- gtk_container_set_border_width (GTK_CONTAINER (window), 3);
- gtk_window_set_modal (GTK_WINDOW (window), TRUE);
- g_signal_connect (window, "delete_event",
+ tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_container_set_border_width (GTK_CONTAINER (tree_view->priv->search_window), 3);
+ gtk_window_set_modal (GTK_WINDOW (tree_view->priv->search_window), TRUE);
+ g_signal_connect (tree_view->priv->search_window, "delete_event",
G_CALLBACK (gtk_tree_view_search_delete_event),
tree_view);
- g_signal_connect (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 (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);
/* add entry */
- entry = gtk_entry_new ();
- gtk_widget_show (entry);
- g_signal_connect (entry, "changed",
+ tree_view->priv->search_entry = gtk_entry_new ();
+ gtk_widget_show (tree_view->priv->search_entry);
+ g_signal_connect (tree_view->priv->search_entry, "changed",
G_CALLBACK (gtk_tree_view_search_init),
tree_view);
- g_signal_connect (entry, "populate_popup",
+ g_signal_connect (tree_view->priv->search_entry, "populate_popup",
G_CALLBACK (gtk_tree_view_search_disable_popdown),
tree_view);
- gtk_container_add (GTK_CONTAINER (window), entry);
+ gtk_container_add (GTK_CONTAINER (tree_view->priv->search_window),
+ tree_view->priv->search_entry);
+}
- /* done, show it */
- tree_view->priv->search_dialog_position_func (tree_view, window);
- gtk_widget_show_all (window);
- gtk_widget_grab_focus (entry);
+static gboolean
+gtk_tree_view_real_start_interactive_search (GtkTreeView *tree_view)
+{
+ if (! GTK_WIDGET_HAS_FOCUS (tree_view))
+ return FALSE;
- /* send focus-in event */
- send_focus_change (entry, TRUE);
+ if (tree_view->priv->enable_search == FALSE ||
+ tree_view->priv->search_column < 0)
+ return FALSE;
+
+ gtk_tree_view_ensure_interactive_directory (tree_view);
+ gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
- /* position window */
+ /* done, show it */
+ tree_view->priv->search_dialog_position_func (tree_view, tree_view->priv->search_window);
+ gtk_widget_show (tree_view->priv->search_window);
+ gtk_widget_grab_focus (tree_view->priv->search_entry);
- /* yes, we point to the entry's private text thing here, a bit evil */
- g_object_set_data (G_OBJECT (window), "gtk-tree-view-text",
- (gchar *) gtk_entry_get_text (GTK_ENTRY (entry)));
- g_object_set_data (G_OBJECT (tree_view),
- GTK_TREE_VIEW_SEARCH_DIALOG_KEY, window);
+ /* send focus-in event */
+ send_focus_change (tree_view->priv->search_entry, TRUE);
/* search first matching iter */
- gtk_tree_view_search_init (entry, tree_view);
+ gtk_tree_view_search_init (tree_view->priv->search_entry, tree_view);
return TRUE;
}
0);
dy = tree_view->priv->dy - (int) tree_view->priv->vadjustment->value;
if (dy && tree_view->priv->edited_column)
- gtk_tree_view_stop_editing (tree_view, TRUE);
+ {
+ if (GTK_IS_WIDGET (tree_view->priv->edited_column->editable_widget))
+ GTK_WIDGET (tree_view->priv->edited_column->editable_widget)->allocation.y += dy;
+ }
gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
/* update our dy and top_row */
* #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
- * signals.
+ * row_inserted and row_deleted signals.
*
* This function does not give you any degree of control over the order -- any
- * reorderering is allowed. If more control is needed, you should probably
+ * reordering is allowed. If more control is needed, you should probably
* handle drag and drop manually.
**/
void
remaining_x -= tmp_column->width;
}
+ /* If found is FALSE and there is a last_column, then it the remainder
+ * space is in that area
+ */
if (!found)
{
- if (column)
- *column = last_column;
-
- if (cell_x)
- *cell_x = last_column->width + remaining_x;
- }
+ if (last_column)
+ {
+ if (column)
+ *column = last_column;
+
+ if (cell_x)
+ *cell_x = last_column->width + remaining_x;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
}
y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
}
}
+/**
+ * gtk_tree_view_enable_model_drag_source:
+ * @tree_view: a #GtkTreeView
+ * @start_button_mask: Mask of allowed buttons to start drag
+ * @targets: the table of targets that the drag will support
+ * @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.
+ **/
void
gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view,
GdkModifierType start_button_mask,
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+ gtk_drag_source_set (GTK_WIDGET (tree_view),
+ 0,
+ NULL,
+ 0,
+ actions);
+
di = ensure_info (tree_view);
clear_source_info (di);
unset_reorderable (tree_view);
}
+/**
+ * gtk_tree_view_enable_model_drag_dest:
+ * @tree_view: a #GtkTreeView
+ * @targets: the table of targets that the drag will support
+ * @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 drop destination for automatic DND.
+ **/
void
gtk_tree_view_enable_model_drag_dest (GtkTreeView *tree_view,
const GtkTargetEntry *targets,
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().
+ **/
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;
}
unset_reorderable (tree_view);
}
+/**
+ * gtk_tree_view_unset_rows_drag_dest:
+ * @tree_view: a #GtkTreeView
+ *
+ * Undoes the effect of gtk_tree_view_enable_model_drag_dest().
+ **/
void
gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
{
unset_reorderable (tree_view);
}
+/**
+ * gtk_tree_view_set_drag_dest_row:
+ * @tree_view: a #GtkTreeView
+ * @path: 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.
+ **/
void
gtk_tree_view_set_drag_dest_row (GtkTreeView *tree_view,
GtkTreePath *path,
}
}
+/**
+ * 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
+ *
+ * Gets information about the row that is highlighted for feedback.
+ **/
void
gtk_tree_view_get_drag_dest_row (GtkTreeView *tree_view,
GtkTreePath **path,
*pos = tree_view->priv->drag_dest_pos;
}
+/**
+ * gtk_tree_view_get_dest_row_at_pos:
+ * @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
+ *
+ * Determines the destination row for a given position.
+ *
+ * Return value: whether there is a row at the given postiion,
+ **/
gboolean
gtk_tree_view_get_dest_row_at_pos (GtkTreeView *tree_view,
gint drag_x,
* @search_user_data: user data to pass to @search_equal_func, or %NULL
* @search_destroy: Destroy notifier for @search_user_data, or %NULL
*
- * Sets the compare function for the interactive search capabilities.
+ * Sets the compare function for the interactive search capabilities; note
+ * that somewhat like strcmp() returning 0 for equality
+ * #GtkTreeViewSearchEqualFunc returns %FALSE on matches.
**/
void
gtk_tree_view_set_search_equal_func (GtkTreeView *tree_view,
}
static void
-gtk_tree_view_search_dialog_destroy (GtkWidget *search_dialog,
+gtk_tree_view_search_dialog_hide (GtkWidget *search_dialog,
GtkTreeView *tree_view)
{
- GtkEntry *entry = (GtkEntry *)(gtk_container_get_children (GTK_CONTAINER (search_dialog)))->data;
- gint *selected_iter;
-
if (tree_view->priv->disable_popdown)
return;
- if (entry)
- {
- /* send focus-in event */
- send_focus_change (GTK_WIDGET (entry), FALSE);
- }
-
- /* remove data from tree_view */
- g_object_set_data (G_OBJECT (tree_view), GTK_TREE_VIEW_SEARCH_DIALOG_KEY,
- NULL);
-
- selected_iter = g_object_get_data (G_OBJECT (search_dialog),
- "gtk-tree-view-selected-iter");
- if (selected_iter)
- g_free (selected_iter);
- g_object_set_data (G_OBJECT (search_dialog), "gtk-tree-view-selected-iter",
- NULL);
-
- gtk_widget_destroy (search_dialog);
+ /* send focus-in event */
+ send_focus_change (GTK_WIDGET (tree_view->priv->search_entry), FALSE);
+ gtk_widget_hide (search_dialog);
}
static void
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
- gtk_tree_view_search_dialog_destroy (widget, tree_view);
+ gtk_tree_view_search_dialog_hide (widget, tree_view);
return TRUE;
}
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
- gtk_tree_view_search_dialog_destroy (widget, tree_view);
+ gtk_tree_view_search_dialog_hide (widget, tree_view);
return TRUE;
}
event->keyval == GDK_Return ||
event->keyval == GDK_Tab)
{
- gtk_tree_view_search_dialog_destroy (widget, tree_view);
+ gtk_tree_view_search_dialog_hide (widget, tree_view);
return TRUE;
}
gboolean up)
{
gboolean ret;
- gint *selected_iter;
gint len;
gint count = 0;
- gchar *text;
+ const gchar *text;
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreeSelection *selection;
- text = g_object_get_data (G_OBJECT (window), "gtk-tree-view-text");
- selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
+ text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
g_return_if_fail (text != NULL);
- if (!selected_iter || (up && *selected_iter == 1))
+ if (up && tree_view->priv->selected_iter == 1)
return;
len = strlen (text);
gtk_tree_model_get_iter_first (model, &iter);
ret = gtk_tree_view_search_iter (model, selection, &iter, text,
- &count, up?((*selected_iter) - 1):((*selected_iter + 1)));
+ &count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
if (ret)
{
/* found */
- *selected_iter += up?(-1):(1);
+ tree_view->priv->selected_iter += up?(-1):(1);
}
else
{
gtk_tree_model_get_iter_first (model, &iter);
gtk_tree_view_search_iter (model, selection,
&iter, text,
- &count, *selected_iter);
+ &count, tree_view->priv->selected_iter);
}
}
gpointer search_data)
{
gboolean retval = TRUE;
+ const gchar *str;
gchar *normalized_string;
gchar *normalized_key;
- gchar *case_normalized_string;
- gchar *case_normalized_key;
+ gchar *case_normalized_string = NULL;
+ gchar *case_normalized_key = NULL;
GValue value = {0,};
GValue transformed = {0,};
- gint key_len;
gtk_tree_model_get_value (model, iter, column, &value);
if (!g_value_transform (&value, &transformed))
{
g_value_unset (&value);
- return FALSE;
+ return TRUE;
}
g_value_unset (&value);
- normalized_string = g_utf8_normalize (g_value_get_string (&transformed), -1, G_NORMALIZE_ALL);
+ str = g_value_get_string (&transformed);
+ if (!str)
+ {
+ g_value_unset (&transformed);
+ return TRUE;
+ }
+
+ normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
- case_normalized_string = g_utf8_casefold (normalized_string, -1);
- case_normalized_key = g_utf8_casefold (normalized_key, -1);
- key_len = strlen (case_normalized_key);
+ if (normalized_string && normalized_key)
+ {
+ case_normalized_string = g_utf8_casefold (normalized_string, -1);
+ case_normalized_key = g_utf8_casefold (normalized_key, -1);
- if (!strncmp (case_normalized_key, case_normalized_string, key_len))
- retval = FALSE;
+ if (strstr (case_normalized_string, case_normalized_key))
+ retval = FALSE;
+ }
g_value_unset (&transformed);
g_free (normalized_key);
GtkTreeView *tree_view)
{
gint ret;
- gint *selected_iter;
gint len;
gint count = 0;
const gchar *text;
/* search */
gtk_tree_selection_unselect_all (selection);
- selected_iter = g_object_get_data (G_OBJECT (window), "gtk-tree-view-selected-iter");
- if (selected_iter)
- g_free (selected_iter);
- g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter", NULL);
if (len < 1)
return;
&count, 1);
if (ret)
- {
- selected_iter = g_malloc (sizeof (int));
- *selected_iter = 1;
- g_object_set_data (G_OBJECT (window), "gtk-tree-view-selected-iter",
- selected_iter);
- }
+ tree_view->priv->selected_iter = 1;
}
static void