1 --- gtk+-2.6.4/gtk/gtktreeview.c 2005-02-24 00:38:20.000000000 +0200
2 +++ gtk+-2.6.4/gtk/gtktreeview.c 2005-04-06 16:19:38.274719720 +0300
6 #include "gtktreemodelsort.h"
7 +#include "gtkscrolledwindow.h"
9 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
10 #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
12 EXPAND_COLLAPSE_CURSOR_ROW,
14 START_INTERACTIVE_SEARCH,
21 PROP_FIXED_HEIGHT_MODE,
26 + PROP_FORCE_LIST_KLUDGE,
27 + PROP_ALLOW_CHECKBOX_MODE
30 static void gtk_tree_view_class_init (GtkTreeViewClass *klass);
32 static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
35 -static void gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view,
36 - GtkTreeViewColumn *column);
37 static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view,
38 GdkEventMotion *event);
39 static void gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view);
42 static gboolean expand_collapse_timeout (gpointer data);
43 static gboolean do_expand_collapse (GtkTreeView *tree_view);
44 +static void update_checkbox_mode (GObject *object,
47 +static void set_dotted_lines (GtkTreeView *tree_view,
49 +static void selection_changed (GtkTreeSelection *selection,
51 +static void check_if_can_focus (GtkTreeView *tree_view);
52 +static gint scroll_row_timeout (gpointer data);
54 +static void add_scroll_timeout (GtkTreeView *tree_view);
55 +static void remove_scroll_timeout (GtkTreeView *tree_view);
57 /* interactive search */
58 static void gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view);
64 + * GtkTreeView:dotted-lines:
66 + * Enables or disables the dotted lines for hierarchical trees.
69 + g_object_class_install_property (o_class,
71 + g_param_spec_boolean ("dotted_lines",
73 + P_("Whether to show or hide dotted lines for hierarchical trees"),
75 + G_PARAM_READWRITE));
78 + * GtkTreeView:force-list-kludge:
80 + * Hildon kludge for fixing file tree behaviour until a cleaner
81 + * implementation is scheduled: if this property is set, then rows
82 + * can be activated by tapping even if the underlying tree model is
83 + * not technically a list.
85 + g_object_class_install_property (o_class,
86 + PROP_FORCE_LIST_KLUDGE,
87 + g_param_spec_boolean ("force_list_kludge",
88 + P_("Force List Behaviour"),
89 + P_("Whether to activate tapped focused items even if model was not a list"),
91 + G_PARAM_READWRITE));
94 + * GtkTreeView:enable-checkbox-mode:
96 + * Another Hildon kludge for allowing the existence of GtkTreeViews
97 + * that have activatable columns but that still is not a Text Listbox
98 + * in multiple selection with checkboxes mode.
100 + g_object_class_install_property (o_class,
101 + PROP_ALLOW_CHECKBOX_MODE,
102 + g_param_spec_boolean ("allow_checkbox_mode",
103 + P_("Enable Checkbox Mode"),
104 + P_("Whether to behave like a Listbox in a multiple selection with checkboxes mode, if checkboxes exist"),
106 + G_PARAM_READWRITE));
108 /* Style properties */
109 #define _TREE_VIEW_EXPANDER_SIZE 12
110 +#define _TREE_VIEW_EXPANDER_INDENT 10
111 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
112 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
117 gtk_widget_class_install_style_property (widget_class,
118 + g_param_spec_int ("expander_indent",
119 + P_("Expander intent"),
120 + P_("Defines the expanders indent"),
123 + _TREE_VIEW_EXPANDER_INDENT,
124 + G_PARAM_READABLE));
126 + gtk_widget_class_install_style_property (widget_class,
127 g_param_spec_int ("vertical_separator",
128 P_("Vertical Separator Width"),
129 P_("Vertical space between cells. Must be an even number"),
134 + gtk_widget_class_install_style_property (widget_class,
135 + g_param_spec_boolean ("passive_focus",
136 + P_("Enables passive focus"),
137 + P_("Used for tree view passive focus"),
139 + G_PARAM_READABLE));
142 widget_class->set_scroll_adjustments_signal =
143 g_signal_new ("set_scroll_adjustments",
145 _gtk_marshal_BOOLEAN__NONE,
148 + tree_view_signals[ROW_INSENSITIVE] =
149 + g_signal_new ("row_insensitive",
150 + G_TYPE_FROM_CLASS (o_class),
151 + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
152 + G_STRUCT_OFFSET (GtkTreeViewClass, row_insensitive),
154 + _gtk_marshal_VOID__OBJECT,
156 + GTK_TYPE_TREE_PATH);
159 gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
160 GTK_MOVEMENT_DISPLAY_LINES, -1);
161 @@ -1004,12 +1091,13 @@
163 gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 1,
164 G_TYPE_BOOLEAN, TRUE);
165 + /* Hildon change: Enter shouldn't select
166 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select_cursor_row", 1,
167 G_TYPE_BOOLEAN, TRUE);
168 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select_cursor_row", 1,
169 G_TYPE_BOOLEAN, TRUE);
170 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select_cursor_row", 1,
171 - G_TYPE_BOOLEAN, TRUE);
172 + G_TYPE_BOOLEAN, TRUE);*/
174 /* expand and collapse rows */
175 gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
176 @@ -1123,19 +1211,31 @@
177 gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start_interactive_search", 0);
179 gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0);
181 + /* Hildon addition: Add key bindings to Right and Left arrows */
182 + gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "expand_collapse_cursor_row", 3,
183 + G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE, G_TYPE_BOOLEAN, FALSE);
184 + gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
185 + G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE, G_TYPE_BOOLEAN, TRUE);
186 + gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "expand_collapse_cursor_row", 3,
187 + G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE);
188 + gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
189 + G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, FALSE, G_TYPE_BOOLEAN, TRUE);
193 gtk_tree_view_init (GtkTreeView *tree_view)
195 tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
196 - GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
198 + /* Hildon: focus cannot be gained until at least one row is added */
199 + GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);
201 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
203 + /* Hildon: Headers invisible by default */
204 tree_view->priv->flags = GTK_TREE_VIEW_SHOW_EXPANDERS
205 - | GTK_TREE_VIEW_DRAW_KEYFOCUS
206 - | GTK_TREE_VIEW_HEADERS_VISIBLE;
207 + | GTK_TREE_VIEW_DRAW_KEYFOCUS;
209 /* We need some padding */
210 tree_view->priv->dy = 0;
211 @@ -1165,6 +1265,26 @@
213 tree_view->priv->hover_selection = FALSE;
214 tree_view->priv->hover_expand = FALSE;
216 + tree_view->priv->ctrl_pressed = FALSE;
217 + tree_view->priv->shift_pressed = FALSE;
219 + tree_view->priv->checkbox_mode = FALSE;
220 + tree_view->priv->allow_checkbox_mode = TRUE;
221 + tree_view->priv->pen_down = FALSE;
222 + tree_view->priv->pen_drag_active = FALSE;
223 + tree_view->priv->pen_drag_reverse = FALSE;
224 + tree_view->priv->first_drag_row = NULL;
225 + tree_view->priv->last_drag_row = NULL;
226 + tree_view->priv->queued_expand_row = NULL;
227 + tree_view->priv->queued_select_row = NULL;
228 + tree_view->priv->pen_focus = TRUE;
230 + /* Hildon: cursor should follow when selection changes */
231 + g_signal_connect (tree_view->priv->selection, "changed",
232 + G_CALLBACK (selection_changed), tree_view);
234 + gtk_widget_set_name (GTK_WIDGET (tree_view), "treeview");
238 @@ -1223,6 +1343,27 @@
239 case PROP_HOVER_EXPAND:
240 tree_view->priv->hover_expand = g_value_get_boolean (value);
242 + case PROP_DOTTED_LINES:
243 + set_dotted_lines (tree_view, g_value_get_boolean (value));
245 + case PROP_FORCE_LIST_KLUDGE:
246 + tree_view->priv->force_list_kludge = g_value_get_boolean (value);
248 + case PROP_ALLOW_CHECKBOX_MODE:
249 + if ((tree_view->priv->allow_checkbox_mode = g_value_get_boolean (value)))
251 + gtk_widget_set_name (GTK_WIDGET(tree_view), "treeview");
252 + update_checkbox_mode (NULL, NULL, tree_view);
256 + /* ugly hack - to ensure that checkboxes are independent of the
257 + selection if !allow_checkbox_mode, we must be able to use
258 + different theming in that case */
259 + gtk_widget_set_name (GTK_WIDGET(tree_view), "no_checkbox_mode");
260 + tree_view->priv->checkbox_mode = FALSE;
266 @@ -1276,6 +1417,15 @@
267 case PROP_HOVER_EXPAND:
268 g_value_set_boolean (value, tree_view->priv->hover_expand);
270 + case PROP_DOTTED_LINES:
271 + g_value_set_boolean (value, tree_view->priv->dotted_lines);
273 + case PROP_FORCE_LIST_KLUDGE:
274 + g_value_set_boolean (value, tree_view->priv->force_list_kludge);
276 + case PROP_ALLOW_CHECKBOX_MODE:
277 + g_value_set_boolean (value, tree_view->priv->allow_checkbox_mode);
280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
282 @@ -1376,6 +1526,27 @@
283 tree_view->priv->destroy_count_data = NULL;
286 + if (tree_view->priv->first_drag_row)
288 + gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
289 + tree_view->priv->first_drag_row = NULL;
291 + if (tree_view->priv->last_drag_row)
293 + gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
294 + tree_view->priv->last_drag_row = NULL;
296 + if (tree_view->priv->queued_expand_row)
298 + gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
299 + tree_view->priv->queued_expand_row = NULL;
301 + if (tree_view->priv->queued_select_row)
303 + gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
304 + tree_view->priv->queued_select_row = NULL;
307 gtk_tree_row_reference_free (tree_view->priv->cursor);
308 tree_view->priv->cursor = NULL;
310 @@ -1494,6 +1665,8 @@
311 gtk_tree_view_map_buttons (tree_view);
313 gdk_window_show (widget->window);
315 + check_if_can_focus (tree_view);
319 @@ -1895,6 +2068,8 @@
320 gint full_requested_width = 0;
321 gint number_of_expand_columns = 0;
324 + GtkPolicyType ptype;
326 tree_view = GTK_TREE_VIEW (widget);
328 @@ -1969,6 +2144,19 @@
329 allocation.x = width;
330 column->width = real_requested_width;
332 + /* a dirty Hildon hack to force truncation if not enough space. This hack is applied
333 + * only if we are NOT in a scrolled window with hscroll*/
334 + scroll = gtk_widget_get_ancestor(widget, GTK_TYPE_SCROLLED_WINDOW);
336 + (gtk_scrolled_window_get_policy (GTK_SCROLLED_WINDOW (scroll), &ptype, NULL), ptype == GTK_POLICY_NEVER))
337 + && (width + real_requested_width > widget->allocation.width))
339 + column->width = widget->allocation.width - width;
340 + if (column->width < 1)
342 + gtk_widget_queue_draw (widget);
347 if (number_of_expand_columns == 1)
348 @@ -2153,6 +2341,23 @@
349 GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
352 +/* helper function for gtk_tree_view_button_press */
354 +activate_callback (GtkTreeModel *model,
359 + GtkTreeView *tree_view = GTK_TREE_VIEW (data);
361 + /* Hildon: if the tree view has no active focus we don't activate
362 + * the selected row */
363 + if ( !GTK_WIDGET_HAS_FOCUS (GTK_WIDGET(data)) )
366 + gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
370 gtk_tree_view_button_press (GtkWidget *widget,
371 GdkEventButton *event)
372 @@ -2166,6 +2371,7 @@
373 gint vertical_separator;
374 gint horizontal_separator;
376 + gint expander_indent;
378 g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
379 g_return_val_if_fail (event != NULL, FALSE);
380 @@ -2176,6 +2382,7 @@
381 gtk_widget_style_get (widget,
382 "vertical_separator", &vertical_separator,
383 "horizontal_separator", &horizontal_separator,
384 + "expander_indent", &expander_indent,
388 @@ -2199,6 +2406,14 @@
389 gint column_handled_click = FALSE;
390 gboolean row_double_click = FALSE;
392 + gboolean force_list_kludge;
393 + GtkRBNode *cursor = NULL;
394 + gboolean focus_grab = FALSE;
396 + if (!GTK_WIDGET_HAS_FOCUS (widget))
399 + GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
402 if (tree_view->priv->tree == NULL)
403 @@ -2207,7 +2422,9 @@
407 - /* are we in an arrow? */
408 + /* In Hildon we don't want to use the arrows */
410 + /* are we in an arrow? */
411 if (tree_view->priv->prelight_node &&
412 GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
414 @@ -2226,6 +2443,7 @@
415 grab_focus_and_unset_draw_keyfocus (tree_view);
420 /* find the node that was clicked */
421 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
422 @@ -2247,6 +2465,65 @@
423 background_area.height = ROW_HEIGHT (tree_view, GTK_RBNODE_GET_HEIGHT (node));
424 background_area.x = 0;
426 + if (tree_view->priv->first_drag_row)
428 + gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
429 + tree_view->priv->first_drag_row = NULL;
431 + if (tree_view->priv->last_drag_row)
433 + gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
434 + tree_view->priv->last_drag_row = NULL;
436 + tree_view->priv->first_drag_row =
437 + gtk_tree_row_reference_new (tree_view->priv->model, path);
438 + tree_view->priv->last_drag_row = gtk_tree_row_reference_copy (tree_view->priv->first_drag_row);
440 + /* force_list_kludge allows pen dragging even if
441 + GTK_TREE_MODEL_LIST_ONLY is not set (to fix file tree) */
442 + g_object_get (widget, "force_list_kludge", &force_list_kludge, NULL);
444 + /* Hildon: activate pen dragging, if listbox is not hierarchical and
445 + the pen was not put down in a position that initiates drag'n'drop */
446 + if (!tree_view->priv->pen_down &&
447 + (force_list_kludge ||
448 + (gtk_tree_model_get_flags(tree_view->priv->model)
449 + & GTK_TREE_MODEL_LIST_ONLY)) &&
450 + (tree_view->priv->checkbox_mode ||
451 + !gtk_tree_selection_path_is_selected(tree_view->priv->selection, path)))
453 + gpointer drag_data;
455 + tree_view->priv->pen_down = TRUE;
456 + tree_view->priv->pen_focus = TRUE;
458 + /* also block attached dnd signal handler */
459 + drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
461 + g_signal_handlers_block_matched (widget,
462 + G_SIGNAL_MATCH_DATA,
467 + /* For the Hildon buttonpress find out the previously selected row */
468 + GtkRBTree *cursor_tree = NULL;
469 + GtkTreePath *cursor_path = NULL;
471 + if (tree_view->priv->cursor)
473 + cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
476 + _gtk_tree_view_find_node (tree_view, cursor_path,
477 + &cursor_tree, &cursor);
478 + gtk_tree_path_free (cursor_path);
482 + /* Hildon: in checkbox mode, dragging sets all checkboxes
483 + to the same state as the first toggled checkbox */
484 + tree_view->priv->new_state = !gtk_tree_selection_path_is_selected(tree_view->priv->selection, path);
486 /* Let the column have a chance at selecting it. */
487 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
488 @@ -2275,8 +2552,11 @@
489 if (gtk_tree_view_is_expander_column (tree_view, column) &&
490 TREE_VIEW_DRAW_EXPANDERS(tree_view))
492 - cell_area.x += depth * tree_view->priv->expander_size;
493 - cell_area.width -= depth * tree_view->priv->expander_size;
496 + adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent;
497 + cell_area.x += adjust;
498 + cell_area.width -= adjust;
502 @@ -2364,15 +2644,19 @@
504 if (event->type == GDK_BUTTON_PRESS)
506 + /* Hildon: ignore Ctrl and Shift */
508 if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
509 tree_view->priv->ctrl_pressed = TRUE;
510 if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
511 tree_view->priv->shift_pressed = TRUE;
514 focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x);
516 gtk_tree_view_column_focus_cell (column, focus_cell);
519 if (event->state & GDK_CONTROL_MASK)
521 gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
522 @@ -2387,6 +2671,86 @@
524 gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
527 + if (tree_view->priv->checkbox_mode)
529 + GtkRBTree *tree = NULL;
530 + GtkRBNode *node = NULL;
532 + _gtk_tree_view_find_node (tree_view, path, &tree, &node);
534 + /* cursor cannot move to an insensitive row, so we
535 + need to check here to avoid toggling the current
536 + row by clicking on an insensitive row */
537 + if (_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
540 + gtk_tree_view_real_set_cursor (tree_view, path,
542 + gtk_tree_view_real_toggle_cursor_row (tree_view);
545 + /* Usually this would be emitted by real_set_cursor.
546 + However in this case we never call it. */
547 + g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path);
551 + gboolean queue_row = TRUE;
552 + gboolean force_list_kludge;
554 + /* force_list_kludge allows rows to be activated even if
555 + GTK_TREE_MODEL_LIST_ONLY is not set (to fix file tree) */
556 + g_object_get (widget, "force_list_kludge",
557 + &force_list_kludge, NULL);
558 + if ((force_list_kludge ||
559 + (gtk_tree_model_get_flags (tree_view->priv->model) &
560 + GTK_TREE_MODEL_LIST_ONLY)) &&
561 + gtk_tree_row_reference_valid (tree_view->priv->cursor))
563 + /* special case: text listbox without checkboxes
564 + should activate selected rows when user taps
565 + on cursor row, but not affect selection*/
566 + GtkTreePath *cursor_path =
567 + gtk_tree_row_reference_get_path (tree_view->priv->cursor);
568 + if (gtk_tree_path_compare (cursor_path, path) == 0)
570 + gtk_tree_selection_selected_foreach (tree_view->priv->selection,
578 + (gtk_tree_selection_get_mode (tree_view->priv->selection) == GTK_SELECTION_MULTIPLE) &&
579 + gtk_tree_selection_path_is_selected (tree_view->priv->selection, path))
581 + GtkTreePath *old_cursor_path = NULL;
583 + /* we don't know if the user is selecting an item or performing
584 + multiple item drag and drop until we know where button is released */
585 + if (tree_view->priv->queued_select_row)
586 + gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
587 + tree_view->priv->queued_select_row =
588 + gtk_tree_row_reference_new (tree_view->priv->model, path);
590 + /* however, move focus */
591 + if (tree_view->priv->cursor)
593 + old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
594 + gtk_tree_row_reference_free (tree_view->priv->cursor);
596 + tree_view->priv->cursor = gtk_tree_row_reference_new (tree_view->priv->model,
598 + gtk_tree_view_queue_draw_path (tree_view, path, NULL);
599 + if (old_cursor_path)
600 + gtk_tree_view_queue_draw_path (tree_view, old_cursor_path, NULL);
603 + gtk_tree_view_real_set_cursor (tree_view, path,
607 tree_view->priv->ctrl_pressed = FALSE;
608 tree_view->priv->shift_pressed = FALSE;
609 @@ -2412,6 +2776,15 @@
610 tree_view->priv->press_start_y = event->y;
613 + /* Hildon: if selected row is tapped -> the row gets activated and expands */
616 + /* ...although not until button is released */
617 + gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
618 + tree_view->priv->queued_expand_row =
619 + gtk_tree_row_reference_new (tree_view->priv->model, path);
622 /* Test if a double click happened on the same row. */
623 if (event->button == 1)
625 @@ -2433,6 +2806,8 @@
629 + /* Hildon doesn't support double clicks */
631 if (row_double_click)
633 if (tree_view->priv->last_button_press)
634 @@ -2443,6 +2818,7 @@
635 tree_view->priv->last_button_press_2 = NULL;
640 if (tree_view->priv->last_button_press)
641 gtk_tree_row_reference_free (tree_view->priv->last_button_press);
642 @@ -2626,6 +3002,28 @@
644 tree_view = GTK_TREE_VIEW (widget);
646 + /* unblock attached dnd signal handler */
647 + if (tree_view->priv->pen_down)
649 + gpointer drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
651 + g_signal_handlers_unblock_matched (widget,
652 + G_SIGNAL_MATCH_DATA,
657 + /* stop pen dragging */
658 + if (tree_view->priv->first_drag_row)
659 + gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
660 + if (tree_view->priv->last_drag_row)
661 + gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
662 + tree_view->priv->first_drag_row = NULL;
663 + tree_view->priv->last_drag_row = NULL;
664 + tree_view->priv->pen_down = FALSE;
665 + tree_view->priv->pen_drag_active = FALSE;
666 + remove_scroll_timeout (tree_view);
668 if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
669 return gtk_tree_view_button_release_drag_column (widget, event);
671 @@ -2635,6 +3033,65 @@
672 if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
673 return gtk_tree_view_button_release_column_resize (widget, event);
675 + if (gtk_tree_row_reference_valid (tree_view->priv->queued_select_row))
677 + /* unselect other nodes - but only if not drag'n'dropping */
678 + if (event->window == tree_view->priv->bin_window)
679 + gtk_tree_selection_unselect_all (tree_view->priv->selection);
681 + gtk_tree_view_real_set_cursor (tree_view,
682 + gtk_tree_row_reference_get_path (tree_view->priv->queued_select_row),
684 + gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
685 + tree_view->priv->queued_select_row = NULL;
688 + /* for handling expand/collapse postponed from button_press (since we
689 + don't want expand/collapse before tap on node has been completed) */
690 + if (gtk_tree_row_reference_valid (tree_view->priv->queued_expand_row) &&
691 + tree_view->priv->tree != NULL)
693 + GtkTreePath *queued_expand_path;
696 + GtkRBNode *old_node;
699 + queued_expand_path =
700 + gtk_tree_row_reference_get_path (tree_view->priv->queued_expand_row);
702 + if (queued_expand_path)
704 + /* must check that cursor hasn't moved elsewhere since button_press */
705 + y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->y);
706 + _gtk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node);
708 + _gtk_tree_view_find_node (tree_view, queued_expand_path,
711 + if (node && old_node == node)
713 + if (node->children == NULL)
714 + gtk_tree_view_real_expand_row (tree_view,
715 + queued_expand_path,
720 + gtk_tree_view_real_collapse_row (tree_view,
721 + queued_expand_path,
727 + gtk_tree_path_free (queued_expand_path);
730 + gtk_tree_row_reference_free( tree_view->priv->queued_expand_row);
731 + tree_view->priv->queued_expand_row = NULL;
734 if (tree_view->priv->button_pressed_node == NULL)
737 @@ -3311,6 +3768,7 @@
738 GtkTreeView *tree_view;
741 + GtkTreePath *path, *last_drag_path, *current_path;
744 tree_view = (GtkTreeView *) widget;
745 @@ -3319,7 +3777,8 @@
748 /* only check for an initiated drag when a button is pressed */
749 - if (tree_view->priv->pressed_button >= 0)
750 + /* Hildon: active pen drag overrides drag and drop */
751 + if (tree_view->priv->pressed_button >= 0 && !tree_view->priv->pen_down)
752 gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
754 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
755 @@ -3328,6 +3787,99 @@
757 _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
759 + /* Hildon: pen dragging */
760 + if (tree_view->priv->pen_down && node != NULL &&
761 + tree_view->priv->queued_select_row == NULL &&
762 + gtk_tree_row_reference_valid (tree_view->priv->last_drag_row))
766 + last_drag_path = gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row);
767 + path = _gtk_tree_view_find_path (tree_view, tree, node);
768 + direction = gtk_tree_path_compare (path, last_drag_path);
770 + if (direction != 0)
772 + current_path = gtk_tree_path_copy (last_drag_path);
774 + /* we must ensure that no row is skipped because stylus
775 + is moving faster than motion events are generated */
779 + /* gtk_tree_path_next does not let us know when it failed */
781 + gtk_tree_model_get_iter (tree_view->priv->model, &iter, current_path);
782 + if (!gtk_tree_model_iter_next (tree_view->priv->model, &iter))
785 + gtk_tree_path_next (current_path);
787 + else if (!gtk_tree_path_prev (current_path))
790 + /* set cursor, and start scrolling */
791 + gtk_tree_view_real_set_cursor (tree_view, current_path, FALSE, FALSE);
792 + add_scroll_timeout (tree_view);
794 + if (tree_view->priv->checkbox_mode)
796 + /* always set to same state as the first tapped node */
797 + if (tree_view->priv->new_state)
798 + gtk_tree_selection_select_path (tree_view->priv->selection,
801 + gtk_tree_selection_unselect_path (tree_view->priv->selection,
806 + if (gtk_tree_selection_path_is_selected (tree_view->priv->selection,
809 + /* apparently we have reversed the pen drag direction */
810 + GtkTreePath *reverse_path;
811 + gint reverse_direction;
813 + reverse_direction = gtk_tree_path_compare (current_path,
815 + reverse_path = gtk_tree_path_copy (last_drag_path);
817 + gtk_tree_selection_unselect_path (tree_view->priv->selection,
819 + tree_view->priv->pen_drag_reverse = TRUE;
820 + if (reverse_direction > 0)
823 + gtk_tree_model_get_iter (tree_view->priv->model, &iter, reverse_path);
824 + if (!gtk_tree_model_iter_next (tree_view->priv->model, &iter))
827 + gtk_tree_path_next (reverse_path);
829 + else if (!gtk_tree_path_prev (reverse_path))
831 + } while (gtk_tree_path_compare (reverse_path, current_path) != 0);
832 + gtk_tree_path_free (reverse_path);
836 + gtk_tree_selection_select_path (tree_view->priv->selection,
838 + tree_view->priv->pen_drag_reverse = FALSE;
841 + } while (gtk_tree_path_compare(current_path, path) != 0);
842 + gtk_tree_path_free (current_path);
844 + /* update last_drag_row */
845 + gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
846 + tree_view->priv->last_drag_row =
847 + gtk_tree_row_reference_new (tree_view->priv->model, path);
848 + gtk_tree_path_free (path);
852 /* If we are currently pressing down a button, we don't want to prelight anything else. */
853 if ((tree_view->priv->button_pressed_node != NULL) &&
854 (tree_view->priv->button_pressed_node != node))
855 @@ -3404,6 +3956,22 @@
859 +/* Hildon: helper function for dotted slash drawing;
860 + returns TRUE or FALSE, depending it there are
861 + more nodes at current level */
863 +iter_has_next (GtkTreeModel *model, GtkTreeIter *iter)
865 + GtkTreeIter *check_iter;
868 + check_iter = gtk_tree_iter_copy(iter);
869 + result = gtk_tree_model_iter_next (model, check_iter);
871 + gtk_tree_iter_free (check_iter);
875 /* Warning: Very scary function.
876 * Modify at your own risk
878 @@ -3433,16 +4001,25 @@
881 gint bin_window_width;
882 - GtkTreePath *cursor_path;
883 - GtkTreePath *drag_dest_path;
884 + GtkTreePath *cursor_path = NULL;
885 + GtkTreePath *drag_dest_path = NULL;
887 gint vertical_separator;
888 gint horizontal_separator;
889 + gint expander_indent;
890 gint focus_line_width;
891 gboolean allow_rules;
892 gboolean has_special_cell;
894 gint n_visible_columns;
895 + gboolean dottedlines, passivefocus, res;
897 + /* Hildon: these variables are added for dotted slash drawing
898 + (Hierarchical listbox) */
900 + gint node_elements = 64;
901 + gboolean *iter_value = NULL;
902 + GtkTreeIter node_iter, parent_iter;
904 g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
906 @@ -3455,8 +4032,12 @@
907 "vertical_separator", &vertical_separator,
908 "allow_rules", &allow_rules,
909 "focus-line-width", &focus_line_width,
910 + "expander_indent", &expander_indent,
911 + "passive_focus", &passivefocus,
914 + g_object_get (widget, "dotted_lines", &dottedlines, NULL);
916 if (tree_view->priv->tree == NULL)
918 draw_empty_focus (tree_view, &event->area);
919 @@ -3478,6 +4059,8 @@
923 + iter_value = g_new (gboolean, node_elements);
925 /* find the path for the node */
926 path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
928 @@ -3486,11 +4069,25 @@
931 depth = gtk_tree_path_get_depth (path);
934 + for (i = depth - 1; i >= 1; i--)
936 + res = gtk_tree_model_iter_parent (tree_view->priv->model, &parent_iter, &node_iter);
937 + /* Check, if we should grow array */
938 + if (i >= node_elements - 1)
940 + node_elements *= 2;
941 + iter_value = g_renew (gboolean, iter_value, node_elements);
945 + iter_value[i] = iter_has_next (tree_view->priv->model, &parent_iter);
946 + node_iter = parent_iter;
948 + gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
949 gtk_tree_path_free (path);
951 - cursor_path = NULL;
952 - drag_dest_path = NULL;
954 if (tree_view->priv->cursor)
955 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
957 @@ -3533,6 +4130,7 @@
961 + gboolean is_first = TRUE;
962 gboolean is_separator = FALSE;
964 if (tree_view->priv->row_separator_func)
965 @@ -3570,6 +4168,7 @@
966 GtkTreeViewColumn *column = list->data;
967 const gchar *detail = NULL;
969 + gboolean is_last = (rtl ? !list->prev : !list->next);
971 if (!column->visible)
973 @@ -3660,31 +4259,152 @@
975 state = GTK_STATE_NORMAL;
977 - /* Draw background */
978 - gtk_paint_flat_box (widget->style,
987 - background_area.width,
988 - background_area.height);
989 + if (tree_view->priv->pen_focus)
991 + if (node != cursor ||
992 + (!GTK_WIDGET_HAS_FOCUS (widget) && !passivefocus))
994 + if ((flags & GTK_CELL_RENDERER_SELECTED)
995 + && !tree_view->priv->checkbox_mode)
996 + state = GTK_STATE_SELECTED;
998 + state = GTK_STATE_NORMAL;
1000 + /* Draw background */
1001 + gtk_paint_flat_box (widget->style,
1008 + background_area.x,
1009 + background_area.y,
1010 + background_area.width,
1011 + background_area.height);
1013 + else if ((flags & GTK_CELL_RENDERER_SELECTED) &&
1014 + !tree_view->priv->checkbox_mode &&
1017 + gtk_paint_flat_box (widget->style,
1019 + GTK_STATE_SELECTED,
1024 + background_area.x,
1025 + background_area.y,
1026 + background_area.width,
1027 + background_area.height);
1032 + /* Draw background */
1033 + gtk_paint_flat_box (widget->style,
1040 + background_area.x,
1041 + background_area.y,
1042 + background_area.width,
1043 + background_area.height);
1046 + /* Hildon change: drawing focus is moved here because it didn't work
1047 + properly before. Some changes where also made.*/
1048 + /* draw the big row-spanning focus rectangle, if needed */
1049 + if (node == cursor &&
1050 + (!passivefocus || GTK_WIDGET_HAS_FOCUS (widget)))
1052 + gtk_paint_focus (widget->style,
1058 + ? (is_last ? "full" : "left")
1059 + : (is_last ? "right" : "middle")),
1060 + background_area.x - (is_first ? 0 : horizontal_separator / 2),
1061 + background_area.y - vertical_separator / 2,
1062 + background_area.width + (is_first ? 0 : (is_last ? horizontal_separator / 2 : horizontal_separator)),
1063 + background_area.height + vertical_separator);
1067 + else if (node == cursor && passivefocus &&
1068 + !GTK_WIDGET_HAS_FOCUS (widget))
1070 + GtkStyle *style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget),
1074 + gtk_style_attach (style, event->window);
1076 + gtk_paint_focus (style, event->window, GTK_STATE_SELECTED,
1077 + &event->area, widget,
1079 + ? (is_last ? "full" : "left")
1080 + : (is_last ? "right" : "middle")),
1081 + background_area.x - (is_first ? 0 : horizontal_separator / 2),
1082 + background_area.y - vertical_separator / 2,
1083 + background_area.width + (is_first ? 0 : (is_last ? horizontal_separator / 2 : horizontal_separator)),
1084 + background_area.height + vertical_separator);
1089 + if (node == cursor)
1091 + gint width, x_offset;
1092 + GtkStateType focus_rect_state;
1093 + focus_rect_state =
1094 + flags & GTK_CELL_RENDERER_FOCUSED ? GTK_STATE_ACTIVE :
1095 + (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
1096 + (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
1097 + (flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
1098 + GTK_STATE_NORMAL)));
1100 + gtk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, NULL);
1101 + gdk_drawable_get_size (tree_view->priv->bin_window, &width, NULL);
1104 if (gtk_tree_view_is_expander_column (tree_view, column) &&
1105 TREE_VIEW_DRAW_EXPANDERS(tree_view))
1107 + gint px, px2, py, i;
1112 + px = (depth - 1) * tree_view->priv->expander_size +
1113 + (depth - 2) * expander_indent;
1115 + /* Hildonlike hack for making the indent look better.
1116 + * indent is added to all rows except the first one */
1119 - cell_area.x += depth * tree_view->priv->expander_size;
1120 - cell_area.width -= depth * tree_view->priv->expander_size;
1121 + cell_area.x += depth * tree_view->priv->expander_size + (depth-1) * expander_indent;
1122 + cell_area.width -= depth * tree_view->priv->expander_size + (depth-1) * expander_indent;
1124 /* If we have an expander column, the highlight underline
1125 * starts with that column, so that it indicates which
1126 * level of the tree we're dropping at.
1128 highlight_x = cell_area.x;
1130 + if (!GTK_WIDGET_IS_SENSITIVE (widget))
1132 + flags &= ~ (GTK_CELL_RENDERER_PRELIT + GTK_CELL_RENDERER_INSENSITIVE +
1133 + GTK_CELL_RENDERER_FOCUSED);
1134 + flags &= GTK_CELL_RENDERER_INSENSITIVE;
1138 gtk_paint_hline (widget->style,
1140 @@ -3702,6 +4422,48 @@
1145 + /* Hildon dotted slash line drawing for Hierarchical Listbox
1149 + py = cell_area.y + cell_area.height / 2;
1150 + px2 = depth * tree_view->priv->expander_size +
1151 + (depth - 1) * expander_indent;
1153 + gdk_gc_set_line_attributes (widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1154 + 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
1156 + gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1161 + gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1162 + px, cell_area.y, px, py);
1163 + if (iter_has_next (tree_view->priv->model, &iter))
1165 + gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1166 + px, py, px, cell_area.y + cell_area.height);
1170 + if (node->children)
1172 + gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1173 + px2, py, px2, cell_area.y + cell_area.height);
1175 + for (i = depth - 1; i >= 2; i--)
1177 + if (iter_value[i])
1179 + px = (i - 1)* tree_view->priv->expander_size + (i - 2) * expander_indent;
1180 + gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1181 + px, cell_area.y, px, cell_area.y + cell_area.height);
1186 if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
1189 @@ -3803,6 +4565,8 @@
1193 + /* Hildon: disabled this */
1195 /* draw the big row-spanning focus rectangle, if needed */
1196 if (!has_special_cell && node == cursor &&
1197 GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
1198 @@ -3830,6 +4594,7 @@
1200 ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node)));
1204 y_offset += max_height;
1206 @@ -3847,6 +4612,17 @@
1207 has_child = gtk_tree_model_iter_children (tree_view->priv->model,
1211 + /* Check if we need to grow array */
1212 + if (depth >= node_elements - 1)
1214 + node_elements *= 2;
1215 + iter_value = g_renew (gboolean, iter_value, node_elements);
1219 + iter_value[depth] = iter_has_next (tree_view->priv->model, &parent);
1224 @@ -3897,6 +4673,9 @@
1226 gtk_tree_path_free (drag_dest_path);
1229 + g_free (iter_value);
1234 @@ -4179,6 +4958,63 @@
1236 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1238 + /* Special Hildon keyboard interactions */
1239 + if (event->keyval == GDK_Escape)
1240 + gtk_tree_selection_unselect_all (tree_view->priv->selection);
1242 + if (event->keyval == GDK_Return &&
1243 + gtk_tree_row_reference_valid (tree_view->priv->cursor))
1245 + gboolean force_list_kludge;
1247 + g_object_get (widget, "force_list_kludge", &force_list_kludge, NULL);
1248 + if (force_list_kludge ||
1249 + (gtk_tree_model_get_flags (tree_view->priv->model) &
1250 + GTK_TREE_MODEL_LIST_ONLY))
1252 + /* text listbox */
1253 + if (tree_view->priv->checkbox_mode)
1255 + /* multisel with checkboxes: select key toggles focused */
1256 + gtk_tree_view_real_toggle_cursor_row (tree_view);
1260 + /* no checkboxes: select key activates focused */
1261 + GtkTreePath *cursor_path =
1262 + gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1264 + gtk_tree_view_row_activated (tree_view, cursor_path,
1265 + tree_view->priv->focus_column);
1267 + gtk_tree_path_free (cursor_path);
1272 + /* hierarchical listbox */
1273 + GtkTreePath *cursor_path;
1277 + cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1278 + _gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node);
1280 + if (node->children == NULL)
1281 + gtk_tree_view_real_expand_row (tree_view,
1287 + gtk_tree_view_real_collapse_row (tree_view,
1295 if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
1297 if (event->keyval == GDK_Escape)
1298 @@ -4420,6 +5256,7 @@
1300 /* FIXME Is this function necessary? Can I get an enter_notify event
1301 * w/o either an expose event or a mouse motion event?
1302 + * Hildon => it is necessary to make pen dragging work correctly
1305 gtk_tree_view_enter_notify (GtkWidget *widget,
1306 @@ -4434,6 +5271,10 @@
1308 tree_view = GTK_TREE_VIEW (widget);
1310 + /* stop "automatic" pen dragging */
1311 + tree_view->priv->pen_drag_active = FALSE;
1312 + remove_scroll_timeout (tree_view);
1314 /* Sanity check it */
1315 if (event->window != tree_view->priv->bin_window)
1317 @@ -4463,6 +5304,9 @@
1318 tree_view = GTK_TREE_VIEW (widget);
1319 tree_view->priv->pressed_button = -1;
1321 + if (tree_view->priv->pen_down && tree_view->priv->queued_select_row == NULL)
1322 + tree_view->priv->pen_drag_active = TRUE;
1324 if (event->mode == GDK_CROSSING_GRAB)
1327 @@ -4535,6 +5379,7 @@
1328 gboolean retval = FALSE;
1329 gboolean is_separator = FALSE;
1331 + gint expander_indent;
1333 /* double check the row needs validating */
1334 if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID) &&
1335 @@ -4551,6 +5396,7 @@
1336 gtk_widget_style_get (GTK_WIDGET (tree_view),
1337 "focus-padding", &focus_pad,
1338 "horizontal_separator", &horizontal_separator,
1339 + "expander_indent", &expander_indent,
1342 for (list = tree_view->priv->columns; list; list = list->next)
1343 @@ -4577,13 +5423,16 @@
1345 height = MAX (height, tmp_height);
1346 height = MAX (height, tree_view->priv->expander_size);
1348 + /* Hildon addition */
1352 height = 2 + 2 * focus_pad;
1354 if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view))
1356 - tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size);
1357 + tmp_width = tmp_width + horizontal_separator + depth * (tree_view->priv->expander_size) + (depth - 1) * expander_indent;
1360 tmp_width = tmp_width + horizontal_separator;
1361 @@ -5585,6 +6434,16 @@
1365 +add_scroll_timeout (GtkTreeView *tree_view)
1367 + if (tree_view->priv->scroll_timeout == 0)
1369 + tree_view->priv->scroll_timeout =
1370 + g_timeout_add (150, scroll_row_timeout, tree_view);
1375 remove_scroll_timeout (GtkTreeView *tree_view)
1377 if (tree_view->priv->scroll_timeout != 0)
1378 @@ -6130,10 +6989,9 @@
1379 tree_view->priv->open_dest_timeout =
1380 g_timeout_add (AUTO_EXPAND_TIMEOUT, open_row_timeout, tree_view);
1382 - else if (tree_view->priv->scroll_timeout == 0)
1385 - tree_view->priv->scroll_timeout =
1386 - g_timeout_add (150, scroll_row_timeout, tree_view);
1387 + add_scroll_timeout (tree_view);
1390 if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
1391 @@ -6901,8 +7759,6 @@
1392 GtkMovementStep step,
1395 - GdkModifierType state;
1397 g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
1398 g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
1399 step == GTK_MOVEMENT_VISUAL_POSITIONS ||
1400 @@ -6919,6 +7775,8 @@
1401 GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1402 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
1404 + /* Hildon: Ignore ctrl and shift */
1406 if (gtk_get_current_event_state (&state))
1408 if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
1409 @@ -6926,6 +7784,7 @@
1410 if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
1411 tree_view->priv->shift_pressed = TRUE;
1414 /* else we assume not pressed */
1417 @@ -7092,6 +7951,27 @@
1419 if (!tree_view->priv->fixed_height_mode)
1420 install_presize_handler (tree_view);
1422 + /* Hildon: has row now been dimmed? If so, unselect it */
1423 + _gtk_tree_view_find_node (tree_view, path, &tree, &node);
1424 + if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1428 + if (gtk_tree_path_compare (path,
1429 + gtk_tree_row_reference_get_path(tree_view->priv->cursor))
1432 + gtk_tree_row_reference_free (tree_view->priv->cursor);
1433 + tree_view->priv->cursor = NULL;
1436 + gtk_tree_selection_unselect_path (tree_view->priv->selection, path);
1437 + gtk_tree_view_collapse_row (tree_view, path);
1440 + check_if_can_focus (tree_view);
1443 gtk_tree_path_free (path);
1445 @@ -7196,6 +8076,11 @@
1446 install_presize_handler (tree_view);
1448 gtk_tree_path_free (path);
1450 + /* Hildon: after a focusable row has been added, the
1451 + entire widget becomes focusable if it wasn't before */
1452 + if ((GTK_WIDGET_FLAGS (tree_view) & GTK_CAN_FOCUS) == 0)
1453 + check_if_can_focus (tree_view);
1457 @@ -7295,6 +8180,16 @@
1458 _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data);
1462 +check_if_can_focus_idle (GtkTreeView *tree_view)
1464 + check_if_can_focus (tree_view);
1466 + tree_view->priv->check_if_can_focus_idle_id = 0;
1472 gtk_tree_view_row_deleted (GtkTreeModel *model,
1474 @@ -7357,6 +8252,11 @@
1475 tree_view->priv->tree = NULL;
1477 _gtk_rbtree_remove (tree);
1479 + /* Hildon: no nodes -> not focusable */
1480 + /* FIXME this looks superfluos to me. check_if_can_focus is called
1481 + * at the end of this function .. -- Jorn */
1482 + GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);
1486 @@ -7375,6 +8275,13 @@
1488 if (selection_changed)
1489 g_signal_emit_by_name (tree_view->priv->selection, "changed");
1491 + /* FIXME whacky hack to work around the treeview not being in a clean state
1492 + * when in a tree a row has been removed, but has_child_toggled not been
1494 + if (tree_view->priv->check_if_can_focus_idle_id == 0)
1495 + tree_view->priv->check_if_can_focus_idle_id =
1496 + g_idle_add ((GSourceFunc) check_if_can_focus_idle, tree_view);
1500 @@ -7508,6 +8415,7 @@
1502 GtkTreeViewColumn *tmp_column = NULL;
1504 + gint expander_indent, depth;
1505 gboolean indent_expanders;
1508 @@ -7535,14 +8443,19 @@
1510 gtk_widget_style_get (GTK_WIDGET (tree_view),
1511 "indent_expanders", &indent_expanders,
1512 + "expander_indent", &expander_indent,
1515 + /* Hildonlike hack for making the indent look better.
1516 + * indent is added to all rows except the first one */
1517 + depth = _gtk_rbtree_get_depth (tree);
1519 if (indent_expanders)
1522 - x_offset -= tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
1523 + x_offset -= tree_view->priv->expander_size * depth + (depth) * expander_indent;
1525 - x_offset += tree_view->priv->expander_size * _gtk_rbtree_get_depth (tree);
1526 + x_offset += tree_view->priv->expander_size * depth + (depth) * expander_indent;
1530 @@ -7617,9 +8530,11 @@
1531 gboolean retval = FALSE;
1533 gint horizontal_separator;
1534 + gint expander_indent;
1536 gtk_widget_style_get (GTK_WIDGET (tree_view),
1537 "horizontal_separator", &horizontal_separator,
1538 + "expander_indent", &expander_indent,
1542 @@ -7657,7 +8572,7 @@
1543 if (gtk_tree_view_is_expander_column (tree_view, column) &&
1544 TREE_VIEW_DRAW_EXPANDERS (tree_view))
1546 - if (depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
1547 + if ((depth - 1) *expander_indent + depth * tree_view->priv->expander_size + horizontal_separator + width > column->requested_width)
1549 _gtk_tree_view_column_cell_set_dirty (column, TRUE);
1551 @@ -7747,6 +8662,7 @@
1557 gtk_tree_view_clamp_column_visible (GtkTreeView *tree_view,
1558 GtkTreeViewColumn *column)
1559 @@ -7762,6 +8678,7 @@
1560 gtk_adjustment_set_value (tree_view->priv->hadjustment,
1561 column->button->allocation.x);
1565 /* This function could be more efficient. I'll optimize it if profiling seems
1566 * to imply that it is important */
1567 @@ -8290,7 +9207,7 @@
1570 area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
1571 - area.width = expander_size + 2;
1572 + area.width = expander_size;
1573 area.height = MAX (CELL_HEIGHT (node, vertical_separator), (expander_size - vertical_separator));
1575 if (node == tree_view->priv->button_pressed_node)
1576 @@ -8397,7 +9314,10 @@
1577 GtkRBNode *cursor_node = NULL;
1578 GtkRBTree *new_cursor_tree = NULL;
1579 GtkRBNode *new_cursor_node = NULL;
1580 + GtkRBTree *old_cursor_tree;
1581 + GtkRBNode *old_cursor_node;
1582 GtkTreePath *cursor_path = NULL;
1583 + GtkTreePath *new_cursor_path = NULL;
1585 if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1587 @@ -8415,12 +9335,30 @@
1588 if (cursor_tree == NULL)
1589 /* FIXME: we lost the cursor; should we get the first? */
1592 - _gtk_rbtree_prev_full (cursor_tree, cursor_node,
1593 - &new_cursor_tree, &new_cursor_node);
1595 - _gtk_rbtree_next_full (cursor_tree, cursor_node,
1596 - &new_cursor_tree, &new_cursor_node);
1598 + old_cursor_tree = cursor_tree;
1599 + old_cursor_node = cursor_node;
1602 + _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node,
1603 + &new_cursor_tree, &new_cursor_node);
1605 + _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node,
1606 + &new_cursor_tree, &new_cursor_node);
1608 + if (new_cursor_node)
1610 + if (new_cursor_path)
1611 + gtk_tree_path_free (new_cursor_path);
1613 + new_cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
1614 + old_cursor_tree = new_cursor_tree;
1615 + old_cursor_node = new_cursor_node;
1617 + } while (new_cursor_node &&
1618 + !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1620 + new_cursor_path));
1623 * If the list has only one item and multi-selection is set then select
1624 @@ -8450,7 +9388,33 @@
1625 if (new_cursor_node)
1627 cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
1628 - gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
1630 + if (tree_view->priv->checkbox_mode)
1631 + gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, TRUE);
1633 + gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
1635 + if (tree_view->priv->pen_drag_active)
1637 + if (gtk_tree_path_compare (gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row),
1638 + gtk_tree_row_reference_get_path (tree_view->priv->first_drag_row)) == 0)
1639 + tree_view->priv->pen_drag_reverse = FALSE;
1641 + if (tree_view->priv->pen_drag_reverse)
1643 + gtk_tree_selection_select_path (tree_view->priv->selection,
1645 + gtk_tree_selection_unselect_path (tree_view->priv->selection,
1646 + gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row));
1649 + gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
1651 + tree_view->priv->last_drag_row =
1652 + gtk_tree_row_reference_new (tree_view->priv->model,
1656 gtk_tree_path_free (cursor_path);
1659 @@ -8467,6 +9431,8 @@
1661 GtkRBTree *cursor_tree = NULL;
1662 GtkRBNode *cursor_node = NULL;
1663 + GtkRBTree *old_cursor_tree = NULL;
1664 + GtkRBNode *old_cursor_node = NULL;
1665 GtkTreePath *cursor_path = NULL;
1667 gint vertical_separator;
1668 @@ -8474,6 +9440,9 @@
1669 if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1672 + if (tree_view->priv->tree == NULL)
1675 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
1676 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1678 @@ -8504,7 +9473,65 @@
1680 _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
1681 cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1682 - g_return_if_fail (cursor_path != NULL);
1684 + while (cursor_node &&
1685 + !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1689 + old_cursor_tree = cursor_tree;
1690 + old_cursor_node = cursor_node;
1693 + _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node,
1694 + &cursor_tree, &cursor_node);
1696 + _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node,
1697 + &cursor_tree, &cursor_node);
1701 + gtk_tree_path_free(cursor_path);
1702 + cursor_path = NULL;
1706 + cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1709 + if (cursor_path == NULL)
1711 + /* looks like we reached the end without finding a sensitive row,
1712 + so search backwards and try to find the last sensitive row as
1713 + the next best thing */
1714 + _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
1715 + cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1716 + while (cursor_node &&
1717 + !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1721 + old_cursor_tree = cursor_tree;
1722 + old_cursor_node = cursor_node;
1725 + _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node,
1726 + &cursor_tree, &cursor_node);
1728 + _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node,
1729 + &cursor_tree, &cursor_node);
1733 + gtk_tree_path_free(cursor_path);
1734 + cursor_path = NULL;
1738 + cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1742 gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
1743 gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
1744 gtk_tree_path_free (cursor_path);
1745 @@ -8514,6 +9541,8 @@
1746 gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
1749 + /* Hildon: cursor is always displayed on an entire row anyway */
1751 GtkRBTree *cursor_tree = NULL;
1752 GtkRBNode *cursor_node = NULL;
1753 GtkTreePath *cursor_path = NULL;
1754 @@ -8589,12 +9618,15 @@
1755 g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
1757 gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
1762 gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
1765 + /* Hildon: cursor is always displayed on an entire row anyway */
1767 GtkRBTree *cursor_tree;
1768 GtkRBNode *cursor_node;
1770 @@ -8631,6 +9663,7 @@
1771 path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
1772 gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
1773 gtk_tree_path_free (path);
1778 @@ -8670,7 +9703,7 @@
1779 GtkTreePath *cursor_path = NULL;
1780 GtkTreeSelectMode mode = 0;
1782 - if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1783 + if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode)
1786 if (tree_view->priv->cursor)
1787 @@ -8731,7 +9764,7 @@
1788 GtkRBNode *cursor_node = NULL;
1789 GtkTreePath *cursor_path = NULL;
1791 - if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1792 + if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode)
1796 @@ -8774,6 +9807,7 @@
1797 GtkTreePath *cursor_path = NULL;
1800 + gboolean hildon_row;
1802 if (! GTK_WIDGET_HAS_FOCUS (tree_view))
1804 @@ -8796,10 +9830,32 @@
1805 && gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL)
1809 - gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, node, open_all, TRUE);
1810 + /* Keyboard Navigation: if we can't expand/collapse row, we should either move active focus
1811 + to child item (right arrow) or move active focus to the parent item (left arrow) */
1814 + hildon_row = gtk_tree_view_real_expand_row (tree_view, cursor_path, tree,
1815 + node, open_all, TRUE);
1817 + if (!hildon_row || !node->children)
1818 + g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET (tree_view),
1821 + GTK_DIR_TAB_FORWARD);
1824 - gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
1826 + hildon_row = gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE);
1828 + if (hildon_row == FALSE)
1830 + g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET(tree_view),
1833 + GTK_DIR_TAB_BACKWARD);
1834 + gtk_tree_view_real_select_cursor_parent (tree_view);
1838 gtk_tree_path_free (cursor_path);
1840 @@ -9327,6 +10383,14 @@
1841 tree_view->priv->last_button_press_2 = NULL;
1842 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
1843 tree_view->priv->scroll_to_path = NULL;
1844 + gtk_tree_row_reference_free (tree_view->priv->first_drag_row);
1845 + tree_view->priv->first_drag_row = NULL;
1846 + gtk_tree_row_reference_free (tree_view->priv->last_drag_row);
1847 + tree_view->priv->last_drag_row = NULL;
1848 + gtk_tree_row_reference_free (tree_view->priv->queued_expand_row);
1849 + tree_view->priv->queued_expand_row = NULL;
1850 + gtk_tree_row_reference_free (tree_view->priv->queued_select_row);
1851 + tree_view->priv->queued_select_row = NULL;
1853 tree_view->priv->scroll_to_column = NULL;
1855 @@ -9402,6 +10466,8 @@
1856 install_presize_handler (tree_view);
1859 + check_if_can_focus (tree_view);
1861 g_object_notify (G_OBJECT (tree_view), "model");
1863 if (GTK_WIDGET_REALIZED (tree_view))
1864 @@ -9744,6 +10810,10 @@
1865 G_CALLBACK (column_sizing_notify),
1868 + g_signal_handlers_disconnect_by_func (column,
1869 + G_CALLBACK (update_checkbox_mode),
1872 _gtk_tree_view_column_unset_tree_view (column);
1874 tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
1875 @@ -9773,6 +10843,8 @@
1876 g_object_unref (column);
1877 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
1879 + update_checkbox_mode (NULL, NULL, tree_view);
1881 return tree_view->priv->n_columns;
1884 @@ -9815,6 +10887,9 @@
1885 g_signal_connect (column, "notify::sizing",
1886 G_CALLBACK (column_sizing_notify), tree_view);
1888 + g_signal_connect (column, "notify::visible",
1889 + G_CALLBACK (update_checkbox_mode), tree_view);
1891 tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
1893 tree_view->priv->n_columns++;
1894 @@ -9838,6 +10913,9 @@
1896 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
1898 + update_checkbox_mode (NULL, NULL, tree_view);
1899 + check_if_can_focus (tree_view);
1901 return tree_view->priv->n_columns;
1904 @@ -10295,7 +11373,6 @@
1905 GtkTreeViewColumn *column)
1907 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
1909 g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
1912 @@ -10560,6 +11637,16 @@
1916 + gint vertical_separator;
1917 + GtkTreePath *collapse_path;
1920 + GtkTreePath *child_path = NULL;
1921 + GtkTreeIter parent_iter;
1922 + GtkTreeIter child_iter;
1923 + GdkRectangle visible_rect;
1925 + guint total_height;
1927 remove_auto_expand_timeout (tree_view);
1929 @@ -10573,8 +11660,12 @@
1930 if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
1933 + /* Hildon: insensitive rows cannot be expanded */
1934 + if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
1938 - if (node->children && open_all)
1939 + if (node->children && open_all)
1941 gboolean retval = FALSE;
1942 GtkTreePath *tmp_path = gtk_tree_path_copy (path);
1943 @@ -10603,6 +11694,37 @@
1947 + /* Hildon: collapse other items in the same level */
1948 + gtk_widget_style_get (GTK_WIDGET (tree_view),
1949 + "vertical_separator", &vertical_separator, NULL);
1951 + /* find the first child */
1952 + collapse_path = gtk_tree_path_copy (path);
1953 + while (gtk_tree_path_prev (collapse_path))
1957 + if (gtk_tree_path_compare (collapse_path, path) != 0)
1959 + _gtk_tree_view_find_node (tree_view, collapse_path, &tree2, &node2);
1961 + if (tree2 == NULL)
1962 + /* end reached already */
1965 + if (node2->children != NULL &&
1966 + gtk_tree_view_real_collapse_row (tree_view, collapse_path,
1967 + tree2, node2, FALSE))
1968 + /* no need to do anything else since only one row may
1969 + be expanded on any particular level at any time */
1973 + gtk_tree_path_next (collapse_path);
1976 + gtk_tree_path_free (collapse_path);
1978 g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
1981 @@ -10643,6 +11765,42 @@
1982 GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED);
1985 + /* autoscroll if necessary */
1986 + validate_visible_area (tree_view);
1987 + gtk_tree_model_get_iter (tree_view->priv->model, &parent_iter, path);
1988 + _gtk_tree_view_find_node (tree_view, path, &tree2, &node2);
1989 + validate_row (tree_view, tree2, node2, &parent_iter, path);
1990 + total_height = CELL_HEIGHT (node2, vertical_separator);
1991 + children = gtk_tree_model_iter_n_children (tree_view->priv->model, &parent_iter);
1992 + for (n = 0; n < children; n++)
1994 + gtk_tree_model_iter_nth_child (tree_view->priv->model,
1995 + &child_iter, &parent_iter, n);
1997 + /* must free here so the path of last child is kept for later */
1998 + if (child_path != NULL)
1999 + gtk_tree_path_free (child_path);
2001 + child_path = gtk_tree_model_get_path (tree_view->priv->model, &child_iter);
2002 + _gtk_tree_view_find_node (tree_view, child_path, &tree2, &node2);
2004 + if (CELL_HEIGHT (node2, 0) == 0)
2005 + validate_row (tree_view, tree2, node2, &child_iter, child_path);
2007 + total_height += CELL_HEIGHT (node2, vertical_separator);
2010 + gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
2012 + /* KNOWN BUG: If no autocollapse was performed earlier above, these calls
2013 + to gtk_tree_view_scroll_to_cell do nothing although they should. */
2014 + if (total_height > visible_rect.height)
2015 + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.0, 0.0);
2017 + gtk_tree_view_scroll_to_cell (tree_view, child_path, NULL, FALSE, 0.0, 0.0);
2019 + gtk_tree_path_free (child_path);
2021 install_presize_handler (tree_view);
2023 g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
2024 @@ -11070,6 +12228,16 @@
2025 GtkRBTree *tree = NULL;
2026 GtkRBNode *node = NULL;
2028 + _gtk_tree_view_find_node (tree_view, path, &tree, &node);
2030 + /* Hildon: cursor cannot move to an insensitive row */
2031 + if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
2034 + g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path);
2038 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
2040 GtkTreePath *cursor_path;
2041 @@ -11083,7 +12251,6 @@
2042 tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
2043 tree_view->priv->model,
2045 - _gtk_tree_view_find_node (tree_view, path, &tree, &node);
2048 GtkRBTree *new_tree = NULL;
2049 @@ -11093,7 +12260,8 @@
2051 GtkTreeSelectMode mode = 0;
2053 - if (tree_view->priv->ctrl_pressed)
2054 + if (tree_view->priv->ctrl_pressed ||
2055 + tree_view->priv->pen_drag_active)
2056 mode |= GTK_TREE_SELECT_MODE_TOGGLE;
2057 if (tree_view->priv->shift_pressed)
2058 mode |= GTK_TREE_SELECT_MODE_EXTEND;
2059 @@ -11213,6 +12381,9 @@
2061 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
2062 g_return_if_fail (path != NULL);
2064 + tree_view->priv->pen_focus = FALSE;
2067 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
2069 @@ -11414,6 +12585,7 @@
2070 GtkRBNode *node = NULL;
2071 gint vertical_separator;
2072 gint horizontal_separator;
2073 + gint expander_indent;
2075 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
2076 g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
2077 @@ -11424,6 +12596,7 @@
2078 gtk_widget_style_get (GTK_WIDGET (tree_view),
2079 "vertical_separator", &vertical_separator,
2080 "horizontal_separator", &horizontal_separator,
2081 + "expander_indent", &expander_indent,
2085 @@ -11453,9 +12626,11 @@
2086 TREE_VIEW_DRAW_EXPANDERS (tree_view))
2088 gint depth = gtk_tree_path_get_depth (path) - 1;
2091 - rect->x += depth * tree_view->priv->expander_size;
2092 - rect->width -= depth * tree_view->priv->expander_size;
2093 + adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent;
2094 + rect->x += adjust;
2095 + rect->width -= adjust;
2096 rect->width = MAX (rect->width, 0);
2099 @@ -12077,8 +13252,13 @@
2100 if (gtk_tree_view_is_expander_column (tree_view, column) &&
2101 TREE_VIEW_DRAW_EXPANDERS(tree_view))
2103 - cell_area.x += depth * tree_view->priv->expander_size;
2104 - cell_area.width -= depth * tree_view->priv->expander_size;
2105 + gint adjust, expander_indent;
2107 + gtk_widget_style_get (widget, "expander_indent", &expander_indent, NULL);
2109 + adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent;
2110 + cell_area.x += adjust;
2111 + cell_area.width -= adjust;
2114 if (gtk_tree_view_column_cell_is_visible (column))
2115 @@ -13062,3 +14242,138 @@
2116 tree_view->priv->pressed_button = -1;
2119 +/* Hildon addition: iterates through columns and cells, looks for
2120 + a cell with "activatable" attribute and sets or unsets
2121 + priv->checkbox_mode accordingly (except when checkbox mode
2122 + is disabled by unsetting allow_checkbox_mode).
2125 +update_checkbox_mode (GObject *object, GParamSpec *pspec, gpointer data)
2127 + GtkTreeView *tree_view = GTK_TREE_VIEW (data);
2128 + GList *columns = gtk_tree_view_get_columns (tree_view);
2130 + gboolean allow_checkbox_mode;
2132 + g_object_get (GTK_WIDGET (data),
2133 + "allow_checkbox_mode", &allow_checkbox_mode, NULL);
2134 + g_return_if_fail (allow_checkbox_mode);
2136 + for (list = columns; list; list = list->next)
2138 + GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN (list->data);
2139 + if (gtk_tree_view_column_get_visible (col) &&
2140 + _gtk_tree_view_column_has_activatable_cell (col))
2142 + /* checkbox column found */
2143 + tree_view->priv->checkbox_mode = TRUE;
2144 + g_list_free (columns);
2149 + /* no checkbox column was found */
2150 + tree_view->priv->checkbox_mode = FALSE;
2151 + g_list_free (columns);
2155 +set_dotted_lines (GtkTreeView *tree_view, gboolean enable)
2157 + if (enable != tree_view->priv->dotted_lines)
2159 + tree_view->priv->dotted_lines = enable;
2160 + gtk_widget_queue_draw (GTK_WIDGET (tree_view));
2164 +/* This function is used to ensure two things:
2165 + * - in single selection mode, focus will always equal selection
2166 + * - in multiple selection mode, focus is removed if cursor row is
2167 + * explicitly unselected
2170 +selection_changed (GtkTreeSelection *selection, gpointer data)
2172 + GtkTreeView *tree_view = GTK_TREE_VIEW(data);
2173 + GtkTreePath *cursor_path = NULL;
2176 + /* if there are checkboxes, cursor row doesn't have to be selected */
2177 + if (tree_view->priv->checkbox_mode)
2180 + if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
2181 + cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
2183 + if (cursor_path == NULL ||
2184 + !gtk_tree_selection_path_is_selected (selection, cursor_path))
2186 + GtkTreePath *selected_path;
2187 + GtkRBTree *tree = NULL;
2188 + GtkRBNode *node = NULL;
2190 + if (gtk_tree_selection_get_mode (selection) != GTK_SELECTION_MULTIPLE &&
2191 + gtk_tree_selection_get_selected (selection, NULL, &iter))
2193 + selected_path = gtk_tree_model_get_path (tree_view->priv->model,
2195 + gtk_tree_view_real_set_cursor (tree_view, selected_path, TRUE, TRUE);
2196 + _gtk_tree_view_find_node (tree_view, selected_path, &tree, &node);
2197 + gtk_tree_view_clamp_node_visible (tree_view, tree, node);
2198 + gtk_tree_path_free (selected_path);
2199 + gtk_widget_grab_focus (GTK_WIDGET (tree_view));
2203 + gtk_tree_row_reference_free (tree_view->priv->cursor);
2204 + tree_view->priv->cursor = NULL;
2209 + gtk_tree_path_free (cursor_path);
2212 +/* Helper function for ensuring that GtkTreeView is focusable
2213 + * if and only if it contains at least one sensitive top-level row.
2214 + * Should be called whenever the existence of a sensitive top-level row
2215 + * might have changed.
2218 +check_if_can_focus (GtkTreeView *tree_view)
2220 + GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
2223 + if (model == NULL || !GTK_WIDGET_MAPPED (tree_view))
2226 + if (gtk_tree_model_get_iter_first (model, &iter) == FALSE)
2228 + GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);
2233 + GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
2237 + _gtk_tree_view_find_node (tree_view, path, &tree, &node);
2239 + if (_gtk_tree_selection_is_row_selectable (tree_view->priv->selection,
2242 + GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
2243 + if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
2244 + gtk_tree_view_real_set_cursor (tree_view, path,
2245 + !tree_view->priv->checkbox_mode,
2250 + } while (gtk_tree_model_iter_next (model, &iter));
2252 + GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS);