*/
+#include <config.h>
#include <string.h>
#include <gdk/gdkkeysyms.h>
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
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);
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 */
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";
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
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
}
}
+/**
+ * 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,
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);
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)
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);