diff options
Diffstat (limited to 'packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff')
-rw-r--r-- | packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff | 2253 |
1 files changed, 0 insertions, 2253 deletions
diff --git a/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff b/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff deleted file mode 100644 index 87ccffa868..0000000000 --- a/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff +++ /dev/null @@ -1,2253 +0,0 @@ ---- gtk+-2.6.4/gtk/gtktreeview.c 2005-02-24 00:38:20.000000000 +0200 -+++ gtk+-2.6.4/gtk/gtktreeview.c 2005-04-06 16:19:38.274719720 +0300 -@@ -42,6 +42,7 @@ - #include "gtkentry.h" - #include "gtkframe.h" - #include "gtktreemodelsort.h" -+#include "gtkscrolledwindow.h" - - #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5) - #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2) -@@ -114,6 +115,7 @@ - EXPAND_COLLAPSE_CURSOR_ROW, - SELECT_CURSOR_PARENT, - START_INTERACTIVE_SEARCH, -+ ROW_INSENSITIVE, - LAST_SIGNAL - }; - -@@ -132,7 +134,10 @@ - PROP_SEARCH_COLUMN, - PROP_FIXED_HEIGHT_MODE, - PROP_HOVER_SELECTION, -- PROP_HOVER_EXPAND -+ PROP_HOVER_EXPAND, -+ PROP_DOTTED_LINES, -+ PROP_FORCE_LIST_KLUDGE, -+ PROP_ALLOW_CHECKBOX_MODE - }; - - static void gtk_tree_view_class_init (GtkTreeViewClass *klass); -@@ -338,8 +343,6 @@ - static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view, - GtkRBTree *tree, - GtkRBNode *node); --static void gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view, -- GtkTreeViewColumn *column); - static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, - GdkEventMotion *event); - static void gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view); -@@ -372,6 +375,18 @@ - gpointer data); - static gboolean expand_collapse_timeout (gpointer data); - static gboolean do_expand_collapse (GtkTreeView *tree_view); -+static void update_checkbox_mode (GObject *object, -+ GParamSpec *pspec, -+ gpointer data); -+static void set_dotted_lines (GtkTreeView *tree_view, -+ gboolean enable); -+static void selection_changed (GtkTreeSelection *selection, -+ gpointer data); -+static void check_if_can_focus (GtkTreeView *tree_view); -+static gint scroll_row_timeout (gpointer data); -+ -+static void add_scroll_timeout (GtkTreeView *tree_view); -+static void remove_scroll_timeout (GtkTreeView *tree_view); - - /* interactive search */ - static void gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view); -@@ -694,8 +709,54 @@ - FALSE, - G_PARAM_READWRITE)); - -+ /** -+ * GtkTreeView:dotted-lines: -+ * -+ * Enables or disables the dotted lines for hierarchical trees. -+ * Hildon patch. -+ */ -+ g_object_class_install_property (o_class, -+ PROP_DOTTED_LINES, -+ g_param_spec_boolean ("dotted_lines", -+ P_("Dotted Lines"), -+ P_("Whether to show or hide dotted lines for hierarchical trees"), -+ FALSE, -+ G_PARAM_READWRITE)); -+ -+ /** -+ * GtkTreeView:force-list-kludge: -+ * -+ * Hildon kludge for fixing file tree behaviour until a cleaner -+ * implementation is scheduled: if this property is set, then rows -+ * can be activated by tapping even if the underlying tree model is -+ * not technically a list. -+ */ -+ g_object_class_install_property (o_class, -+ PROP_FORCE_LIST_KLUDGE, -+ g_param_spec_boolean ("force_list_kludge", -+ P_("Force List Behaviour"), -+ P_("Whether to activate tapped focused items even if model was not a list"), -+ FALSE, -+ G_PARAM_READWRITE)); -+ -+ /** -+ * GtkTreeView:enable-checkbox-mode: -+ * -+ * Another Hildon kludge for allowing the existence of GtkTreeViews -+ * that have activatable columns but that still is not a Text Listbox -+ * in multiple selection with checkboxes mode. -+ */ -+ g_object_class_install_property (o_class, -+ PROP_ALLOW_CHECKBOX_MODE, -+ g_param_spec_boolean ("allow_checkbox_mode", -+ P_("Enable Checkbox Mode"), -+ P_("Whether to behave like a Listbox in a multiple selection with checkboxes mode, if checkboxes exist"), -+ TRUE, -+ G_PARAM_READWRITE)); -+ - /* Style properties */ - #define _TREE_VIEW_EXPANDER_SIZE 12 -+#define _TREE_VIEW_EXPANDER_INDENT 10 - #define _TREE_VIEW_VERTICAL_SEPARATOR 2 - #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2 - -@@ -709,6 +770,15 @@ - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property (widget_class, -+ g_param_spec_int ("expander_indent", -+ P_("Expander intent"), -+ P_("Defines the expanders indent"), -+ 0, -+ G_MAXINT, -+ _TREE_VIEW_EXPANDER_INDENT, -+ G_PARAM_READABLE)); -+ -+ gtk_widget_class_install_style_property (widget_class, - g_param_spec_int ("vertical_separator", - P_("Vertical Separator Width"), - P_("Vertical space between cells. Must be an even number"), -@@ -754,6 +824,13 @@ - GDK_TYPE_COLOR, - G_PARAM_READABLE)); - -+ gtk_widget_class_install_style_property (widget_class, -+ g_param_spec_boolean ("passive_focus", -+ P_("Enables passive focus"), -+ P_("Used for tree view passive focus"), -+ TRUE, -+ G_PARAM_READABLE)); -+ - /* Signals */ - widget_class->set_scroll_adjustments_signal = - g_signal_new ("set_scroll_adjustments", -@@ -917,6 +994,16 @@ - _gtk_marshal_BOOLEAN__NONE, - G_TYPE_BOOLEAN, 0); - -+ tree_view_signals[ROW_INSENSITIVE] = -+ g_signal_new ("row_insensitive", -+ G_TYPE_FROM_CLASS (o_class), -+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, -+ G_STRUCT_OFFSET (GtkTreeViewClass, row_insensitive), -+ NULL, NULL, -+ _gtk_marshal_VOID__OBJECT, -+ G_TYPE_NONE, 1, -+ GTK_TYPE_TREE_PATH); -+ - /* Key bindings */ - gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0, - GTK_MOVEMENT_DISPLAY_LINES, -1); -@@ -1004,12 +1091,13 @@ - - gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1, - G_TYPE_BOOLEAN, TRUE); -+ /* Hildon change: Enter shouldn't select - gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select_cursor_row", 1, - G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select_cursor_row", 1, - G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select_cursor_row", 1, -- G_TYPE_BOOLEAN, TRUE); -+ G_TYPE_BOOLEAN, TRUE);*/ - - /* expand and collapse rows */ - gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3, -@@ -1123,19 +1211,31 @@ - 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); -+ -+ /* Hildon addition: Add key bindings to Right and Left arrows */ -+ gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "expand_collapse_cursor_row", 3, -+ G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE, G_TYPE_BOOLEAN, FALSE); -+ 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); -+ gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "expand_collapse_cursor_row", 3, -+ G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE); -+ gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3, -+ G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE); - } - - static void - gtk_tree_view_init (GtkTreeView *tree_view) - { - tree_view->priv = g_new0 (GtkTreeViewPrivate, 1); -- GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS); -+ -+ /* Hildon: focus cannot be gained until at least one row is added */ -+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS); - - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE); - -+ /* Hildon: Headers invisible by default */ - tree_view->priv->flags = GTK_TREE_VIEW_SHOW_EXPANDERS -- | GTK_TREE_VIEW_DRAW_KEYFOCUS -- | GTK_TREE_VIEW_HEADERS_VISIBLE; -+ | GTK_TREE_VIEW_DRAW_KEYFOCUS; - - /* We need some padding */ - tree_view->priv->dy = 0; -@@ -1165,6 +1265,26 @@ - - tree_view->priv->hover_selection = FALSE; - tree_view->priv->hover_expand = FALSE; -+ -+ tree_view->priv->ctrl_pressed = FALSE; -+ tree_view->priv->shift_pressed = FALSE; -+ -+ tree_view->priv->checkbox_mode = FALSE; -+ tree_view->priv->allow_checkbox_mode = TRUE; -+ tree_view->priv->pen_down = FALSE; -+ tree_view->priv->pen_drag_active = FALSE; -+ tree_view->priv->pen_drag_reverse = FALSE; -+ tree_view->priv->first_drag_row = NULL; -+ tree_view->priv->last_drag_row = NULL; -+ tree_view->priv->queued_expand_row = NULL; -+ tree_view->priv->queued_select_row = NULL; -+ tree_view->priv->pen_focus = TRUE; -+ -+ /* Hildon: cursor should follow when selection changes */ -+ g_signal_connect (tree_view->priv->selection, "changed", -+ G_CALLBACK (selection_changed), tree_view); -+ -+ gtk_widget_set_name (GTK_WIDGET (tree_view), "treeview"); - } - - -@@ -1223,6 +1343,27 @@ - case PROP_HOVER_EXPAND: - tree_view->priv->hover_expand = g_value_get_boolean (value); - break; -+ case PROP_DOTTED_LINES: -+ set_dotted_lines (tree_view, g_value_get_boolean (value)); -+ break; -+ case PROP_FORCE_LIST_KLUDGE: -+ tree_view->priv->force_list_kludge = g_value_get_boolean (value); -+ break; -+ case PROP_ALLOW_CHECKBOX_MODE: -+ if ((tree_view->priv->allow_checkbox_mode = g_value_get_boolean (value))) -+ { -+ gtk_widget_set_name (GTK_WIDGET(tree_view), "treeview"); -+ update_checkbox_mode (NULL, NULL, tree_view); -+ } -+ else -+ { -+ /* ugly hack - to ensure that checkboxes are independent of the -+ selection if !allow_checkbox_mode, we must be able to use -+ different theming in that case */ -+ gtk_widget_set_name (GTK_WIDGET(tree_view), "no_checkbox_mode"); -+ tree_view->priv->checkbox_mode = FALSE; -+ } -+ break; - default: - break; - } -@@ -1276,6 +1417,15 @@ - case PROP_HOVER_EXPAND: - g_value_set_boolean (value, tree_view->priv->hover_expand); - break; -+ case PROP_DOTTED_LINES: -+ g_value_set_boolean (value, tree_view->priv->dotted_lines); -+ break; -+ case PROP_FORCE_LIST_KLUDGE: -+ g_value_set_boolean (value, tree_view->priv->force_list_kludge); -+ break; -+ case PROP_ALLOW_CHECKBOX_MODE: -+ g_value_set_boolean (value, tree_view->priv->allow_checkbox_mode); -+ break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; -@@ -1376,6 +1526,27 @@ - tree_view->priv->destroy_count_data = NULL; - } - -+ if (tree_view->priv->first_drag_row) -+ { -+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row); -+ tree_view->priv->first_drag_row = NULL; -+ } -+ if (tree_view->priv->last_drag_row) -+ { -+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row); -+ tree_view->priv->last_drag_row = NULL; -+ } -+ if (tree_view->priv->queued_expand_row) -+ { -+ gtk_tree_row_reference_free (tree_view->priv->queued_expand_row); -+ tree_view->priv->queued_expand_row = NULL; -+ } -+ if (tree_view->priv->queued_select_row) -+ { -+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row); -+ tree_view->priv->queued_select_row = NULL; -+ } -+ - gtk_tree_row_reference_free (tree_view->priv->cursor); - tree_view->priv->cursor = NULL; - -@@ -1494,6 +1665,8 @@ - gtk_tree_view_map_buttons (tree_view); - - gdk_window_show (widget->window); -+ -+ check_if_can_focus (tree_view); - } - - static void -@@ -1895,6 +2068,8 @@ - gint full_requested_width = 0; - gint number_of_expand_columns = 0; - gboolean rtl; -+ GtkWidget *scroll; -+ GtkPolicyType ptype; - - tree_view = GTK_TREE_VIEW (widget); - -@@ -1969,6 +2144,19 @@ - allocation.x = width; - column->width = real_requested_width; - -+ /* a dirty Hildon hack to force truncation if not enough space. This hack is applied -+ * only if we are NOT in a scrolled window with hscroll*/ -+ scroll = gtk_widget_get_ancestor(widget, GTK_TYPE_SCROLLED_WINDOW); -+ if ((!scroll || -+ (gtk_scrolled_window_get_policy (GTK_SCROLLED_WINDOW (scroll), &ptype, NULL), ptype == GTK_POLICY_NEVER)) -+ && (width + real_requested_width > widget->allocation.width)) -+ { -+ column->width = widget->allocation.width - width; -+ if (column->width < 1) -+ column->width = 1; -+ gtk_widget_queue_draw (widget); -+ } -+ - if (column->expand) - { - if (number_of_expand_columns == 1) -@@ -2153,6 +2341,23 @@ - GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS); - } - -+/* helper function for gtk_tree_view_button_press */ -+static void -+activate_callback (GtkTreeModel *model, -+ GtkTreePath *path, -+ GtkTreeIter *iter, -+ gpointer data) -+{ -+ GtkTreeView *tree_view = GTK_TREE_VIEW (data); -+ -+ /* Hildon: if the tree view has no active focus we don't activate -+ * the selected row */ -+ if ( !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET(data)) ) -+ return; -+ -+ gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column); -+} -+ - static gboolean - gtk_tree_view_button_press (GtkWidget *widget, - GdkEventButton *event) -@@ -2166,6 +2371,7 @@ - gint vertical_separator; - gint horizontal_separator; - gboolean rtl; -+ gint expander_indent; - - g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); -@@ -2176,6 +2382,7 @@ - gtk_widget_style_get (widget, - "vertical_separator", &vertical_separator, - "horizontal_separator", &horizontal_separator, -+ "expander_indent", &expander_indent, - NULL); - - -@@ -2199,6 +2406,14 @@ - gint column_handled_click = FALSE; - gboolean row_double_click = FALSE; - gboolean rtl; -+ gboolean force_list_kludge; -+ GtkRBNode *cursor = NULL; -+ gboolean focus_grab = FALSE; -+ -+ if (!GTK_WIDGET_HAS_FOCUS (widget)) -+ focus_grab = TRUE; -+ -+ GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS); - - /* Empty tree? */ - if (tree_view->priv->tree == NULL) -@@ -2207,7 +2422,9 @@ - return TRUE; - } - -- /* are we in an arrow? */ -+ /* In Hildon we don't want to use the arrows */ -+#if 0 -+ /* are we in an arrow? */ - if (tree_view->priv->prelight_node && - GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT)) - { -@@ -2226,6 +2443,7 @@ - grab_focus_and_unset_draw_keyfocus (tree_view); - return TRUE; - } -+#endif - - /* find the node that was clicked */ - new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y); -@@ -2247,6 +2465,65 @@ - background_area.height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node)); - background_area.x = 0; - -+ if (tree_view->priv->first_drag_row) -+ { -+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row); -+ tree_view->priv->first_drag_row = NULL; -+ } -+ if (tree_view->priv->last_drag_row) -+ { -+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row); -+ tree_view->priv->last_drag_row = NULL; -+ } -+ tree_view->priv->first_drag_row = -+ gtk_tree_row_reference_new (tree_view->priv->model, path); -+ tree_view->priv->last_drag_row = gtk_tree_row_reference_copy (tree_view->priv->first_drag_row); -+ -+ /* force_list_kludge allows pen dragging even if -+ GTK_TREE_MODEL_LIST_ONLY is not set (to fix file tree) */ -+ g_object_get (widget, "force_list_kludge", &force_list_kludge, NULL); -+ -+ /* Hildon: activate pen dragging, if listbox is not hierarchical and -+ the pen was not put down in a position that initiates drag'n'drop */ -+ if (!tree_view->priv->pen_down && -+ (force_list_kludge || -+ (gtk_tree_model_get_flags(tree_view->priv->model) -+ & GTK_TREE_MODEL_LIST_ONLY)) && -+ (tree_view->priv->checkbox_mode || -+ !gtk_tree_selection_path_is_selected(tree_view->priv->selection, path))) -+ { -+ gpointer drag_data; -+ -+ tree_view->priv->pen_down = TRUE; -+ tree_view->priv->pen_focus = TRUE; -+ -+ /* also block attached dnd signal handler */ -+ drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); -+ if (drag_data) -+ g_signal_handlers_block_matched (widget, -+ G_SIGNAL_MATCH_DATA, -+ 0, 0, NULL, NULL, -+ drag_data); -+ } -+ -+ /* For the Hildon buttonpress find out the previously selected row */ -+ GtkRBTree *cursor_tree = NULL; -+ GtkTreePath *cursor_path = NULL; -+ -+ if (tree_view->priv->cursor) -+ { -+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); -+ if (cursor_path) -+ { -+ _gtk_tree_view_find_node (tree_view, cursor_path, -+ &cursor_tree, &cursor); -+ gtk_tree_path_free (cursor_path); -+ } -+ } -+ -+ /* Hildon: in checkbox mode, dragging sets all checkboxes -+ to the same state as the first toggled checkbox */ -+ tree_view->priv->new_state = !gtk_tree_selection_path_is_selected(tree_view->priv->selection, path); - - /* Let the column have a chance at selecting it. */ - rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL); -@@ -2275,8 +2552,11 @@ - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS(tree_view)) - { -- cell_area.x += depth * tree_view->priv->expander_size; -- cell_area.width -= depth * tree_view->priv->expander_size; -+ gint adjust; -+ -+ adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent; -+ cell_area.x += adjust; -+ cell_area.width -= adjust; - } - break; - } -@@ -2364,15 +2644,19 @@ - */ - if (event->type == GDK_BUTTON_PRESS) - { -+ /* Hildon: ignore Ctrl and Shift */ -+#if 0 - if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) - tree_view->priv->ctrl_pressed = TRUE; - if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) - tree_view->priv->shift_pressed = TRUE; -+#endif - - focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x); - if (focus_cell) - gtk_tree_view_column_focus_cell (column, focus_cell); - -+#if 0 - if (event->state & GDK_CONTROL_MASK) - { - gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE); -@@ -2387,6 +2671,86 @@ - { - gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE); - } -+#endif -+ if (tree_view->priv->checkbox_mode) -+ { -+ GtkRBTree *tree = NULL; -+ GtkRBNode *node = NULL; -+ -+ _gtk_tree_view_find_node (tree_view, path, &tree, &node); -+ -+ /* cursor cannot move to an insensitive row, so we -+ need to check here to avoid toggling the current -+ row by clicking on an insensitive row */ -+ if (_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ node, path)) -+ { -+ gtk_tree_view_real_set_cursor (tree_view, path, -+ FALSE, TRUE); -+ gtk_tree_view_real_toggle_cursor_row (tree_view); -+ } -+ else -+ /* Usually this would be emitted by real_set_cursor. -+ However in this case we never call it. */ -+ g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path); -+ } -+ else -+ { -+ gboolean queue_row = TRUE; -+ gboolean force_list_kludge; -+ -+ /* force_list_kludge allows rows to be activated even if -+ GTK_TREE_MODEL_LIST_ONLY is not set (to fix file tree) */ -+ g_object_get (widget, "force_list_kludge", -+ &force_list_kludge, NULL); -+ if ((force_list_kludge || -+ (gtk_tree_model_get_flags (tree_view->priv->model) & -+ GTK_TREE_MODEL_LIST_ONLY)) && -+ gtk_tree_row_reference_valid (tree_view->priv->cursor)) -+ { -+ /* special case: text listbox without checkboxes -+ should activate selected rows when user taps -+ on cursor row, but not affect selection*/ -+ GtkTreePath *cursor_path = -+ gtk_tree_row_reference_get_path (tree_view->priv->cursor); -+ if (gtk_tree_path_compare (cursor_path, path) == 0) -+ { -+ gtk_tree_selection_selected_foreach (tree_view->priv->selection, -+ activate_callback, -+ tree_view); -+ queue_row = FALSE; -+ } -+ } -+ -+ if (queue_row && -+ (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE) && -+ gtk_tree_selection_path_is_selected (tree_view->priv->selection, path)) -+ { -+ GtkTreePath *old_cursor_path = NULL; -+ -+ /* we don't know if the user is selecting an item or performing -+ multiple item drag and drop until we know where button is released */ -+ if (tree_view->priv->queued_select_row) -+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row); -+ tree_view->priv->queued_select_row = -+ gtk_tree_row_reference_new (tree_view->priv->model, path); -+ -+ /* however, move focus */ -+ if (tree_view->priv->cursor) -+ { -+ old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); -+ gtk_tree_row_reference_free (tree_view->priv->cursor); -+ } -+ tree_view->priv->cursor = gtk_tree_row_reference_new (tree_view->priv->model, -+ path); -+ gtk_tree_view_queue_draw_path (tree_view, path, NULL); -+ if (old_cursor_path) -+ gtk_tree_view_queue_draw_path (tree_view, old_cursor_path, NULL); -+ } -+ else -+ gtk_tree_view_real_set_cursor (tree_view, path, -+ queue_row, TRUE); -+ } - - tree_view->priv->ctrl_pressed = FALSE; - tree_view->priv->shift_pressed = FALSE; -@@ -2412,6 +2776,15 @@ - tree_view->priv->press_start_y = event->y; - } - -+ /* Hildon: if selected row is tapped -> the row gets activated and expands */ -+ if (!focus_grab) -+ { -+ /* ...although not until button is released */ -+ gtk_tree_row_reference_free (tree_view->priv->queued_expand_row); -+ tree_view->priv->queued_expand_row = -+ gtk_tree_row_reference_new (tree_view->priv->model, path); -+ } -+ - /* Test if a double click happened on the same row. */ - if (event->button == 1) - { -@@ -2433,6 +2806,8 @@ - } - } - -+ /* Hildon doesn't support double clicks */ -+#if 0 - if (row_double_click) - { - if (tree_view->priv->last_button_press) -@@ -2443,6 +2818,7 @@ - tree_view->priv->last_button_press_2 = NULL; - } - else -+#endif - { - if (tree_view->priv->last_button_press) - gtk_tree_row_reference_free (tree_view->priv->last_button_press); -@@ -2626,6 +3002,28 @@ - - tree_view = GTK_TREE_VIEW (widget); - -+ /* unblock attached dnd signal handler */ -+ if (tree_view->priv->pen_down) -+ { -+ gpointer drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); -+ if (drag_data) -+ g_signal_handlers_unblock_matched (widget, -+ G_SIGNAL_MATCH_DATA, -+ 0, 0, NULL, NULL, -+ drag_data); -+ } -+ -+ /* stop pen dragging */ -+ if (tree_view->priv->first_drag_row) -+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row); -+ if (tree_view->priv->last_drag_row) -+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row); -+ tree_view->priv->first_drag_row = NULL; -+ tree_view->priv->last_drag_row = NULL; -+ tree_view->priv->pen_down = FALSE; -+ tree_view->priv->pen_drag_active = FALSE; -+ remove_scroll_timeout (tree_view); -+ - if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG)) - return gtk_tree_view_button_release_drag_column (widget, event); - -@@ -2635,6 +3033,65 @@ - if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE)) - return gtk_tree_view_button_release_column_resize (widget, event); - -+ if (gtk_tree_row_reference_valid (tree_view->priv->queued_select_row)) -+ { -+ /* unselect other nodes - but only if not drag'n'dropping */ -+ if (event->window == tree_view->priv->bin_window) -+ gtk_tree_selection_unselect_all (tree_view->priv->selection); -+ -+ gtk_tree_view_real_set_cursor (tree_view, -+ gtk_tree_row_reference_get_path (tree_view->priv->queued_select_row), -+ FALSE, TRUE); -+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row); -+ tree_view->priv->queued_select_row = NULL; -+ } -+ -+ /* for handling expand/collapse postponed from button_press (since we -+ don't want expand/collapse before tap on node has been completed) */ -+ if (gtk_tree_row_reference_valid (tree_view->priv->queued_expand_row) && -+ tree_view->priv->tree != NULL) -+ { -+ GtkTreePath *queued_expand_path; -+ GtkRBTree *tree; -+ GtkRBNode *node; -+ GtkRBNode *old_node; -+ gint y; -+ -+ queued_expand_path = -+ gtk_tree_row_reference_get_path (tree_view->priv->queued_expand_row); -+ -+ if (queued_expand_path) -+ { -+ /* must check that cursor hasn't moved elsewhere since button_press */ -+ y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->y); -+ _gtk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node); -+ -+ _gtk_tree_view_find_node (tree_view, queued_expand_path, -+ &tree, &old_node); -+ -+ if (node && old_node == node) -+ { -+ if (node->children == NULL) -+ gtk_tree_view_real_expand_row (tree_view, -+ queued_expand_path, -+ tree, -+ node, -+ FALSE, TRUE); -+ else -+ gtk_tree_view_real_collapse_row (tree_view, -+ queued_expand_path, -+ tree, -+ node, -+ TRUE); -+ } -+ -+ gtk_tree_path_free (queued_expand_path); -+ } -+ -+ gtk_tree_row_reference_free( tree_view->priv->queued_expand_row); -+ tree_view->priv->queued_expand_row = NULL; -+ } -+ - if (tree_view->priv->button_pressed_node == NULL) - return FALSE; - -@@ -3311,6 +3768,7 @@ - GtkTreeView *tree_view; - GtkRBTree *tree; - GtkRBNode *node; -+ GtkTreePath *path, *last_drag_path, *current_path; - gint new_y; - - tree_view = (GtkTreeView *) widget; -@@ -3319,7 +3777,8 @@ - return FALSE; - - /* only check for an initiated drag when a button is pressed */ -- if (tree_view->priv->pressed_button >= 0) -+ /* Hildon: active pen drag overrides drag and drop */ -+ if (tree_view->priv->pressed_button >= 0 && !tree_view->priv->pen_down) - gtk_tree_view_maybe_begin_dragging_row (tree_view, event); - - new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y); -@@ -3328,6 +3787,99 @@ - - _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node); - -+ /* Hildon: pen dragging */ -+ if (tree_view->priv->pen_down && node != NULL && -+ tree_view->priv->queued_select_row == NULL && -+ gtk_tree_row_reference_valid (tree_view->priv->last_drag_row)) -+ { -+ gint direction; -+ -+ last_drag_path = gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row); -+ path = _gtk_tree_view_find_path (tree_view, tree, node); -+ direction = gtk_tree_path_compare (path, last_drag_path); -+ -+ if (direction != 0) -+ { -+ current_path = gtk_tree_path_copy (last_drag_path); -+ -+ /* we must ensure that no row is skipped because stylus -+ is moving faster than motion events are generated */ -+ do { -+ if (direction > 0) -+ { -+ /* gtk_tree_path_next does not let us know when it failed */ -+ GtkTreeIter iter; -+ gtk_tree_model_get_iter (tree_view->priv->model, &iter, current_path); -+ if (!gtk_tree_model_iter_next (tree_view->priv->model, &iter)) -+ break; -+ -+ gtk_tree_path_next (current_path); -+ } -+ else if (!gtk_tree_path_prev (current_path)) -+ break; -+ -+ /* set cursor, and start scrolling */ -+ gtk_tree_view_real_set_cursor (tree_view, current_path, FALSE, FALSE); -+ add_scroll_timeout (tree_view); -+ -+ if (tree_view->priv->checkbox_mode) -+ { -+ /* always set to same state as the first tapped node */ -+ if (tree_view->priv->new_state) -+ gtk_tree_selection_select_path (tree_view->priv->selection, -+ current_path); -+ else -+ gtk_tree_selection_unselect_path (tree_view->priv->selection, -+ current_path); -+ } -+ else -+ { -+ if (gtk_tree_selection_path_is_selected (tree_view->priv->selection, -+ current_path)) -+ { -+ /* apparently we have reversed the pen drag direction */ -+ GtkTreePath *reverse_path; -+ gint reverse_direction; -+ -+ reverse_direction = gtk_tree_path_compare (current_path, -+ last_drag_path); -+ reverse_path = gtk_tree_path_copy (last_drag_path); -+ do { -+ gtk_tree_selection_unselect_path (tree_view->priv->selection, -+ reverse_path); -+ tree_view->priv->pen_drag_reverse = TRUE; -+ if (reverse_direction > 0) -+ { -+ GtkTreeIter iter; -+ gtk_tree_model_get_iter (tree_view->priv->model, &iter, reverse_path); -+ if (!gtk_tree_model_iter_next (tree_view->priv->model, &iter)) -+ break; -+ -+ gtk_tree_path_next (reverse_path); -+ } -+ else if (!gtk_tree_path_prev (reverse_path)) -+ break; -+ } while (gtk_tree_path_compare (reverse_path, current_path) != 0); -+ gtk_tree_path_free (reverse_path); -+ } -+ else -+ { -+ gtk_tree_selection_select_path (tree_view->priv->selection, -+ current_path); -+ tree_view->priv->pen_drag_reverse = FALSE; -+ } -+ } -+ } while (gtk_tree_path_compare(current_path, path) != 0); -+ gtk_tree_path_free (current_path); -+ -+ /* update last_drag_row */ -+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row); -+ tree_view->priv->last_drag_row = -+ gtk_tree_row_reference_new (tree_view->priv->model, path); -+ gtk_tree_path_free (path); -+ } -+ } -+ - /* If we are currently pressing down a button, we don't want to prelight anything else. */ - if ((tree_view->priv->button_pressed_node != NULL) && - (tree_view->priv->button_pressed_node != node)) -@@ -3404,6 +3956,22 @@ - 1, 1, w, h); - } - -+/* Hildon: helper function for dotted slash drawing; -+ returns TRUE or FALSE, depending it there are -+ more nodes at current level */ -+static gboolean -+iter_has_next (GtkTreeModel *model, GtkTreeIter *iter) -+{ -+ GtkTreeIter *check_iter; -+ gboolean result; -+ -+ check_iter = gtk_tree_iter_copy(iter); -+ result = gtk_tree_model_iter_next (model, check_iter); -+ -+ gtk_tree_iter_free (check_iter); -+ return result; -+} -+ - /* Warning: Very scary function. - * Modify at your own risk - * -@@ -3433,16 +4001,25 @@ - guint flags; - gint highlight_x; - gint bin_window_width; -- GtkTreePath *cursor_path; -- GtkTreePath *drag_dest_path; -+ GtkTreePath *cursor_path = NULL; -+ GtkTreePath *drag_dest_path = NULL; - GList *last_column; - gint vertical_separator; - gint horizontal_separator; -+ gint expander_indent; - gint focus_line_width; - gboolean allow_rules; - gboolean has_special_cell; - gboolean rtl; - gint n_visible_columns; -+ gboolean dottedlines, passivefocus, res; -+ -+ /* Hildon: these variables are added for dotted slash drawing -+ (Hierarchical listbox) */ -+ gint i; -+ gint node_elements = 64; -+ gboolean *iter_value = NULL; -+ GtkTreeIter node_iter, parent_iter; - - g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE); - -@@ -3455,8 +4032,12 @@ - "vertical_separator", &vertical_separator, - "allow_rules", &allow_rules, - "focus-line-width", &focus_line_width, -+ "expander_indent", &expander_indent, -+ "passive_focus", &passivefocus, - NULL); - -+ g_object_get (widget, "dotted_lines", &dottedlines, NULL); -+ - if (tree_view->priv->tree == NULL) - { - draw_empty_focus (tree_view, &event->area); -@@ -3478,6 +4059,8 @@ - if (node == NULL) - return TRUE; - -+ iter_value = g_new (gboolean, node_elements); -+ - /* find the path for the node */ - path = _gtk_tree_view_find_path ((GtkTreeView *)widget, - tree, -@@ -3486,11 +4069,25 @@ - &iter, - path); - depth = gtk_tree_path_get_depth (path); -+ -+ node_iter = iter; -+ for (i = depth - 1; i >= 1; i--) -+ { -+ res = gtk_tree_model_iter_parent (tree_view->priv->model, &parent_iter, &node_iter); -+ /* Check, if we should grow array */ -+ if (i >= node_elements - 1) -+ { -+ node_elements *= 2; -+ iter_value = g_renew (gboolean, iter_value, node_elements); -+ if (!iter_value) -+ goto done; -+ } -+ iter_value[i] = iter_has_next (tree_view->priv->model, &parent_iter); -+ node_iter = parent_iter; -+ } -+ gtk_tree_model_get_iter (tree_view->priv->model, &iter, path); - gtk_tree_path_free (path); - -- cursor_path = NULL; -- drag_dest_path = NULL; -- - if (tree_view->priv->cursor) - cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); - -@@ -3533,6 +4130,7 @@ - do - { - gboolean parity; -+ gboolean is_first = TRUE; - gboolean is_separator = FALSE; - - if (tree_view->priv->row_separator_func) -@@ -3570,6 +4168,7 @@ - GtkTreeViewColumn *column = list->data; - const gchar *detail = NULL; - GtkStateType state; -+ gboolean is_last = (rtl ? !list->prev : !list->next); - - if (!column->visible) - continue; -@@ -3660,31 +4259,152 @@ - else - state = GTK_STATE_NORMAL; - -- /* Draw background */ -- gtk_paint_flat_box (widget->style, -- event->window, -- state, -- GTK_SHADOW_NONE, -- &event->area, -- widget, -- detail, -- background_area.x, -- background_area.y, -- background_area.width, -- background_area.height); -+ if (tree_view->priv->pen_focus) -+ { -+ if (node != cursor || -+ (!GTK_WIDGET_HAS_FOCUS (widget) && !passivefocus)) -+ { -+ if ((flags & GTK_CELL_RENDERER_SELECTED) -+ && !tree_view->priv->checkbox_mode) -+ state = GTK_STATE_SELECTED; -+ else -+ state = GTK_STATE_NORMAL; -+ -+ /* Draw background */ -+ gtk_paint_flat_box (widget->style, -+ event->window, -+ state, -+ GTK_SHADOW_NONE, -+ &event->area, -+ widget, -+ detail, -+ background_area.x, -+ background_area.y, -+ background_area.width, -+ background_area.height); -+ } -+ else if ((flags & GTK_CELL_RENDERER_SELECTED) && -+ !tree_view->priv->checkbox_mode && -+ node != cursor) -+ { -+ gtk_paint_flat_box (widget->style, -+ event->window, -+ GTK_STATE_SELECTED, -+ GTK_SHADOW_NONE, -+ &event->area, -+ widget, -+ detail, -+ background_area.x, -+ background_area.y, -+ background_area.width, -+ background_area.height); -+ } -+ } -+ else -+ { -+ /* Draw background */ -+ gtk_paint_flat_box (widget->style, -+ event->window, -+ state, -+ GTK_SHADOW_NONE, -+ &event->area, -+ widget, -+ detail, -+ background_area.x, -+ background_area.y, -+ background_area.width, -+ background_area.height); -+ } -+ -+ /* Hildon change: drawing focus is moved here because it didn't work -+ properly before. Some changes where also made.*/ -+ /* draw the big row-spanning focus rectangle, if needed */ -+ if (node == cursor && -+ (!passivefocus || GTK_WIDGET_HAS_FOCUS (widget))) -+ { -+ gtk_paint_focus (widget->style, -+ event->window, -+ GTK_STATE_ACTIVE, -+ &event->area, -+ widget, -+ (is_first -+ ? (is_last ? "full" : "left") -+ : (is_last ? "right" : "middle")), -+ background_area.x - (is_first ? 0 : horizontal_separator / 2), -+ background_area.y - vertical_separator / 2, -+ background_area.width + (is_first ? 0 : (is_last ? horizontal_separator / 2 : horizontal_separator)), -+ background_area.height + vertical_separator); -+ -+ is_first = FALSE; -+ } -+ else if (node == cursor && passivefocus && -+ !GTK_WIDGET_HAS_FOCUS (widget)) -+ { -+ GtkStyle *style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget), -+ "hildon-focus", -+ NULL, -+ G_TYPE_NONE); -+ gtk_style_attach (style, event->window); -+ -+ gtk_paint_focus (style, event->window, GTK_STATE_SELECTED, -+ &event->area, widget, -+ (is_first -+ ? (is_last ? "full" : "left") -+ : (is_last ? "right" : "middle")), -+ background_area.x - (is_first ? 0 : horizontal_separator / 2), -+ background_area.y - vertical_separator / 2, -+ background_area.width + (is_first ? 0 : (is_last ? horizontal_separator / 2 : horizontal_separator)), -+ background_area.height + vertical_separator); -+ -+ is_first = FALSE; -+ } -+ -+ if (node == cursor) -+ { -+ gint width, x_offset; -+ GtkStateType focus_rect_state; -+ focus_rect_state = -+ flags & GTK_CELL_RENDERER_FOCUSED ? GTK_STATE_ACTIVE : -+ (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT : -+ (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE : -+ (flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED : -+ GTK_STATE_NORMAL))); -+ -+ gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL); -+ gdk_drawable_get_size (tree_view->priv->bin_window, &width, NULL); -+ } - - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS(tree_view)) - { -+ gint px, px2, py, i; -+ -+ if (depth <= 1) -+ px = 0; -+ else -+ px = (depth - 1) * tree_view->priv->expander_size + -+ (depth - 2) * expander_indent; -+ -+ /* Hildonlike hack for making the indent look better. -+ * indent is added to all rows except the first one */ -+ - if (!rtl) -- cell_area.x += depth * tree_view->priv->expander_size; -- cell_area.width -= depth * tree_view->priv->expander_size; -+ cell_area.x += depth * tree_view->priv->expander_size + (depth-1) * expander_indent; -+ cell_area.width -= depth * tree_view->priv->expander_size + (depth-1) * expander_indent; - - /* If we have an expander column, the highlight underline - * starts with that column, so that it indicates which - * level of the tree we're dropping at. - */ - highlight_x = cell_area.x; -+ -+ if (!GTK_WIDGET_IS_SENSITIVE (widget)) -+ { -+ flags &= ~ (GTK_CELL_RENDERER_PRELIT + GTK_CELL_RENDERER_INSENSITIVE + -+ GTK_CELL_RENDERER_FOCUSED); -+ flags &= GTK_CELL_RENDERER_INSENSITIVE; -+ } -+ - if (is_separator) - gtk_paint_hline (widget->style, - event->window, -@@ -3702,6 +4422,48 @@ - &cell_area, - &event->area, - flags); -+ -+ /* Hildon dotted slash line drawing for Hierarchical Listbox -+ widget */ -+ if (dottedlines) -+ { -+ py = cell_area.y + cell_area.height / 2; -+ px2 = depth * tree_view->priv->expander_size + -+ (depth - 1) * expander_indent; -+ -+ gdk_gc_set_line_attributes (widget->style->fg_gc[GTK_WIDGET_STATE (widget)], -+ 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL); -+ -+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], -+ px, py, px2, py); -+ -+ if (depth > 1) -+ { -+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], -+ px, cell_area.y, px, py); -+ if (iter_has_next (tree_view->priv->model, &iter)) -+ { -+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], -+ px, py, px, cell_area.y + cell_area.height); -+ } -+ } -+ -+ if (node->children) -+ { -+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], -+ px2, py, px2, cell_area.y + cell_area.height); -+ } -+ for (i = depth - 1; i >= 2; i--) -+ { -+ if (iter_value[i]) -+ { -+ px = (i - 1)* tree_view->priv->expander_size + (i - 2) * expander_indent; -+ gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], -+ px, cell_area.y, px, cell_area.y + cell_area.height); -+ } -+ } -+ } -+ - if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT) - { - gint x, y; -@@ -3803,6 +4565,8 @@ - } - } - -+ /* Hildon: disabled this */ -+#if 0 - /* draw the big row-spanning focus rectangle, if needed */ - if (!has_special_cell && node == cursor && - GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) && -@@ -3830,6 +4594,7 @@ - width, - ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))); - } -+#endif - - y_offset += max_height; - if (node->children) -@@ -3847,6 +4612,17 @@ - has_child = gtk_tree_model_iter_children (tree_view->priv->model, - &iter, - &parent); -+ -+ /* Check if we need to grow array */ -+ if (depth >= node_elements - 1) -+ { -+ node_elements *= 2; -+ iter_value = g_renew (gboolean, iter_value, node_elements); -+ if (!iter_value) -+ goto done; -+ } -+ iter_value[depth] = iter_has_next (tree_view->priv->model, &parent); -+ - depth++; - - /* Sanity Check! */ -@@ -3897,6 +4673,9 @@ - if (drag_dest_path) - gtk_tree_path_free (drag_dest_path); - -+ if (iter_value) -+ g_free (iter_value); -+ - return FALSE; - } - -@@ -4179,6 +4958,63 @@ - - rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL); - -+ /* Special Hildon keyboard interactions */ -+ if (event->keyval == GDK_Escape) -+ gtk_tree_selection_unselect_all (tree_view->priv->selection); -+ -+ if (event->keyval == GDK_Return && -+ gtk_tree_row_reference_valid (tree_view->priv->cursor)) -+ { -+ gboolean force_list_kludge; -+ -+ g_object_get (widget, "force_list_kludge", &force_list_kludge, NULL); -+ if (force_list_kludge || -+ (gtk_tree_model_get_flags (tree_view->priv->model) & -+ GTK_TREE_MODEL_LIST_ONLY)) -+ { -+ /* text listbox */ -+ if (tree_view->priv->checkbox_mode) -+ { -+ /* multisel with checkboxes: select key toggles focused */ -+ gtk_tree_view_real_toggle_cursor_row (tree_view); -+ } -+ else -+ { -+ /* no checkboxes: select key activates focused */ -+ GtkTreePath *cursor_path = -+ gtk_tree_row_reference_get_path (tree_view->priv->cursor); -+ -+ gtk_tree_view_row_activated (tree_view, cursor_path, -+ tree_view->priv->focus_column); -+ -+ gtk_tree_path_free (cursor_path); -+ } -+ } -+ else -+ { -+ /* hierarchical listbox */ -+ GtkTreePath *cursor_path; -+ GtkRBTree *tree; -+ GtkRBNode *node; -+ -+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); -+ _gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node); -+ -+ if (node->children == NULL) -+ gtk_tree_view_real_expand_row (tree_view, -+ cursor_path, -+ tree, -+ node, -+ FALSE, TRUE); -+ else -+ gtk_tree_view_real_collapse_row (tree_view, -+ cursor_path, -+ tree, -+ node, -+ TRUE); -+ } -+ } -+ - if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG)) - { - if (event->keyval == GDK_Escape) -@@ -4420,6 +5256,7 @@ - - /* FIXME Is this function necessary? Can I get an enter_notify event - * w/o either an expose event or a mouse motion event? -+ * Hildon => it is necessary to make pen dragging work correctly - */ - static gboolean - gtk_tree_view_enter_notify (GtkWidget *widget, -@@ -4434,6 +5271,10 @@ - - tree_view = GTK_TREE_VIEW (widget); - -+ /* stop "automatic" pen dragging */ -+ tree_view->priv->pen_drag_active = FALSE; -+ remove_scroll_timeout (tree_view); -+ - /* Sanity check it */ - if (event->window != tree_view->priv->bin_window) - return FALSE; -@@ -4463,6 +5304,9 @@ - tree_view = GTK_TREE_VIEW (widget); - tree_view->priv->pressed_button = -1; - -+ if (tree_view->priv->pen_down && tree_view->priv->queued_select_row == NULL) -+ tree_view->priv->pen_drag_active = TRUE; -+ - if (event->mode == GDK_CROSSING_GRAB) - return TRUE; - -@@ -4535,6 +5379,7 @@ - gboolean retval = FALSE; - gboolean is_separator = FALSE; - gint focus_pad; -+ gint expander_indent; - - /* double check the row needs validating */ - if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) && -@@ -4551,6 +5396,7 @@ - gtk_widget_style_get (GTK_WIDGET (tree_view), - "focus-padding", &focus_pad, - "horizontal_separator", &horizontal_separator, -+ "expander_indent", &expander_indent, - NULL); - - for (list = tree_view->priv->columns; list; list = list->next) -@@ -4577,13 +5423,16 @@ - { - height = MAX (height, tmp_height); - height = MAX (height, tree_view->priv->expander_size); -+ -+ /* Hildon addition */ -+ height -= 1; - } - else - height = 2 + 2 * focus_pad; - - if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view)) - { -- tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size); -+ tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size) + (depth - 1) * expander_indent; - } - else - tmp_width = tmp_width + horizontal_separator; -@@ -5585,6 +6434,16 @@ - #endif /* 0 */ - - static void -+add_scroll_timeout (GtkTreeView *tree_view) -+{ -+ if (tree_view->priv->scroll_timeout == 0) -+ { -+ tree_view->priv->scroll_timeout = -+ g_timeout_add (150, scroll_row_timeout, tree_view); -+ } -+} -+ -+static void - remove_scroll_timeout (GtkTreeView *tree_view) - { - if (tree_view->priv->scroll_timeout != 0) -@@ -6130,10 +6989,9 @@ - tree_view->priv->open_dest_timeout = - g_timeout_add (AUTO_EXPAND_TIMEOUT, open_row_timeout, tree_view); - } -- else if (tree_view->priv->scroll_timeout == 0) -+ else - { -- tree_view->priv->scroll_timeout = -- g_timeout_add (150, scroll_row_timeout, tree_view); -+ add_scroll_timeout (tree_view); - } - - if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) -@@ -6901,8 +7759,6 @@ - GtkMovementStep step, - gint count) - { -- GdkModifierType state; -- - g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE); - g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS || - step == GTK_MOVEMENT_VISUAL_POSITIONS || -@@ -6919,6 +7775,8 @@ - GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS); - gtk_widget_grab_focus (GTK_WIDGET (tree_view)); - -+ /* Hildon: Ignore ctrl and shift */ -+#if 0 - if (gtk_get_current_event_state (&state)) - { - if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) -@@ -6926,6 +7784,7 @@ - if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) - tree_view->priv->shift_pressed = TRUE; - } -+#endif - /* else we assume not pressed */ - - switch (step) -@@ -7092,6 +7951,27 @@ - done: - if (!tree_view->priv->fixed_height_mode) - install_presize_handler (tree_view); -+ -+ /* Hildon: has row now been dimmed? If so, unselect it */ -+ _gtk_tree_view_find_node (tree_view, path, &tree, &node); -+ if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ node, -+ path)) -+ { -+ if (gtk_tree_path_compare (path, -+ gtk_tree_row_reference_get_path(tree_view->priv->cursor)) -+ == 0) -+ { -+ gtk_tree_row_reference_free (tree_view->priv->cursor); -+ tree_view->priv->cursor = NULL; -+ } -+ -+ gtk_tree_selection_unselect_path (tree_view->priv->selection, path); -+ gtk_tree_view_collapse_row (tree_view, path); -+ } -+ -+ check_if_can_focus (tree_view); -+ - if (free_path) - gtk_tree_path_free (path); - } -@@ -7196,6 +8076,11 @@ - install_presize_handler (tree_view); - if (free_path) - gtk_tree_path_free (path); -+ -+ /* Hildon: after a focusable row has been added, the -+ entire widget becomes focusable if it wasn't before */ -+ if ((GTK_WIDGET_FLAGS (tree_view) & GTK_CAN_FOCUS) == 0) -+ check_if_can_focus (tree_view); - } - - static void -@@ -7295,6 +8180,16 @@ - _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data); - } - -+static gboolean -+check_if_can_focus_idle (GtkTreeView *tree_view) -+{ -+ check_if_can_focus (tree_view); -+ -+ tree_view->priv->check_if_can_focus_idle_id = 0; -+ -+ return FALSE; -+} -+ - static void - gtk_tree_view_row_deleted (GtkTreeModel *model, - GtkTreePath *path, -@@ -7357,6 +8252,11 @@ - tree_view->priv->tree = NULL; - - _gtk_rbtree_remove (tree); -+ -+ /* Hildon: no nodes -> not focusable */ -+ /* FIXME this looks superfluos to me. check_if_can_focus is called -+ * at the end of this function .. -- Jorn */ -+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS); - } - else - { -@@ -7375,6 +8275,13 @@ - - if (selection_changed) - g_signal_emit_by_name (tree_view->priv->selection, "changed"); -+ -+ /* FIXME whacky hack to work around the treeview not being in a clean state -+ * when in a tree a row has been removed, but has_child_toggled not been -+ * called yet */ -+ if (tree_view->priv->check_if_can_focus_idle_id == 0) -+ tree_view->priv->check_if_can_focus_idle_id = -+ g_idle_add ((GSourceFunc) check_if_can_focus_idle, tree_view); - } - - static void -@@ -7508,6 +8415,7 @@ - GList *list; - GtkTreeViewColumn *tmp_column = NULL; - gint total_width; -+ gint expander_indent, depth; - gboolean indent_expanders; - gboolean rtl; - -@@ -7535,14 +8443,19 @@ - - gtk_widget_style_get (GTK_WIDGET (tree_view), - "indent_expanders", &indent_expanders, -+ "expander_indent", &expander_indent, - NULL); - -+ /* Hildonlike hack for making the indent look better. -+ * indent is added to all rows except the first one */ -+ depth = _gtk_rbtree_get_depth (tree); -+ - if (indent_expanders) - { - if (rtl) -- x_offset -= tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree); -+ x_offset -= tree_view->priv->expander_size * depth + (depth) * expander_indent; - else -- x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree); -+ x_offset += tree_view->priv->expander_size * depth + (depth) * expander_indent; - } - if (x1) - { -@@ -7617,9 +8530,11 @@ - gboolean retval = FALSE; - gint tmpheight; - gint horizontal_separator; -+ gint expander_indent; - - gtk_widget_style_get (GTK_WIDGET (tree_view), - "horizontal_separator", &horizontal_separator, -+ "expander_indent", &expander_indent, - NULL); - - if (height) -@@ -7657,7 +8572,7 @@ - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS (tree_view)) - { -- if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width) -+ if ((depth - 1) *expander_indent + depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width) - { - _gtk_tree_view_column_cell_set_dirty (column, TRUE); - retval = TRUE; -@@ -7747,6 +8662,7 @@ - } - } - -+#if 0 - static void - gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view, - GtkTreeViewColumn *column) -@@ -7762,6 +8678,7 @@ - gtk_adjustment_set_value (tree_view->priv->hadjustment, - column->button->allocation.x); - } -+#endif - - /* This function could be more efficient. I'll optimize it if profiling seems - * to imply that it is important */ -@@ -8290,7 +9207,7 @@ - - area.x = x_offset; - area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator); -- area.width = expander_size + 2; -+ area.width = expander_size; - area.height = MAX (CELL_HEIGHT (node, vertical_separator), (expander_size - vertical_separator)); - - if (node == tree_view->priv->button_pressed_node) -@@ -8397,7 +9314,10 @@ - GtkRBNode *cursor_node = NULL; - GtkRBTree *new_cursor_tree = NULL; - GtkRBNode *new_cursor_node = NULL; -+ GtkRBTree *old_cursor_tree; -+ GtkRBNode *old_cursor_node; - GtkTreePath *cursor_path = NULL; -+ GtkTreePath *new_cursor_path = NULL; - - if (! GTK_WIDGET_HAS_FOCUS (tree_view)) - return; -@@ -8415,12 +9335,30 @@ - if (cursor_tree == NULL) - /* FIXME: we lost the cursor; should we get the first? */ - return; -- if (count == -1) -- _gtk_rbtree_prev_full (cursor_tree, cursor_node, -- &new_cursor_tree, &new_cursor_node); -- else -- _gtk_rbtree_next_full (cursor_tree, cursor_node, -- &new_cursor_tree, &new_cursor_node); -+ -+ old_cursor_tree = cursor_tree; -+ old_cursor_node = cursor_node; -+ do { -+ if (count == -1) -+ _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node, -+ &new_cursor_tree, &new_cursor_node); -+ else -+ _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node, -+ &new_cursor_tree, &new_cursor_node); -+ -+ if (new_cursor_node) -+ { -+ if (new_cursor_path) -+ gtk_tree_path_free (new_cursor_path); -+ -+ new_cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node); -+ old_cursor_tree = new_cursor_tree; -+ old_cursor_node = new_cursor_node; -+ } -+ } while (new_cursor_node && -+ !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ new_cursor_node, -+ new_cursor_path)); - - /* - * If the list has only one item and multi-selection is set then select -@@ -8450,7 +9388,33 @@ - if (new_cursor_node) - { - cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node); -- gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE); -+ -+ if (tree_view->priv->checkbox_mode) -+ gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, TRUE); -+ else -+ gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE); -+ -+ if (tree_view->priv->pen_drag_active) -+ { -+ if (gtk_tree_path_compare (gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row), -+ gtk_tree_row_reference_get_path (tree_view->priv->first_drag_row)) == 0) -+ tree_view->priv->pen_drag_reverse = FALSE; -+ -+ if (tree_view->priv->pen_drag_reverse) -+ { -+ gtk_tree_selection_select_path (tree_view->priv->selection, -+ cursor_path); -+ gtk_tree_selection_unselect_path (tree_view->priv->selection, -+ gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row)); -+ } -+ -+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row); -+ -+ tree_view->priv->last_drag_row = -+ gtk_tree_row_reference_new (tree_view->priv->model, -+ cursor_path); -+ } -+ - gtk_tree_path_free (cursor_path); - } - else -@@ -8467,6 +9431,8 @@ - { - GtkRBTree *cursor_tree = NULL; - GtkRBNode *cursor_node = NULL; -+ GtkRBTree *old_cursor_tree = NULL; -+ GtkRBNode *old_cursor_node = NULL; - GtkTreePath *cursor_path = NULL; - gint y; - gint vertical_separator; -@@ -8474,6 +9440,9 @@ - if (! GTK_WIDGET_HAS_FOCUS (tree_view)) - return; - -+ if (tree_view->priv->tree == NULL) -+ return; -+ - if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) - cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); - else -@@ -8504,7 +9473,65 @@ - - _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node); - cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); -- g_return_if_fail (cursor_path != NULL); -+ -+ while (cursor_node && -+ !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ cursor_node, -+ cursor_path)) -+ { -+ old_cursor_tree = cursor_tree; -+ old_cursor_node = cursor_node; -+ -+ if (count < 0) -+ _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node, -+ &cursor_tree, &cursor_node); -+ else -+ _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node, -+ &cursor_tree, &cursor_node); -+ -+ if (cursor_path) -+ { -+ gtk_tree_path_free(cursor_path); -+ cursor_path = NULL; -+ } -+ -+ if (cursor_node) -+ cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); -+ } -+ -+ if (cursor_path == NULL) -+ { -+ /* looks like we reached the end without finding a sensitive row, -+ so search backwards and try to find the last sensitive row as -+ the next best thing */ -+ _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node); -+ cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); -+ while (cursor_node && -+ !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ cursor_node, -+ cursor_path)) -+ { -+ old_cursor_tree = cursor_tree; -+ old_cursor_node = cursor_node; -+ -+ if (count < 0) -+ _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node, -+ &cursor_tree, &cursor_node); -+ else -+ _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node, -+ &cursor_tree, &cursor_node); -+ -+ if (cursor_path) -+ { -+ gtk_tree_path_free(cursor_path); -+ cursor_path = NULL; -+ } -+ -+ if (cursor_node) -+ cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); -+ } -+ } -+ - gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE); - gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node); - gtk_tree_path_free (cursor_path); -@@ -8514,6 +9541,8 @@ - gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view, - gint count) - { -+ /* Hildon: cursor is always displayed on an entire row anyway */ -+#if 0 - GtkRBTree *cursor_tree = NULL; - GtkRBNode *cursor_node = NULL; - GtkTreePath *cursor_path = NULL; -@@ -8589,12 +9618,15 @@ - g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0); - } - gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column); -+#endif - } - - static void - gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view, - gint count) - { -+ /* Hildon: cursor is always displayed on an entire row anyway */ -+#if 0 - GtkRBTree *cursor_tree; - GtkRBNode *cursor_node; - GtkTreePath *path; -@@ -8631,6 +9663,7 @@ - path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); - gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE); - gtk_tree_path_free (path); -+#endif - } - - static gboolean -@@ -8670,7 +9703,7 @@ - GtkTreePath *cursor_path = NULL; - GtkTreeSelectMode mode = 0; - -- if (! GTK_WIDGET_HAS_FOCUS (tree_view)) -+ if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode) - return FALSE; - - if (tree_view->priv->cursor) -@@ -8731,7 +9764,7 @@ - GtkRBNode *cursor_node = NULL; - GtkTreePath *cursor_path = NULL; - -- if (! GTK_WIDGET_HAS_FOCUS (tree_view)) -+ if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode) - return FALSE; - - cursor_path = NULL; -@@ -8774,6 +9807,7 @@ - GtkTreePath *cursor_path = NULL; - GtkRBTree *tree; - GtkRBNode *node; -+ gboolean hildon_row; - - if (! GTK_WIDGET_HAS_FOCUS (tree_view)) - return FALSE; -@@ -8796,10 +9830,32 @@ - && 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); -+ /* Keyboard Navigation: if we can't expand/collapse row, we should either move active focus -+ to child item (right arrow) or move active focus to the parent item (left arrow) */ -+ if (expand) -+ { -+ hildon_row = gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, -+ node, open_all, TRUE); -+ -+ if (!hildon_row || !node->children) -+ g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET (tree_view), -+ GTK_TYPE_WINDOW), -+ "move_focus", -+ GTK_DIR_TAB_FORWARD); -+ } - else -- gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE); -+ { -+ hildon_row = gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE); -+ -+ if (hildon_row == FALSE) -+ { -+ g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET(tree_view), -+ GTK_TYPE_WINDOW), -+ "move_focus", -+ GTK_DIR_TAB_BACKWARD); -+ gtk_tree_view_real_select_cursor_parent (tree_view); -+ } -+ } - - gtk_tree_path_free (cursor_path); - -@@ -9327,6 +10383,14 @@ - tree_view->priv->last_button_press_2 = NULL; - gtk_tree_row_reference_free (tree_view->priv->scroll_to_path); - tree_view->priv->scroll_to_path = NULL; -+ gtk_tree_row_reference_free (tree_view->priv->first_drag_row); -+ tree_view->priv->first_drag_row = NULL; -+ gtk_tree_row_reference_free (tree_view->priv->last_drag_row); -+ tree_view->priv->last_drag_row = NULL; -+ gtk_tree_row_reference_free (tree_view->priv->queued_expand_row); -+ tree_view->priv->queued_expand_row = NULL; -+ gtk_tree_row_reference_free (tree_view->priv->queued_select_row); -+ tree_view->priv->queued_select_row = NULL; - - tree_view->priv->scroll_to_column = NULL; - -@@ -9402,6 +10466,8 @@ - install_presize_handler (tree_view); - } - -+ check_if_can_focus (tree_view); -+ - g_object_notify (G_OBJECT (tree_view), "model"); - - if (GTK_WIDGET_REALIZED (tree_view)) -@@ -9744,6 +10810,10 @@ - G_CALLBACK (column_sizing_notify), - tree_view); - -+ g_signal_handlers_disconnect_by_func (column, -+ G_CALLBACK (update_checkbox_mode), -+ tree_view); -+ - _gtk_tree_view_column_unset_tree_view (column); - - tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column); -@@ -9773,6 +10843,8 @@ - g_object_unref (column); - g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0); - -+ update_checkbox_mode (NULL, NULL, tree_view); -+ - return tree_view->priv->n_columns; - } - -@@ -9815,6 +10887,9 @@ - g_signal_connect (column, "notify::sizing", - G_CALLBACK (column_sizing_notify), tree_view); - -+ g_signal_connect (column, "notify::visible", -+ G_CALLBACK (update_checkbox_mode), tree_view); -+ - tree_view->priv->columns = g_list_insert (tree_view->priv->columns, - column, position); - tree_view->priv->n_columns++; -@@ -9838,6 +10913,9 @@ - - g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0); - -+ update_checkbox_mode (NULL, NULL, tree_view); -+ check_if_can_focus (tree_view); -+ - return tree_view->priv->n_columns; - } - -@@ -10295,7 +11373,6 @@ - GtkTreeViewColumn *column) - { - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); -- - g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column); - } - -@@ -10560,6 +11637,16 @@ - GtkTreeIter iter; - GtkTreeIter temp; - gboolean expand; -+ gint vertical_separator; -+ GtkTreePath *collapse_path; -+ GtkRBTree *tree2; -+ GtkRBNode *node2; -+ GtkTreePath *child_path = NULL; -+ GtkTreeIter parent_iter; -+ GtkTreeIter child_iter; -+ GdkRectangle visible_rect; -+ gint children, n; -+ guint total_height; - - remove_auto_expand_timeout (tree_view); - -@@ -10573,8 +11660,12 @@ - if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter)) - return FALSE; - -+ /* Hildon: insensitive rows cannot be expanded */ -+ if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ node, path)) -+ return FALSE; - -- if (node->children && open_all) -+ if (node->children && open_all) - { - gboolean retval = FALSE; - GtkTreePath *tmp_path = gtk_tree_path_copy (path); -@@ -10603,6 +11694,37 @@ - return retval; - } - -+ /* Hildon: collapse other items in the same level */ -+ gtk_widget_style_get (GTK_WIDGET (tree_view), -+ "vertical_separator", &vertical_separator, NULL); -+ -+ /* find the first child */ -+ collapse_path = gtk_tree_path_copy (path); -+ while (gtk_tree_path_prev (collapse_path)) -+ ; -+ -+ do { -+ if (gtk_tree_path_compare (collapse_path, path) != 0) -+ { -+ _gtk_tree_view_find_node (tree_view, collapse_path, &tree2, &node2); -+ -+ if (tree2 == NULL) -+ /* end reached already */ -+ break; -+ -+ if (node2->children != NULL && -+ gtk_tree_view_real_collapse_row (tree_view, collapse_path, -+ tree2, node2, FALSE)) -+ /* no need to do anything else since only one row may -+ be expanded on any particular level at any time */ -+ break; -+ } -+ -+ gtk_tree_path_next (collapse_path); -+ } while (1); -+ -+ gtk_tree_path_free (collapse_path); -+ - g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand); - - if (expand) -@@ -10643,6 +11765,42 @@ - GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED); - } - -+ /* autoscroll if necessary */ -+ validate_visible_area (tree_view); -+ gtk_tree_model_get_iter (tree_view->priv->model, &parent_iter, path); -+ _gtk_tree_view_find_node (tree_view, path, &tree2, &node2); -+ validate_row (tree_view, tree2, node2, &parent_iter, path); -+ total_height = CELL_HEIGHT (node2, vertical_separator); -+ children = gtk_tree_model_iter_n_children (tree_view->priv->model, &parent_iter); -+ for (n = 0; n < children; n++) -+ { -+ gtk_tree_model_iter_nth_child (tree_view->priv->model, -+ &child_iter, &parent_iter, n); -+ -+ /* must free here so the path of last child is kept for later */ -+ if (child_path != NULL) -+ gtk_tree_path_free (child_path); -+ -+ child_path = gtk_tree_model_get_path (tree_view->priv->model, &child_iter); -+ _gtk_tree_view_find_node (tree_view, child_path, &tree2, &node2); -+ -+ if (CELL_HEIGHT (node2, 0) == 0) -+ validate_row (tree_view, tree2, node2, &child_iter, child_path); -+ -+ total_height += CELL_HEIGHT (node2, vertical_separator); -+ } -+ -+ gtk_tree_view_get_visible_rect (tree_view, &visible_rect); -+ -+ /* KNOWN BUG: If no autocollapse was performed earlier above, these calls -+ to gtk_tree_view_scroll_to_cell do nothing although they should. */ -+ if (total_height > visible_rect.height) -+ gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.0, 0.0); -+ else -+ gtk_tree_view_scroll_to_cell (tree_view, child_path, NULL, FALSE, 0.0, 0.0); -+ -+ gtk_tree_path_free (child_path); -+ - install_presize_handler (tree_view); - - g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path); -@@ -11070,6 +12228,16 @@ - GtkRBTree *tree = NULL; - GtkRBNode *node = NULL; - -+ _gtk_tree_view_find_node (tree_view, path, &tree, &node); -+ -+ /* Hildon: cursor cannot move to an insensitive row */ -+ if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ node, path)) -+ { -+ g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path); -+ return; -+ } -+ - if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) - { - GtkTreePath *cursor_path; -@@ -11083,7 +12251,6 @@ - tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), - tree_view->priv->model, - path); -- _gtk_tree_view_find_node (tree_view, path, &tree, &node); - if (tree != NULL) - { - GtkRBTree *new_tree = NULL; -@@ -11093,7 +12260,8 @@ - { - GtkTreeSelectMode mode = 0; - -- if (tree_view->priv->ctrl_pressed) -+ if (tree_view->priv->ctrl_pressed || -+ tree_view->priv->pen_drag_active) - mode |= GTK_TREE_SELECT_MODE_TOGGLE; - if (tree_view->priv->shift_pressed) - mode |= GTK_TREE_SELECT_MODE_EXTEND; -@@ -11213,6 +12381,9 @@ - { - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - g_return_if_fail (path != NULL); -+ -+ tree_view->priv->pen_focus = FALSE; -+ - if (focus_column) - g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column)); - if (focus_cell) -@@ -11414,6 +12585,7 @@ - GtkRBNode *node = NULL; - gint vertical_separator; - gint horizontal_separator; -+ gint expander_indent; - - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column)); -@@ -11424,6 +12596,7 @@ - gtk_widget_style_get (GTK_WIDGET (tree_view), - "vertical_separator", &vertical_separator, - "horizontal_separator", &horizontal_separator, -+ "expander_indent", &expander_indent, - NULL); - - rect->x = 0; -@@ -11453,9 +12626,11 @@ - TREE_VIEW_DRAW_EXPANDERS (tree_view)) - { - gint depth = gtk_tree_path_get_depth (path) - 1; -+ gint adjust; - -- rect->x += depth * tree_view->priv->expander_size; -- rect->width -= depth * tree_view->priv->expander_size; -+ adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent; -+ rect->x += adjust; -+ rect->width -= adjust; - rect->width = MAX (rect->width, 0); - } - } -@@ -12077,8 +13252,13 @@ - if (gtk_tree_view_is_expander_column (tree_view, column) && - TREE_VIEW_DRAW_EXPANDERS(tree_view)) - { -- cell_area.x += depth * tree_view->priv->expander_size; -- cell_area.width -= depth * tree_view->priv->expander_size; -+ gint adjust, expander_indent; -+ -+ gtk_widget_style_get (widget, "expander_indent", &expander_indent, NULL); -+ -+ adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent; -+ cell_area.x += adjust; -+ cell_area.width -= adjust; - } - - if (gtk_tree_view_column_cell_is_visible (column)) -@@ -13062,3 +14242,138 @@ - tree_view->priv->pressed_button = -1; - } - -+/* Hildon addition: iterates through columns and cells, looks for -+ a cell with "activatable" attribute and sets or unsets -+ priv->checkbox_mode accordingly (except when checkbox mode -+ is disabled by unsetting allow_checkbox_mode). -+ */ -+static void -+update_checkbox_mode (GObject *object, GParamSpec *pspec, gpointer data) -+{ -+ GtkTreeView *tree_view = GTK_TREE_VIEW (data); -+ GList *columns = gtk_tree_view_get_columns (tree_view); -+ GList *list; -+ gboolean allow_checkbox_mode; -+ -+ g_object_get (GTK_WIDGET (data), -+ "allow_checkbox_mode", &allow_checkbox_mode, NULL); -+ g_return_if_fail (allow_checkbox_mode); -+ -+ for (list = columns; list; list = list->next) -+ { -+ GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN (list->data); -+ if (gtk_tree_view_column_get_visible (col) && -+ _gtk_tree_view_column_has_activatable_cell (col)) -+ { -+ /* checkbox column found */ -+ tree_view->priv->checkbox_mode = TRUE; -+ g_list_free (columns); -+ return; -+ } -+ } -+ -+ /* no checkbox column was found */ -+ tree_view->priv->checkbox_mode = FALSE; -+ g_list_free (columns); -+} -+ -+static void -+set_dotted_lines (GtkTreeView *tree_view, gboolean enable) -+{ -+ if (enable != tree_view->priv->dotted_lines) -+ { -+ tree_view->priv->dotted_lines = enable; -+ gtk_widget_queue_draw (GTK_WIDGET (tree_view)); -+ } -+} -+ -+/* This function is used to ensure two things: -+ * - in single selection mode, focus will always equal selection -+ * - in multiple selection mode, focus is removed if cursor row is -+ * explicitly unselected -+ */ -+static void -+selection_changed (GtkTreeSelection *selection, gpointer data) -+{ -+ GtkTreeView *tree_view = GTK_TREE_VIEW(data); -+ GtkTreePath *cursor_path = NULL; -+ GtkTreeIter iter; -+ -+ /* if there are checkboxes, cursor row doesn't have to be selected */ -+ if (tree_view->priv->checkbox_mode) -+ return; -+ -+ if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) -+ cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); -+ -+ if (cursor_path == NULL || -+ !gtk_tree_selection_path_is_selected (selection, cursor_path)) -+ { -+ GtkTreePath *selected_path; -+ GtkRBTree *tree = NULL; -+ GtkRBNode *node = NULL; -+ -+ if (gtk_tree_selection_get_mode (selection) != GTK_SELECTION_MULTIPLE && -+ gtk_tree_selection_get_selected (selection, NULL, &iter)) -+ { -+ selected_path = gtk_tree_model_get_path (tree_view->priv->model, -+ &iter); -+ gtk_tree_view_real_set_cursor (tree_view, selected_path, TRUE, TRUE); -+ _gtk_tree_view_find_node (tree_view, selected_path, &tree, &node); -+ gtk_tree_view_clamp_node_visible (tree_view, tree, node); -+ gtk_tree_path_free (selected_path); -+ gtk_widget_grab_focus (GTK_WIDGET (tree_view)); -+ } -+ else -+ { -+ gtk_tree_row_reference_free (tree_view->priv->cursor); -+ tree_view->priv->cursor = NULL; -+ } -+ } -+ -+ if (cursor_path) -+ gtk_tree_path_free (cursor_path); -+} -+ -+/* Helper function for ensuring that GtkTreeView is focusable -+ * if and only if it contains at least one sensitive top-level row. -+ * Should be called whenever the existence of a sensitive top-level row -+ * might have changed. -+ */ -+static void -+check_if_can_focus (GtkTreeView *tree_view) -+{ -+ GtkTreeModel *model = gtk_tree_view_get_model (tree_view); -+ GtkTreeIter iter; -+ -+ if (model == NULL || !GTK_WIDGET_MAPPED (tree_view)) -+ return; -+ -+ if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) -+ { -+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS); -+ return; -+ } -+ -+ do { -+ GtkTreePath *path = gtk_tree_model_get_path (model, &iter); -+ GtkRBTree *tree; -+ GtkRBNode *node; -+ -+ _gtk_tree_view_find_node (tree_view, path, &tree, &node); -+ -+ if (_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, -+ node, path)) -+ { -+ GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS); -+ if (!gtk_tree_row_reference_valid (tree_view->priv->cursor)) -+ gtk_tree_view_real_set_cursor (tree_view, path, -+ !tree_view->priv->checkbox_mode, -+ TRUE); -+ -+ return; -+ } -+ } while (gtk_tree_model_iter_next (model, &iter)); -+ -+ GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS); -+} |