X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktreeview.c;h=65bc59e7e6980b454895aa68640a1ca78d1e8d71;hb=d7cb94614d93ca364cc3095bd6489a516b7da7c6;hp=c8c2ffb2f25c14ed3f861a08adcef436775f2df6;hpb=5f65142b3ca6c8885273a60e61a0cc0c1a151da8;p=~andy%2Fgtk diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index c8c2ffb2f..65bc59e7e 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -18,6 +18,7 @@ */ +#include #include #include @@ -39,8 +40,6 @@ #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 @@ -165,6 +164,11 @@ static gboolean gtk_tree_view_button_press (GtkWidget *widget, 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, @@ -359,7 +363,7 @@ static gboolean expand_collapse_timeout (gpointer 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); @@ -486,6 +490,7 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) 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; @@ -524,80 +529,80 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) 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, @@ -606,8 +611,8 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) 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)); @@ -618,8 +623,8 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) 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, @@ -627,8 +632,8 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) 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, @@ -636,8 +641,8 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) 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, @@ -645,29 +650,29 @@ gtk_tree_view_class_init (GtkTreeViewClass *class) 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)); @@ -1076,6 +1081,8 @@ gtk_tree_view_init (GtkTreeView *tree_view) 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; } @@ -1284,11 +1291,12 @@ gtk_tree_view_destroy (GtkObject *object) 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) { @@ -1583,10 +1591,12 @@ gtk_tree_view_update_size (GtkTreeView *tree_view) 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++) @@ -1887,6 +1897,7 @@ gtk_tree_view_size_allocate (GtkWidget *widget, 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)); @@ -1921,8 +1932,30 @@ gtk_tree_view_size_allocate (GtkWidget *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); @@ -2013,16 +2046,13 @@ gtk_tree_view_button_press (GtkWidget *widget, "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 && @@ -2059,6 +2089,9 @@ gtk_tree_view_button_press (GtkWidget *widget, 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; } @@ -2069,8 +2102,13 @@ gtk_tree_view_button_press (GtkWidget *widget, 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); @@ -2117,7 +2155,9 @@ gtk_tree_view_button_press (GtkWidget *widget, 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; } @@ -2287,8 +2327,6 @@ gtk_tree_view_button_press (GtkWidget *widget, } } - GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS); - if (row_double_click) { gtk_grab_remove (widget); @@ -2300,6 +2338,10 @@ gtk_tree_view_button_press (GtkWidget *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; } @@ -2318,7 +2360,7 @@ gtk_tree_view_button_press (GtkWidget *widget, 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, @@ -2346,10 +2388,10 @@ gtk_tree_view_button_press (GtkWidget *widget, 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 */ @@ -2498,6 +2540,19 @@ gtk_tree_view_button_release (GtkWidget *widget, 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. */ @@ -3129,6 +3184,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget, gboolean allow_rules; gboolean has_special_cell; gboolean rtl; + gint n_visible_columns; g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE); @@ -3191,6 +3247,16 @@ gtk_tree_view_bin_expose (GtkWidget *widget, 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) && @@ -3247,7 +3313,7 @@ gtk_tree_view_bin_expose (GtkWidget *widget, } if (column->show_sort_indicator) - flags |= GTK_CELL_RENDERER_SORTED; + flags |= GTK_CELL_RENDERER_SORTED; else flags &= ~GTK_CELL_RENDERER_SORTED; @@ -3283,7 +3349,8 @@ gtk_tree_view_bin_expose (GtkWidget *widget, */ 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"; @@ -3300,7 +3367,8 @@ gtk_tree_view_bin_expose (GtkWidget *widget, } else { - if (flags & GTK_CELL_RENDERER_SORTED) + if ((flags & GTK_CELL_RENDERER_SORTED) && + n_visible_columns >= 3) { if (parity) detail = "cell_odd_sorted"; @@ -3972,7 +4040,10 @@ gtk_tree_view_key_press (GtkWidget *widget, } } - 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 @@ -4041,15 +4112,15 @@ static gint 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; } @@ -6615,6 +6686,7 @@ gtk_tree_view_row_inserted (GtkTreeModel *model, GtkRBNode *tmpnode = NULL; gint depth; gint i = 0; + gint height; gboolean free_path = FALSE; g_return_if_fail (path != NULL || iter != NULL); @@ -6676,22 +6748,24 @@ gtk_tree_view_row_inserted (GtkTreeModel *model, 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); @@ -6882,8 +6956,12 @@ static void 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 @@ -8341,69 +8419,61 @@ send_focus_change (GtkWidget *widget, 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; - /* position window */ + gtk_tree_view_ensure_interactive_directory (tree_view); + gtk_entry_set_text (GTK_ENTRY (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); + /* 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); + + /* 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; } @@ -8461,7 +8531,10 @@ gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment, 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 */ @@ -10282,10 +10355,10 @@ gtk_tree_view_get_reorderable (GtkTreeView *tree_view) * #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 @@ -10611,14 +10684,24 @@ gtk_tree_view_get_path_at_pos (GtkTreeView *tree_view, 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, @@ -10642,7 +10725,7 @@ gtk_tree_view_get_path_at_pos (GtkTreeView *tree_view, * 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 coordiantes + * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordinates * @rect: rectangle to fill with cell rect * * Fills the bounding rectangle in tree window coordinates for the cell at the @@ -10864,6 +10947,17 @@ unset_reorderable (GtkTreeView *tree_view) } } +/** + * 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, @@ -10875,6 +10969,12 @@ gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view, 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); @@ -10887,6 +10987,16 @@ gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view, 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, @@ -10914,6 +11024,12 @@ gtk_tree_view_enable_model_drag_dest (GtkTreeView *tree_view, 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) { @@ -10927,6 +11043,7 @@ 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; } @@ -10938,6 +11055,12 @@ gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view) 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) { @@ -10963,6 +11086,14 @@ 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, @@ -11033,6 +11164,14 @@ gtk_tree_view_set_drag_dest_row (GtkTreeView *tree_view, } } +/** + * 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, @@ -11057,6 +11196,18 @@ gtk_tree_view_get_drag_dest_row (GtkTreeView *tree_view, *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, @@ -11396,7 +11547,9 @@ gtk_tree_view_get_search_equal_func (GtkTreeView *tree_view) * @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, @@ -11418,33 +11571,15 @@ 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 @@ -11523,7 +11658,7 @@ gtk_tree_view_search_delete_event (GtkWidget *widget, { 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; } @@ -11535,7 +11670,7 @@ gtk_tree_view_search_button_press_event (GtkWidget *widget, { 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; } @@ -11553,7 +11688,7 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget, 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; } @@ -11580,20 +11715,18 @@ gtk_tree_view_search_move (GtkWidget *window, 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); @@ -11609,12 +11742,12 @@ gtk_tree_view_search_move (GtkWidget *window, 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 { @@ -11623,7 +11756,7 @@ gtk_tree_view_search_move (GtkWidget *window, 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); } } @@ -11635,13 +11768,13 @@ gtk_tree_view_search_equal_func (GtkTreeModel *model, gpointer search_data) { gboolean retval = TRUE; + const gchar *str; gchar *normalized_string; gchar *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); @@ -11650,12 +11783,19 @@ gtk_tree_view_search_equal_func (GtkTreeModel *model, 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); if (normalized_string && normalized_key) @@ -11663,13 +11803,9 @@ gtk_tree_view_search_equal_func (GtkTreeModel *model, 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 (strstr (case_normalized_string, case_normalized_key)) retval = FALSE; } - else - retval = FALSE; g_value_unset (&transformed); g_free (normalized_key); @@ -11793,7 +11929,6 @@ gtk_tree_view_search_init (GtkWidget *entry, GtkTreeView *tree_view) { gint ret; - gint *selected_iter; gint len; gint count = 0; const gchar *text; @@ -11813,10 +11948,6 @@ gtk_tree_view_search_init (GtkWidget *entry, /* 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; @@ -11828,12 +11959,7 @@ gtk_tree_view_search_init (GtkWidget *entry, &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