diff options
Diffstat (limited to 'meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff')
-rw-r--r-- | meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff | 2253 |
1 files changed, 2253 insertions, 0 deletions
diff --git a/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff new file mode 100644 index 0000000000..87ccffa868 --- /dev/null +++ b/meta/packages/gtk+/gtk+-2.6.4-1.osso7/gtktreeview.c.diff | |||
@@ -0,0 +1,2253 @@ | |||
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 | ||
3 | @@ -42,6 +42,7 @@ | ||
4 | #include "gtkentry.h" | ||
5 | #include "gtkframe.h" | ||
6 | #include "gtktreemodelsort.h" | ||
7 | +#include "gtkscrolledwindow.h" | ||
8 | |||
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) | ||
11 | @@ -114,6 +115,7 @@ | ||
12 | EXPAND_COLLAPSE_CURSOR_ROW, | ||
13 | SELECT_CURSOR_PARENT, | ||
14 | START_INTERACTIVE_SEARCH, | ||
15 | + ROW_INSENSITIVE, | ||
16 | LAST_SIGNAL | ||
17 | }; | ||
18 | |||
19 | @@ -132,7 +134,10 @@ | ||
20 | PROP_SEARCH_COLUMN, | ||
21 | PROP_FIXED_HEIGHT_MODE, | ||
22 | PROP_HOVER_SELECTION, | ||
23 | - PROP_HOVER_EXPAND | ||
24 | + PROP_HOVER_EXPAND, | ||
25 | + PROP_DOTTED_LINES, | ||
26 | + PROP_FORCE_LIST_KLUDGE, | ||
27 | + PROP_ALLOW_CHECKBOX_MODE | ||
28 | }; | ||
29 | |||
30 | static void gtk_tree_view_class_init (GtkTreeViewClass *klass); | ||
31 | @@ -338,8 +343,6 @@ | ||
32 | static void gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view, | ||
33 | GtkRBTree *tree, | ||
34 | GtkRBNode *node); | ||
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); | ||
40 | @@ -372,6 +375,18 @@ | ||
41 | gpointer data); | ||
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, | ||
45 | + GParamSpec *pspec, | ||
46 | + gpointer data); | ||
47 | +static void set_dotted_lines (GtkTreeView *tree_view, | ||
48 | + gboolean enable); | ||
49 | +static void selection_changed (GtkTreeSelection *selection, | ||
50 | + gpointer data); | ||
51 | +static void check_if_can_focus (GtkTreeView *tree_view); | ||
52 | +static gint scroll_row_timeout (gpointer data); | ||
53 | + | ||
54 | +static void add_scroll_timeout (GtkTreeView *tree_view); | ||
55 | +static void remove_scroll_timeout (GtkTreeView *tree_view); | ||
56 | |||
57 | /* interactive search */ | ||
58 | static void gtk_tree_view_ensure_interactive_directory (GtkTreeView *tree_view); | ||
59 | @@ -694,8 +709,54 @@ | ||
60 | FALSE, | ||
61 | G_PARAM_READWRITE)); | ||
62 | |||
63 | + /** | ||
64 | + * GtkTreeView:dotted-lines: | ||
65 | + * | ||
66 | + * Enables or disables the dotted lines for hierarchical trees. | ||
67 | + * Hildon patch. | ||
68 | + */ | ||
69 | + g_object_class_install_property (o_class, | ||
70 | + PROP_DOTTED_LINES, | ||
71 | + g_param_spec_boolean ("dotted_lines", | ||
72 | + P_("Dotted Lines"), | ||
73 | + P_("Whether to show or hide dotted lines for hierarchical trees"), | ||
74 | + FALSE, | ||
75 | + G_PARAM_READWRITE)); | ||
76 | + | ||
77 | + /** | ||
78 | + * GtkTreeView:force-list-kludge: | ||
79 | + * | ||
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. | ||
84 | + */ | ||
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"), | ||
90 | + FALSE, | ||
91 | + G_PARAM_READWRITE)); | ||
92 | + | ||
93 | + /** | ||
94 | + * GtkTreeView:enable-checkbox-mode: | ||
95 | + * | ||
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. | ||
99 | + */ | ||
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"), | ||
105 | + TRUE, | ||
106 | + G_PARAM_READWRITE)); | ||
107 | + | ||
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 | ||
113 | |||
114 | @@ -709,6 +770,15 @@ | ||
115 | G_PARAM_READABLE)); | ||
116 | |||
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"), | ||
121 | + 0, | ||
122 | + G_MAXINT, | ||
123 | + _TREE_VIEW_EXPANDER_INDENT, | ||
124 | + G_PARAM_READABLE)); | ||
125 | + | ||
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"), | ||
130 | @@ -754,6 +824,13 @@ | ||
131 | GDK_TYPE_COLOR, | ||
132 | G_PARAM_READABLE)); | ||
133 | |||
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"), | ||
138 | + TRUE, | ||
139 | + G_PARAM_READABLE)); | ||
140 | + | ||
141 | /* Signals */ | ||
142 | widget_class->set_scroll_adjustments_signal = | ||
143 | g_signal_new ("set_scroll_adjustments", | ||
144 | @@ -917,6 +994,16 @@ | ||
145 | _gtk_marshal_BOOLEAN__NONE, | ||
146 | G_TYPE_BOOLEAN, 0); | ||
147 | |||
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), | ||
153 | + NULL, NULL, | ||
154 | + _gtk_marshal_VOID__OBJECT, | ||
155 | + G_TYPE_NONE, 1, | ||
156 | + GTK_TYPE_TREE_PATH); | ||
157 | + | ||
158 | /* Key bindings */ | ||
159 | gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0, | ||
160 | GTK_MOVEMENT_DISPLAY_LINES, -1); | ||
161 | @@ -1004,12 +1091,13 @@ | ||
162 | |||
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);*/ | ||
173 | |||
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); | ||
178 | |||
179 | gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start_interactive_search", 0); | ||
180 | + | ||
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); | ||
190 | } | ||
191 | |||
192 | static void | ||
193 | gtk_tree_view_init (GtkTreeView *tree_view) | ||
194 | { | ||
195 | tree_view->priv = g_new0 (GtkTreeViewPrivate, 1); | ||
196 | - GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS); | ||
197 | + | ||
198 | + /* Hildon: focus cannot be gained until at least one row is added */ | ||
199 | + GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS); | ||
200 | |||
201 | gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE); | ||
202 | |||
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; | ||
208 | |||
209 | /* We need some padding */ | ||
210 | tree_view->priv->dy = 0; | ||
211 | @@ -1165,6 +1265,26 @@ | ||
212 | |||
213 | tree_view->priv->hover_selection = FALSE; | ||
214 | tree_view->priv->hover_expand = FALSE; | ||
215 | + | ||
216 | + tree_view->priv->ctrl_pressed = FALSE; | ||
217 | + tree_view->priv->shift_pressed = FALSE; | ||
218 | + | ||
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; | ||
229 | + | ||
230 | + /* Hildon: cursor should follow when selection changes */ | ||
231 | + g_signal_connect (tree_view->priv->selection, "changed", | ||
232 | + G_CALLBACK (selection_changed), tree_view); | ||
233 | + | ||
234 | + gtk_widget_set_name (GTK_WIDGET (tree_view), "treeview"); | ||
235 | } | ||
236 | |||
237 | |||
238 | @@ -1223,6 +1343,27 @@ | ||
239 | case PROP_HOVER_EXPAND: | ||
240 | tree_view->priv->hover_expand = g_value_get_boolean (value); | ||
241 | break; | ||
242 | + case PROP_DOTTED_LINES: | ||
243 | + set_dotted_lines (tree_view, g_value_get_boolean (value)); | ||
244 | + break; | ||
245 | + case PROP_FORCE_LIST_KLUDGE: | ||
246 | + tree_view->priv->force_list_kludge = g_value_get_boolean (value); | ||
247 | + break; | ||
248 | + case PROP_ALLOW_CHECKBOX_MODE: | ||
249 | + if ((tree_view->priv->allow_checkbox_mode = g_value_get_boolean (value))) | ||
250 | + { | ||
251 | + gtk_widget_set_name (GTK_WIDGET(tree_view), "treeview"); | ||
252 | + update_checkbox_mode (NULL, NULL, tree_view); | ||
253 | + } | ||
254 | + else | ||
255 | + { | ||
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; | ||
261 | + } | ||
262 | + break; | ||
263 | default: | ||
264 | break; | ||
265 | } | ||
266 | @@ -1276,6 +1417,15 @@ | ||
267 | case PROP_HOVER_EXPAND: | ||
268 | g_value_set_boolean (value, tree_view->priv->hover_expand); | ||
269 | break; | ||
270 | + case PROP_DOTTED_LINES: | ||
271 | + g_value_set_boolean (value, tree_view->priv->dotted_lines); | ||
272 | + break; | ||
273 | + case PROP_FORCE_LIST_KLUDGE: | ||
274 | + g_value_set_boolean (value, tree_view->priv->force_list_kludge); | ||
275 | + break; | ||
276 | + case PROP_ALLOW_CHECKBOX_MODE: | ||
277 | + g_value_set_boolean (value, tree_view->priv->allow_checkbox_mode); | ||
278 | + break; | ||
279 | default: | ||
280 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
281 | break; | ||
282 | @@ -1376,6 +1526,27 @@ | ||
283 | tree_view->priv->destroy_count_data = NULL; | ||
284 | } | ||
285 | |||
286 | + if (tree_view->priv->first_drag_row) | ||
287 | + { | ||
288 | + gtk_tree_row_reference_free (tree_view->priv->first_drag_row); | ||
289 | + tree_view->priv->first_drag_row = NULL; | ||
290 | + } | ||
291 | + if (tree_view->priv->last_drag_row) | ||
292 | + { | ||
293 | + gtk_tree_row_reference_free (tree_view->priv->last_drag_row); | ||
294 | + tree_view->priv->last_drag_row = NULL; | ||
295 | + } | ||
296 | + if (tree_view->priv->queued_expand_row) | ||
297 | + { | ||
298 | + gtk_tree_row_reference_free (tree_view->priv->queued_expand_row); | ||
299 | + tree_view->priv->queued_expand_row = NULL; | ||
300 | + } | ||
301 | + if (tree_view->priv->queued_select_row) | ||
302 | + { | ||
303 | + gtk_tree_row_reference_free (tree_view->priv->queued_select_row); | ||
304 | + tree_view->priv->queued_select_row = NULL; | ||
305 | + } | ||
306 | + | ||
307 | gtk_tree_row_reference_free (tree_view->priv->cursor); | ||
308 | tree_view->priv->cursor = NULL; | ||
309 | |||
310 | @@ -1494,6 +1665,8 @@ | ||
311 | gtk_tree_view_map_buttons (tree_view); | ||
312 | |||
313 | gdk_window_show (widget->window); | ||
314 | + | ||
315 | + check_if_can_focus (tree_view); | ||
316 | } | ||
317 | |||
318 | static void | ||
319 | @@ -1895,6 +2068,8 @@ | ||
320 | gint full_requested_width = 0; | ||
321 | gint number_of_expand_columns = 0; | ||
322 | gboolean rtl; | ||
323 | + GtkWidget *scroll; | ||
324 | + GtkPolicyType ptype; | ||
325 | |||
326 | tree_view = GTK_TREE_VIEW (widget); | ||
327 | |||
328 | @@ -1969,6 +2144,19 @@ | ||
329 | allocation.x = width; | ||
330 | column->width = real_requested_width; | ||
331 | |||
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); | ||
335 | + if ((!scroll || | ||
336 | + (gtk_scrolled_window_get_policy (GTK_SCROLLED_WINDOW (scroll), &ptype, NULL), ptype == GTK_POLICY_NEVER)) | ||
337 | + && (width + real_requested_width > widget->allocation.width)) | ||
338 | + { | ||
339 | + column->width = widget->allocation.width - width; | ||
340 | + if (column->width < 1) | ||
341 | + column->width = 1; | ||
342 | + gtk_widget_queue_draw (widget); | ||
343 | + } | ||
344 | + | ||
345 | if (column->expand) | ||
346 | { | ||
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); | ||
350 | } | ||
351 | |||
352 | +/* helper function for gtk_tree_view_button_press */ | ||
353 | +static void | ||
354 | +activate_callback (GtkTreeModel *model, | ||
355 | + GtkTreePath *path, | ||
356 | + GtkTreeIter *iter, | ||
357 | + gpointer data) | ||
358 | +{ | ||
359 | + GtkTreeView *tree_view = GTK_TREE_VIEW (data); | ||
360 | + | ||
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)) ) | ||
364 | + return; | ||
365 | + | ||
366 | + gtk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column); | ||
367 | +} | ||
368 | + | ||
369 | static gboolean | ||
370 | gtk_tree_view_button_press (GtkWidget *widget, | ||
371 | GdkEventButton *event) | ||
372 | @@ -2166,6 +2371,7 @@ | ||
373 | gint vertical_separator; | ||
374 | gint horizontal_separator; | ||
375 | gboolean rtl; | ||
376 | + gint expander_indent; | ||
377 | |||
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, | ||
385 | NULL); | ||
386 | |||
387 | |||
388 | @@ -2199,6 +2406,14 @@ | ||
389 | gint column_handled_click = FALSE; | ||
390 | gboolean row_double_click = FALSE; | ||
391 | gboolean rtl; | ||
392 | + gboolean force_list_kludge; | ||
393 | + GtkRBNode *cursor = NULL; | ||
394 | + gboolean focus_grab = FALSE; | ||
395 | + | ||
396 | + if (!GTK_WIDGET_HAS_FOCUS (widget)) | ||
397 | + focus_grab = TRUE; | ||
398 | + | ||
399 | + GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS); | ||
400 | |||
401 | /* Empty tree? */ | ||
402 | if (tree_view->priv->tree == NULL) | ||
403 | @@ -2207,7 +2422,9 @@ | ||
404 | return TRUE; | ||
405 | } | ||
406 | |||
407 | - /* are we in an arrow? */ | ||
408 | + /* In Hildon we don't want to use the arrows */ | ||
409 | +#if 0 | ||
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)) | ||
413 | { | ||
414 | @@ -2226,6 +2443,7 @@ | ||
415 | grab_focus_and_unset_draw_keyfocus (tree_view); | ||
416 | return TRUE; | ||
417 | } | ||
418 | +#endif | ||
419 | |||
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; | ||
425 | |||
426 | + if (tree_view->priv->first_drag_row) | ||
427 | + { | ||
428 | + gtk_tree_row_reference_free (tree_view->priv->first_drag_row); | ||
429 | + tree_view->priv->first_drag_row = NULL; | ||
430 | + } | ||
431 | + if (tree_view->priv->last_drag_row) | ||
432 | + { | ||
433 | + gtk_tree_row_reference_free (tree_view->priv->last_drag_row); | ||
434 | + tree_view->priv->last_drag_row = NULL; | ||
435 | + } | ||
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); | ||
439 | + | ||
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); | ||
443 | + | ||
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))) | ||
452 | + { | ||
453 | + gpointer drag_data; | ||
454 | + | ||
455 | + tree_view->priv->pen_down = TRUE; | ||
456 | + tree_view->priv->pen_focus = TRUE; | ||
457 | + | ||
458 | + /* also block attached dnd signal handler */ | ||
459 | + drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); | ||
460 | + if (drag_data) | ||
461 | + g_signal_handlers_block_matched (widget, | ||
462 | + G_SIGNAL_MATCH_DATA, | ||
463 | + 0, 0, NULL, NULL, | ||
464 | + drag_data); | ||
465 | + } | ||
466 | + | ||
467 | + /* For the Hildon buttonpress find out the previously selected row */ | ||
468 | + GtkRBTree *cursor_tree = NULL; | ||
469 | + GtkTreePath *cursor_path = NULL; | ||
470 | + | ||
471 | + if (tree_view->priv->cursor) | ||
472 | + { | ||
473 | + cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); | ||
474 | + if (cursor_path) | ||
475 | + { | ||
476 | + _gtk_tree_view_find_node (tree_view, cursor_path, | ||
477 | + &cursor_tree, &cursor); | ||
478 | + gtk_tree_path_free (cursor_path); | ||
479 | + } | ||
480 | + } | ||
481 | + | ||
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); | ||
485 | |||
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)) | ||
491 | { | ||
492 | - cell_area.x += depth * tree_view->priv->expander_size; | ||
493 | - cell_area.width -= depth * tree_view->priv->expander_size; | ||
494 | + gint adjust; | ||
495 | + | ||
496 | + adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent; | ||
497 | + cell_area.x += adjust; | ||
498 | + cell_area.width -= adjust; | ||
499 | } | ||
500 | break; | ||
501 | } | ||
502 | @@ -2364,15 +2644,19 @@ | ||
503 | */ | ||
504 | if (event->type == GDK_BUTTON_PRESS) | ||
505 | { | ||
506 | + /* Hildon: ignore Ctrl and Shift */ | ||
507 | +#if 0 | ||
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; | ||
512 | +#endif | ||
513 | |||
514 | focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x); | ||
515 | if (focus_cell) | ||
516 | gtk_tree_view_column_focus_cell (column, focus_cell); | ||
517 | |||
518 | +#if 0 | ||
519 | if (event->state & GDK_CONTROL_MASK) | ||
520 | { | ||
521 | gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE); | ||
522 | @@ -2387,6 +2671,86 @@ | ||
523 | { | ||
524 | gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE); | ||
525 | } | ||
526 | +#endif | ||
527 | + if (tree_view->priv->checkbox_mode) | ||
528 | + { | ||
529 | + GtkRBTree *tree = NULL; | ||
530 | + GtkRBNode *node = NULL; | ||
531 | + | ||
532 | + _gtk_tree_view_find_node (tree_view, path, &tree, &node); | ||
533 | + | ||
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, | ||
538 | + node, path)) | ||
539 | + { | ||
540 | + gtk_tree_view_real_set_cursor (tree_view, path, | ||
541 | + FALSE, TRUE); | ||
542 | + gtk_tree_view_real_toggle_cursor_row (tree_view); | ||
543 | + } | ||
544 | + else | ||
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); | ||
548 | + } | ||
549 | + else | ||
550 | + { | ||
551 | + gboolean queue_row = TRUE; | ||
552 | + gboolean force_list_kludge; | ||
553 | + | ||
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)) | ||
562 | + { | ||
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) | ||
569 | + { | ||
570 | + gtk_tree_selection_selected_foreach (tree_view->priv->selection, | ||
571 | + activate_callback, | ||
572 | + tree_view); | ||
573 | + queue_row = FALSE; | ||
574 | + } | ||
575 | + } | ||
576 | + | ||
577 | + if (queue_row && | ||
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)) | ||
580 | + { | ||
581 | + GtkTreePath *old_cursor_path = NULL; | ||
582 | + | ||
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); | ||
589 | + | ||
590 | + /* however, move focus */ | ||
591 | + if (tree_view->priv->cursor) | ||
592 | + { | ||
593 | + old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); | ||
594 | + gtk_tree_row_reference_free (tree_view->priv->cursor); | ||
595 | + } | ||
596 | + tree_view->priv->cursor = gtk_tree_row_reference_new (tree_view->priv->model, | ||
597 | + path); | ||
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); | ||
601 | + } | ||
602 | + else | ||
603 | + gtk_tree_view_real_set_cursor (tree_view, path, | ||
604 | + queue_row, TRUE); | ||
605 | + } | ||
606 | |||
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; | ||
611 | } | ||
612 | |||
613 | + /* Hildon: if selected row is tapped -> the row gets activated and expands */ | ||
614 | + if (!focus_grab) | ||
615 | + { | ||
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); | ||
620 | + } | ||
621 | + | ||
622 | /* Test if a double click happened on the same row. */ | ||
623 | if (event->button == 1) | ||
624 | { | ||
625 | @@ -2433,6 +2806,8 @@ | ||
626 | } | ||
627 | } | ||
628 | |||
629 | + /* Hildon doesn't support double clicks */ | ||
630 | +#if 0 | ||
631 | if (row_double_click) | ||
632 | { | ||
633 | if (tree_view->priv->last_button_press) | ||
634 | @@ -2443,6 +2818,7 @@ | ||
635 | tree_view->priv->last_button_press_2 = NULL; | ||
636 | } | ||
637 | else | ||
638 | +#endif | ||
639 | { | ||
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 @@ | ||
643 | |||
644 | tree_view = GTK_TREE_VIEW (widget); | ||
645 | |||
646 | + /* unblock attached dnd signal handler */ | ||
647 | + if (tree_view->priv->pen_down) | ||
648 | + { | ||
649 | + gpointer drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); | ||
650 | + if (drag_data) | ||
651 | + g_signal_handlers_unblock_matched (widget, | ||
652 | + G_SIGNAL_MATCH_DATA, | ||
653 | + 0, 0, NULL, NULL, | ||
654 | + drag_data); | ||
655 | + } | ||
656 | + | ||
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); | ||
667 | + | ||
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); | ||
670 | |||
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); | ||
674 | |||
675 | + if (gtk_tree_row_reference_valid (tree_view->priv->queued_select_row)) | ||
676 | + { | ||
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); | ||
680 | + | ||
681 | + gtk_tree_view_real_set_cursor (tree_view, | ||
682 | + gtk_tree_row_reference_get_path (tree_view->priv->queued_select_row), | ||
683 | + FALSE, TRUE); | ||
684 | + gtk_tree_row_reference_free (tree_view->priv->queued_select_row); | ||
685 | + tree_view->priv->queued_select_row = NULL; | ||
686 | + } | ||
687 | + | ||
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) | ||
692 | + { | ||
693 | + GtkTreePath *queued_expand_path; | ||
694 | + GtkRBTree *tree; | ||
695 | + GtkRBNode *node; | ||
696 | + GtkRBNode *old_node; | ||
697 | + gint y; | ||
698 | + | ||
699 | + queued_expand_path = | ||
700 | + gtk_tree_row_reference_get_path (tree_view->priv->queued_expand_row); | ||
701 | + | ||
702 | + if (queued_expand_path) | ||
703 | + { | ||
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); | ||
707 | + | ||
708 | + _gtk_tree_view_find_node (tree_view, queued_expand_path, | ||
709 | + &tree, &old_node); | ||
710 | + | ||
711 | + if (node && old_node == node) | ||
712 | + { | ||
713 | + if (node->children == NULL) | ||
714 | + gtk_tree_view_real_expand_row (tree_view, | ||
715 | + queued_expand_path, | ||
716 | + tree, | ||
717 | + node, | ||
718 | + FALSE, TRUE); | ||
719 | + else | ||
720 | + gtk_tree_view_real_collapse_row (tree_view, | ||
721 | + queued_expand_path, | ||
722 | + tree, | ||
723 | + node, | ||
724 | + TRUE); | ||
725 | + } | ||
726 | + | ||
727 | + gtk_tree_path_free (queued_expand_path); | ||
728 | + } | ||
729 | + | ||
730 | + gtk_tree_row_reference_free( tree_view->priv->queued_expand_row); | ||
731 | + tree_view->priv->queued_expand_row = NULL; | ||
732 | + } | ||
733 | + | ||
734 | if (tree_view->priv->button_pressed_node == NULL) | ||
735 | return FALSE; | ||
736 | |||
737 | @@ -3311,6 +3768,7 @@ | ||
738 | GtkTreeView *tree_view; | ||
739 | GtkRBTree *tree; | ||
740 | GtkRBNode *node; | ||
741 | + GtkTreePath *path, *last_drag_path, *current_path; | ||
742 | gint new_y; | ||
743 | |||
744 | tree_view = (GtkTreeView *) widget; | ||
745 | @@ -3319,7 +3777,8 @@ | ||
746 | return FALSE; | ||
747 | |||
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); | ||
753 | |||
754 | new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y); | ||
755 | @@ -3328,6 +3787,99 @@ | ||
756 | |||
757 | _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node); | ||
758 | |||
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)) | ||
763 | + { | ||
764 | + gint direction; | ||
765 | + | ||
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); | ||
769 | + | ||
770 | + if (direction != 0) | ||
771 | + { | ||
772 | + current_path = gtk_tree_path_copy (last_drag_path); | ||
773 | + | ||
774 | + /* we must ensure that no row is skipped because stylus | ||
775 | + is moving faster than motion events are generated */ | ||
776 | + do { | ||
777 | + if (direction > 0) | ||
778 | + { | ||
779 | + /* gtk_tree_path_next does not let us know when it failed */ | ||
780 | + GtkTreeIter iter; | ||
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)) | ||
783 | + break; | ||
784 | + | ||
785 | + gtk_tree_path_next (current_path); | ||
786 | + } | ||
787 | + else if (!gtk_tree_path_prev (current_path)) | ||
788 | + break; | ||
789 | + | ||
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); | ||
793 | + | ||
794 | + if (tree_view->priv->checkbox_mode) | ||
795 | + { | ||
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, | ||
799 | + current_path); | ||
800 | + else | ||
801 | + gtk_tree_selection_unselect_path (tree_view->priv->selection, | ||
802 | + current_path); | ||
803 | + } | ||
804 | + else | ||
805 | + { | ||
806 | + if (gtk_tree_selection_path_is_selected (tree_view->priv->selection, | ||
807 | + current_path)) | ||
808 | + { | ||
809 | + /* apparently we have reversed the pen drag direction */ | ||
810 | + GtkTreePath *reverse_path; | ||
811 | + gint reverse_direction; | ||
812 | + | ||
813 | + reverse_direction = gtk_tree_path_compare (current_path, | ||
814 | + last_drag_path); | ||
815 | + reverse_path = gtk_tree_path_copy (last_drag_path); | ||
816 | + do { | ||
817 | + gtk_tree_selection_unselect_path (tree_view->priv->selection, | ||
818 | + reverse_path); | ||
819 | + tree_view->priv->pen_drag_reverse = TRUE; | ||
820 | + if (reverse_direction > 0) | ||
821 | + { | ||
822 | + GtkTreeIter iter; | ||
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)) | ||
825 | + break; | ||
826 | + | ||
827 | + gtk_tree_path_next (reverse_path); | ||
828 | + } | ||
829 | + else if (!gtk_tree_path_prev (reverse_path)) | ||
830 | + break; | ||
831 | + } while (gtk_tree_path_compare (reverse_path, current_path) != 0); | ||
832 | + gtk_tree_path_free (reverse_path); | ||
833 | + } | ||
834 | + else | ||
835 | + { | ||
836 | + gtk_tree_selection_select_path (tree_view->priv->selection, | ||
837 | + current_path); | ||
838 | + tree_view->priv->pen_drag_reverse = FALSE; | ||
839 | + } | ||
840 | + } | ||
841 | + } while (gtk_tree_path_compare(current_path, path) != 0); | ||
842 | + gtk_tree_path_free (current_path); | ||
843 | + | ||
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); | ||
849 | + } | ||
850 | + } | ||
851 | + | ||
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 @@ | ||
856 | 1, 1, w, h); | ||
857 | } | ||
858 | |||
859 | +/* Hildon: helper function for dotted slash drawing; | ||
860 | + returns TRUE or FALSE, depending it there are | ||
861 | + more nodes at current level */ | ||
862 | +static gboolean | ||
863 | +iter_has_next (GtkTreeModel *model, GtkTreeIter *iter) | ||
864 | +{ | ||
865 | + GtkTreeIter *check_iter; | ||
866 | + gboolean result; | ||
867 | + | ||
868 | + check_iter = gtk_tree_iter_copy(iter); | ||
869 | + result = gtk_tree_model_iter_next (model, check_iter); | ||
870 | + | ||
871 | + gtk_tree_iter_free (check_iter); | ||
872 | + return result; | ||
873 | +} | ||
874 | + | ||
875 | /* Warning: Very scary function. | ||
876 | * Modify at your own risk | ||
877 | * | ||
878 | @@ -3433,16 +4001,25 @@ | ||
879 | guint flags; | ||
880 | gint highlight_x; | ||
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; | ||
886 | GList *last_column; | ||
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; | ||
893 | gboolean rtl; | ||
894 | gint n_visible_columns; | ||
895 | + gboolean dottedlines, passivefocus, res; | ||
896 | + | ||
897 | + /* Hildon: these variables are added for dotted slash drawing | ||
898 | + (Hierarchical listbox) */ | ||
899 | + gint i; | ||
900 | + gint node_elements = 64; | ||
901 | + gboolean *iter_value = NULL; | ||
902 | + GtkTreeIter node_iter, parent_iter; | ||
903 | |||
904 | g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE); | ||
905 | |||
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, | ||
912 | NULL); | ||
913 | |||
914 | + g_object_get (widget, "dotted_lines", &dottedlines, NULL); | ||
915 | + | ||
916 | if (tree_view->priv->tree == NULL) | ||
917 | { | ||
918 | draw_empty_focus (tree_view, &event->area); | ||
919 | @@ -3478,6 +4059,8 @@ | ||
920 | if (node == NULL) | ||
921 | return TRUE; | ||
922 | |||
923 | + iter_value = g_new (gboolean, node_elements); | ||
924 | + | ||
925 | /* find the path for the node */ | ||
926 | path = _gtk_tree_view_find_path ((GtkTreeView *)widget, | ||
927 | tree, | ||
928 | @@ -3486,11 +4069,25 @@ | ||
929 | &iter, | ||
930 | path); | ||
931 | depth = gtk_tree_path_get_depth (path); | ||
932 | + | ||
933 | + node_iter = iter; | ||
934 | + for (i = depth - 1; i >= 1; i--) | ||
935 | + { | ||
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) | ||
939 | + { | ||
940 | + node_elements *= 2; | ||
941 | + iter_value = g_renew (gboolean, iter_value, node_elements); | ||
942 | + if (!iter_value) | ||
943 | + goto done; | ||
944 | + } | ||
945 | + iter_value[i] = iter_has_next (tree_view->priv->model, &parent_iter); | ||
946 | + node_iter = parent_iter; | ||
947 | + } | ||
948 | + gtk_tree_model_get_iter (tree_view->priv->model, &iter, path); | ||
949 | gtk_tree_path_free (path); | ||
950 | |||
951 | - cursor_path = NULL; | ||
952 | - drag_dest_path = NULL; | ||
953 | - | ||
954 | if (tree_view->priv->cursor) | ||
955 | cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); | ||
956 | |||
957 | @@ -3533,6 +4130,7 @@ | ||
958 | do | ||
959 | { | ||
960 | gboolean parity; | ||
961 | + gboolean is_first = TRUE; | ||
962 | gboolean is_separator = FALSE; | ||
963 | |||
964 | if (tree_view->priv->row_separator_func) | ||
965 | @@ -3570,6 +4168,7 @@ | ||
966 | GtkTreeViewColumn *column = list->data; | ||
967 | const gchar *detail = NULL; | ||
968 | GtkStateType state; | ||
969 | + gboolean is_last = (rtl ? !list->prev : !list->next); | ||
970 | |||
971 | if (!column->visible) | ||
972 | continue; | ||
973 | @@ -3660,31 +4259,152 @@ | ||
974 | else | ||
975 | state = GTK_STATE_NORMAL; | ||
976 | |||
977 | - /* Draw background */ | ||
978 | - gtk_paint_flat_box (widget->style, | ||
979 | - event->window, | ||
980 | - state, | ||
981 | - GTK_SHADOW_NONE, | ||
982 | - &event->area, | ||
983 | - widget, | ||
984 | - detail, | ||
985 | - background_area.x, | ||
986 | - background_area.y, | ||
987 | - background_area.width, | ||
988 | - background_area.height); | ||
989 | + if (tree_view->priv->pen_focus) | ||
990 | + { | ||
991 | + if (node != cursor || | ||
992 | + (!GTK_WIDGET_HAS_FOCUS (widget) && !passivefocus)) | ||
993 | + { | ||
994 | + if ((flags & GTK_CELL_RENDERER_SELECTED) | ||
995 | + && !tree_view->priv->checkbox_mode) | ||
996 | + state = GTK_STATE_SELECTED; | ||
997 | + else | ||
998 | + state = GTK_STATE_NORMAL; | ||
999 | + | ||
1000 | + /* Draw background */ | ||
1001 | + gtk_paint_flat_box (widget->style, | ||
1002 | + event->window, | ||
1003 | + state, | ||
1004 | + GTK_SHADOW_NONE, | ||
1005 | + &event->area, | ||
1006 | + widget, | ||
1007 | + detail, | ||
1008 | + background_area.x, | ||
1009 | + background_area.y, | ||
1010 | + background_area.width, | ||
1011 | + background_area.height); | ||
1012 | + } | ||
1013 | + else if ((flags & GTK_CELL_RENDERER_SELECTED) && | ||
1014 | + !tree_view->priv->checkbox_mode && | ||
1015 | + node != cursor) | ||
1016 | + { | ||
1017 | + gtk_paint_flat_box (widget->style, | ||
1018 | + event->window, | ||
1019 | + GTK_STATE_SELECTED, | ||
1020 | + GTK_SHADOW_NONE, | ||
1021 | + &event->area, | ||
1022 | + widget, | ||
1023 | + detail, | ||
1024 | + background_area.x, | ||
1025 | + background_area.y, | ||
1026 | + background_area.width, | ||
1027 | + background_area.height); | ||
1028 | + } | ||
1029 | + } | ||
1030 | + else | ||
1031 | + { | ||
1032 | + /* Draw background */ | ||
1033 | + gtk_paint_flat_box (widget->style, | ||
1034 | + event->window, | ||
1035 | + state, | ||
1036 | + GTK_SHADOW_NONE, | ||
1037 | + &event->area, | ||
1038 | + widget, | ||
1039 | + detail, | ||
1040 | + background_area.x, | ||
1041 | + background_area.y, | ||
1042 | + background_area.width, | ||
1043 | + background_area.height); | ||
1044 | + } | ||
1045 | + | ||
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))) | ||
1051 | + { | ||
1052 | + gtk_paint_focus (widget->style, | ||
1053 | + event->window, | ||
1054 | + GTK_STATE_ACTIVE, | ||
1055 | + &event->area, | ||
1056 | + widget, | ||
1057 | + (is_first | ||
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); | ||
1064 | + | ||
1065 | + is_first = FALSE; | ||
1066 | + } | ||
1067 | + else if (node == cursor && passivefocus && | ||
1068 | + !GTK_WIDGET_HAS_FOCUS (widget)) | ||
1069 | + { | ||
1070 | + GtkStyle *style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget), | ||
1071 | + "hildon-focus", | ||
1072 | + NULL, | ||
1073 | + G_TYPE_NONE); | ||
1074 | + gtk_style_attach (style, event->window); | ||
1075 | + | ||
1076 | + gtk_paint_focus (style, event->window, GTK_STATE_SELECTED, | ||
1077 | + &event->area, widget, | ||
1078 | + (is_first | ||
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); | ||
1085 | + | ||
1086 | + is_first = FALSE; | ||
1087 | + } | ||
1088 | + | ||
1089 | + if (node == cursor) | ||
1090 | + { | ||
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))); | ||
1099 | + | ||
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); | ||
1102 | + } | ||
1103 | |||
1104 | if (gtk_tree_view_is_expander_column (tree_view, column) && | ||
1105 | TREE_VIEW_DRAW_EXPANDERS(tree_view)) | ||
1106 | { | ||
1107 | + gint px, px2, py, i; | ||
1108 | + | ||
1109 | + if (depth <= 1) | ||
1110 | + px = 0; | ||
1111 | + else | ||
1112 | + px = (depth - 1) * tree_view->priv->expander_size + | ||
1113 | + (depth - 2) * expander_indent; | ||
1114 | + | ||
1115 | + /* Hildonlike hack for making the indent look better. | ||
1116 | + * indent is added to all rows except the first one */ | ||
1117 | + | ||
1118 | if (!rtl) | ||
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; | ||
1123 | |||
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. | ||
1127 | */ | ||
1128 | highlight_x = cell_area.x; | ||
1129 | + | ||
1130 | + if (!GTK_WIDGET_IS_SENSITIVE (widget)) | ||
1131 | + { | ||
1132 | + flags &= ~ (GTK_CELL_RENDERER_PRELIT + GTK_CELL_RENDERER_INSENSITIVE + | ||
1133 | + GTK_CELL_RENDERER_FOCUSED); | ||
1134 | + flags &= GTK_CELL_RENDERER_INSENSITIVE; | ||
1135 | + } | ||
1136 | + | ||
1137 | if (is_separator) | ||
1138 | gtk_paint_hline (widget->style, | ||
1139 | event->window, | ||
1140 | @@ -3702,6 +4422,48 @@ | ||
1141 | &cell_area, | ||
1142 | &event->area, | ||
1143 | flags); | ||
1144 | + | ||
1145 | + /* Hildon dotted slash line drawing for Hierarchical Listbox | ||
1146 | + widget */ | ||
1147 | + if (dottedlines) | ||
1148 | + { | ||
1149 | + py = cell_area.y + cell_area.height / 2; | ||
1150 | + px2 = depth * tree_view->priv->expander_size + | ||
1151 | + (depth - 1) * expander_indent; | ||
1152 | + | ||
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); | ||
1155 | + | ||
1156 | + gdk_draw_line (tree_view->priv->bin_window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], | ||
1157 | + px, py, px2, py); | ||
1158 | + | ||
1159 | + if (depth > 1) | ||
1160 | + { | ||
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)) | ||
1164 | + { | ||
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); | ||
1167 | + } | ||
1168 | + } | ||
1169 | + | ||
1170 | + if (node->children) | ||
1171 | + { | ||
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); | ||
1174 | + } | ||
1175 | + for (i = depth - 1; i >= 2; i--) | ||
1176 | + { | ||
1177 | + if (iter_value[i]) | ||
1178 | + { | ||
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); | ||
1182 | + } | ||
1183 | + } | ||
1184 | + } | ||
1185 | + | ||
1186 | if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT) | ||
1187 | { | ||
1188 | gint x, y; | ||
1189 | @@ -3803,6 +4565,8 @@ | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | + /* Hildon: disabled this */ | ||
1194 | +#if 0 | ||
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 @@ | ||
1199 | width, | ||
1200 | ROW_HEIGHT (tree_view, BACKGROUND_HEIGHT (node))); | ||
1201 | } | ||
1202 | +#endif | ||
1203 | |||
1204 | y_offset += max_height; | ||
1205 | if (node->children) | ||
1206 | @@ -3847,6 +4612,17 @@ | ||
1207 | has_child = gtk_tree_model_iter_children (tree_view->priv->model, | ||
1208 | &iter, | ||
1209 | &parent); | ||
1210 | + | ||
1211 | + /* Check if we need to grow array */ | ||
1212 | + if (depth >= node_elements - 1) | ||
1213 | + { | ||
1214 | + node_elements *= 2; | ||
1215 | + iter_value = g_renew (gboolean, iter_value, node_elements); | ||
1216 | + if (!iter_value) | ||
1217 | + goto done; | ||
1218 | + } | ||
1219 | + iter_value[depth] = iter_has_next (tree_view->priv->model, &parent); | ||
1220 | + | ||
1221 | depth++; | ||
1222 | |||
1223 | /* Sanity Check! */ | ||
1224 | @@ -3897,6 +4673,9 @@ | ||
1225 | if (drag_dest_path) | ||
1226 | gtk_tree_path_free (drag_dest_path); | ||
1227 | |||
1228 | + if (iter_value) | ||
1229 | + g_free (iter_value); | ||
1230 | + | ||
1231 | return FALSE; | ||
1232 | } | ||
1233 | |||
1234 | @@ -4179,6 +4958,63 @@ | ||
1235 | |||
1236 | rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL); | ||
1237 | |||
1238 | + /* Special Hildon keyboard interactions */ | ||
1239 | + if (event->keyval == GDK_Escape) | ||
1240 | + gtk_tree_selection_unselect_all (tree_view->priv->selection); | ||
1241 | + | ||
1242 | + if (event->keyval == GDK_Return && | ||
1243 | + gtk_tree_row_reference_valid (tree_view->priv->cursor)) | ||
1244 | + { | ||
1245 | + gboolean force_list_kludge; | ||
1246 | + | ||
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)) | ||
1251 | + { | ||
1252 | + /* text listbox */ | ||
1253 | + if (tree_view->priv->checkbox_mode) | ||
1254 | + { | ||
1255 | + /* multisel with checkboxes: select key toggles focused */ | ||
1256 | + gtk_tree_view_real_toggle_cursor_row (tree_view); | ||
1257 | + } | ||
1258 | + else | ||
1259 | + { | ||
1260 | + /* no checkboxes: select key activates focused */ | ||
1261 | + GtkTreePath *cursor_path = | ||
1262 | + gtk_tree_row_reference_get_path (tree_view->priv->cursor); | ||
1263 | + | ||
1264 | + gtk_tree_view_row_activated (tree_view, cursor_path, | ||
1265 | + tree_view->priv->focus_column); | ||
1266 | + | ||
1267 | + gtk_tree_path_free (cursor_path); | ||
1268 | + } | ||
1269 | + } | ||
1270 | + else | ||
1271 | + { | ||
1272 | + /* hierarchical listbox */ | ||
1273 | + GtkTreePath *cursor_path; | ||
1274 | + GtkRBTree *tree; | ||
1275 | + GtkRBNode *node; | ||
1276 | + | ||
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); | ||
1279 | + | ||
1280 | + if (node->children == NULL) | ||
1281 | + gtk_tree_view_real_expand_row (tree_view, | ||
1282 | + cursor_path, | ||
1283 | + tree, | ||
1284 | + node, | ||
1285 | + FALSE, TRUE); | ||
1286 | + else | ||
1287 | + gtk_tree_view_real_collapse_row (tree_view, | ||
1288 | + cursor_path, | ||
1289 | + tree, | ||
1290 | + node, | ||
1291 | + TRUE); | ||
1292 | + } | ||
1293 | + } | ||
1294 | + | ||
1295 | if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG)) | ||
1296 | { | ||
1297 | if (event->keyval == GDK_Escape) | ||
1298 | @@ -4420,6 +5256,7 @@ | ||
1299 | |||
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 | ||
1303 | */ | ||
1304 | static gboolean | ||
1305 | gtk_tree_view_enter_notify (GtkWidget *widget, | ||
1306 | @@ -4434,6 +5271,10 @@ | ||
1307 | |||
1308 | tree_view = GTK_TREE_VIEW (widget); | ||
1309 | |||
1310 | + /* stop "automatic" pen dragging */ | ||
1311 | + tree_view->priv->pen_drag_active = FALSE; | ||
1312 | + remove_scroll_timeout (tree_view); | ||
1313 | + | ||
1314 | /* Sanity check it */ | ||
1315 | if (event->window != tree_view->priv->bin_window) | ||
1316 | return FALSE; | ||
1317 | @@ -4463,6 +5304,9 @@ | ||
1318 | tree_view = GTK_TREE_VIEW (widget); | ||
1319 | tree_view->priv->pressed_button = -1; | ||
1320 | |||
1321 | + if (tree_view->priv->pen_down && tree_view->priv->queued_select_row == NULL) | ||
1322 | + tree_view->priv->pen_drag_active = TRUE; | ||
1323 | + | ||
1324 | if (event->mode == GDK_CROSSING_GRAB) | ||
1325 | return TRUE; | ||
1326 | |||
1327 | @@ -4535,6 +5379,7 @@ | ||
1328 | gboolean retval = FALSE; | ||
1329 | gboolean is_separator = FALSE; | ||
1330 | gint focus_pad; | ||
1331 | + gint expander_indent; | ||
1332 | |||
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, | ||
1340 | NULL); | ||
1341 | |||
1342 | for (list = tree_view->priv->columns; list; list = list->next) | ||
1343 | @@ -4577,13 +5423,16 @@ | ||
1344 | { | ||
1345 | height = MAX (height, tmp_height); | ||
1346 | height = MAX (height, tree_view->priv->expander_size); | ||
1347 | + | ||
1348 | + /* Hildon addition */ | ||
1349 | + height -= 1; | ||
1350 | } | ||
1351 | else | ||
1352 | height = 2 + 2 * focus_pad; | ||
1353 | |||
1354 | if (gtk_tree_view_is_expander_column (tree_view, column) && TREE_VIEW_DRAW_EXPANDERS (tree_view)) | ||
1355 | { | ||
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; | ||
1358 | } | ||
1359 | else | ||
1360 | tmp_width = tmp_width + horizontal_separator; | ||
1361 | @@ -5585,6 +6434,16 @@ | ||
1362 | #endif /* 0 */ | ||
1363 | |||
1364 | static void | ||
1365 | +add_scroll_timeout (GtkTreeView *tree_view) | ||
1366 | +{ | ||
1367 | + if (tree_view->priv->scroll_timeout == 0) | ||
1368 | + { | ||
1369 | + tree_view->priv->scroll_timeout = | ||
1370 | + g_timeout_add (150, scroll_row_timeout, tree_view); | ||
1371 | + } | ||
1372 | +} | ||
1373 | + | ||
1374 | +static void | ||
1375 | remove_scroll_timeout (GtkTreeView *tree_view) | ||
1376 | { | ||
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); | ||
1381 | } | ||
1382 | - else if (tree_view->priv->scroll_timeout == 0) | ||
1383 | + else | ||
1384 | { | ||
1385 | - tree_view->priv->scroll_timeout = | ||
1386 | - g_timeout_add (150, scroll_row_timeout, tree_view); | ||
1387 | + add_scroll_timeout (tree_view); | ||
1388 | } | ||
1389 | |||
1390 | if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE)) | ||
1391 | @@ -6901,8 +7759,6 @@ | ||
1392 | GtkMovementStep step, | ||
1393 | gint count) | ||
1394 | { | ||
1395 | - GdkModifierType state; | ||
1396 | - | ||
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)); | ||
1403 | |||
1404 | + /* Hildon: Ignore ctrl and shift */ | ||
1405 | +#if 0 | ||
1406 | if (gtk_get_current_event_state (&state)) | ||
1407 | { | ||
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; | ||
1412 | } | ||
1413 | +#endif | ||
1414 | /* else we assume not pressed */ | ||
1415 | |||
1416 | switch (step) | ||
1417 | @@ -7092,6 +7951,27 @@ | ||
1418 | done: | ||
1419 | if (!tree_view->priv->fixed_height_mode) | ||
1420 | install_presize_handler (tree_view); | ||
1421 | + | ||
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, | ||
1425 | + node, | ||
1426 | + path)) | ||
1427 | + { | ||
1428 | + if (gtk_tree_path_compare (path, | ||
1429 | + gtk_tree_row_reference_get_path(tree_view->priv->cursor)) | ||
1430 | + == 0) | ||
1431 | + { | ||
1432 | + gtk_tree_row_reference_free (tree_view->priv->cursor); | ||
1433 | + tree_view->priv->cursor = NULL; | ||
1434 | + } | ||
1435 | + | ||
1436 | + gtk_tree_selection_unselect_path (tree_view->priv->selection, path); | ||
1437 | + gtk_tree_view_collapse_row (tree_view, path); | ||
1438 | + } | ||
1439 | + | ||
1440 | + check_if_can_focus (tree_view); | ||
1441 | + | ||
1442 | if (free_path) | ||
1443 | gtk_tree_path_free (path); | ||
1444 | } | ||
1445 | @@ -7196,6 +8076,11 @@ | ||
1446 | install_presize_handler (tree_view); | ||
1447 | if (free_path) | ||
1448 | gtk_tree_path_free (path); | ||
1449 | + | ||
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); | ||
1454 | } | ||
1455 | |||
1456 | static void | ||
1457 | @@ -7295,6 +8180,16 @@ | ||
1458 | _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data); | ||
1459 | } | ||
1460 | |||
1461 | +static gboolean | ||
1462 | +check_if_can_focus_idle (GtkTreeView *tree_view) | ||
1463 | +{ | ||
1464 | + check_if_can_focus (tree_view); | ||
1465 | + | ||
1466 | + tree_view->priv->check_if_can_focus_idle_id = 0; | ||
1467 | + | ||
1468 | + return FALSE; | ||
1469 | +} | ||
1470 | + | ||
1471 | static void | ||
1472 | gtk_tree_view_row_deleted (GtkTreeModel *model, | ||
1473 | GtkTreePath *path, | ||
1474 | @@ -7357,6 +8252,11 @@ | ||
1475 | tree_view->priv->tree = NULL; | ||
1476 | |||
1477 | _gtk_rbtree_remove (tree); | ||
1478 | + | ||
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); | ||
1483 | } | ||
1484 | else | ||
1485 | { | ||
1486 | @@ -7375,6 +8275,13 @@ | ||
1487 | |||
1488 | if (selection_changed) | ||
1489 | g_signal_emit_by_name (tree_view->priv->selection, "changed"); | ||
1490 | + | ||
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 | ||
1493 | + * called yet */ | ||
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); | ||
1497 | } | ||
1498 | |||
1499 | static void | ||
1500 | @@ -7508,6 +8415,7 @@ | ||
1501 | GList *list; | ||
1502 | GtkTreeViewColumn *tmp_column = NULL; | ||
1503 | gint total_width; | ||
1504 | + gint expander_indent, depth; | ||
1505 | gboolean indent_expanders; | ||
1506 | gboolean rtl; | ||
1507 | |||
1508 | @@ -7535,14 +8443,19 @@ | ||
1509 | |||
1510 | gtk_widget_style_get (GTK_WIDGET (tree_view), | ||
1511 | "indent_expanders", &indent_expanders, | ||
1512 | + "expander_indent", &expander_indent, | ||
1513 | NULL); | ||
1514 | |||
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); | ||
1518 | + | ||
1519 | if (indent_expanders) | ||
1520 | { | ||
1521 | if (rtl) | ||
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; | ||
1524 | else | ||
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; | ||
1527 | } | ||
1528 | if (x1) | ||
1529 | { | ||
1530 | @@ -7617,9 +8530,11 @@ | ||
1531 | gboolean retval = FALSE; | ||
1532 | gint tmpheight; | ||
1533 | gint horizontal_separator; | ||
1534 | + gint expander_indent; | ||
1535 | |||
1536 | gtk_widget_style_get (GTK_WIDGET (tree_view), | ||
1537 | "horizontal_separator", &horizontal_separator, | ||
1538 | + "expander_indent", &expander_indent, | ||
1539 | NULL); | ||
1540 | |||
1541 | if (height) | ||
1542 | @@ -7657,7 +8572,7 @@ | ||
1543 | if (gtk_tree_view_is_expander_column (tree_view, column) && | ||
1544 | TREE_VIEW_DRAW_EXPANDERS (tree_view)) | ||
1545 | { | ||
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) | ||
1548 | { | ||
1549 | _gtk_tree_view_column_cell_set_dirty (column, TRUE); | ||
1550 | retval = TRUE; | ||
1551 | @@ -7747,6 +8662,7 @@ | ||
1552 | } | ||
1553 | } | ||
1554 | |||
1555 | +#if 0 | ||
1556 | static void | ||
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); | ||
1562 | } | ||
1563 | +#endif | ||
1564 | |||
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 @@ | ||
1568 | |||
1569 | area.x = x_offset; | ||
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)); | ||
1574 | |||
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; | ||
1584 | |||
1585 | if (! GTK_WIDGET_HAS_FOCUS (tree_view)) | ||
1586 | return; | ||
1587 | @@ -8415,12 +9335,30 @@ | ||
1588 | if (cursor_tree == NULL) | ||
1589 | /* FIXME: we lost the cursor; should we get the first? */ | ||
1590 | return; | ||
1591 | - if (count == -1) | ||
1592 | - _gtk_rbtree_prev_full (cursor_tree, cursor_node, | ||
1593 | - &new_cursor_tree, &new_cursor_node); | ||
1594 | - else | ||
1595 | - _gtk_rbtree_next_full (cursor_tree, cursor_node, | ||
1596 | - &new_cursor_tree, &new_cursor_node); | ||
1597 | + | ||
1598 | + old_cursor_tree = cursor_tree; | ||
1599 | + old_cursor_node = cursor_node; | ||
1600 | + do { | ||
1601 | + if (count == -1) | ||
1602 | + _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node, | ||
1603 | + &new_cursor_tree, &new_cursor_node); | ||
1604 | + else | ||
1605 | + _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node, | ||
1606 | + &new_cursor_tree, &new_cursor_node); | ||
1607 | + | ||
1608 | + if (new_cursor_node) | ||
1609 | + { | ||
1610 | + if (new_cursor_path) | ||
1611 | + gtk_tree_path_free (new_cursor_path); | ||
1612 | + | ||
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; | ||
1616 | + } | ||
1617 | + } while (new_cursor_node && | ||
1618 | + !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, | ||
1619 | + new_cursor_node, | ||
1620 | + new_cursor_path)); | ||
1621 | |||
1622 | /* | ||
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) | ||
1626 | { | ||
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); | ||
1629 | + | ||
1630 | + if (tree_view->priv->checkbox_mode) | ||
1631 | + gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE, TRUE); | ||
1632 | + else | ||
1633 | + gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE); | ||
1634 | + | ||
1635 | + if (tree_view->priv->pen_drag_active) | ||
1636 | + { | ||
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; | ||
1640 | + | ||
1641 | + if (tree_view->priv->pen_drag_reverse) | ||
1642 | + { | ||
1643 | + gtk_tree_selection_select_path (tree_view->priv->selection, | ||
1644 | + cursor_path); | ||
1645 | + gtk_tree_selection_unselect_path (tree_view->priv->selection, | ||
1646 | + gtk_tree_row_reference_get_path (tree_view->priv->last_drag_row)); | ||
1647 | + } | ||
1648 | + | ||
1649 | + gtk_tree_row_reference_free (tree_view->priv->last_drag_row); | ||
1650 | + | ||
1651 | + tree_view->priv->last_drag_row = | ||
1652 | + gtk_tree_row_reference_new (tree_view->priv->model, | ||
1653 | + cursor_path); | ||
1654 | + } | ||
1655 | + | ||
1656 | gtk_tree_path_free (cursor_path); | ||
1657 | } | ||
1658 | else | ||
1659 | @@ -8467,6 +9431,8 @@ | ||
1660 | { | ||
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; | ||
1666 | gint y; | ||
1667 | gint vertical_separator; | ||
1668 | @@ -8474,6 +9440,9 @@ | ||
1669 | if (! GTK_WIDGET_HAS_FOCUS (tree_view)) | ||
1670 | return; | ||
1671 | |||
1672 | + if (tree_view->priv->tree == NULL) | ||
1673 | + return; | ||
1674 | + | ||
1675 | if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) | ||
1676 | cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); | ||
1677 | else | ||
1678 | @@ -8504,7 +9473,65 @@ | ||
1679 | |||
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); | ||
1683 | + | ||
1684 | + while (cursor_node && | ||
1685 | + !_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, | ||
1686 | + cursor_node, | ||
1687 | + cursor_path)) | ||
1688 | + { | ||
1689 | + old_cursor_tree = cursor_tree; | ||
1690 | + old_cursor_node = cursor_node; | ||
1691 | + | ||
1692 | + if (count < 0) | ||
1693 | + _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node, | ||
1694 | + &cursor_tree, &cursor_node); | ||
1695 | + else | ||
1696 | + _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node, | ||
1697 | + &cursor_tree, &cursor_node); | ||
1698 | + | ||
1699 | + if (cursor_path) | ||
1700 | + { | ||
1701 | + gtk_tree_path_free(cursor_path); | ||
1702 | + cursor_path = NULL; | ||
1703 | + } | ||
1704 | + | ||
1705 | + if (cursor_node) | ||
1706 | + cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); | ||
1707 | + } | ||
1708 | + | ||
1709 | + if (cursor_path == NULL) | ||
1710 | + { | ||
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, | ||
1718 | + cursor_node, | ||
1719 | + cursor_path)) | ||
1720 | + { | ||
1721 | + old_cursor_tree = cursor_tree; | ||
1722 | + old_cursor_node = cursor_node; | ||
1723 | + | ||
1724 | + if (count < 0) | ||
1725 | + _gtk_rbtree_next_full (old_cursor_tree, old_cursor_node, | ||
1726 | + &cursor_tree, &cursor_node); | ||
1727 | + else | ||
1728 | + _gtk_rbtree_prev_full (old_cursor_tree, old_cursor_node, | ||
1729 | + &cursor_tree, &cursor_node); | ||
1730 | + | ||
1731 | + if (cursor_path) | ||
1732 | + { | ||
1733 | + gtk_tree_path_free(cursor_path); | ||
1734 | + cursor_path = NULL; | ||
1735 | + } | ||
1736 | + | ||
1737 | + if (cursor_node) | ||
1738 | + cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node); | ||
1739 | + } | ||
1740 | + } | ||
1741 | + | ||
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, | ||
1747 | gint count) | ||
1748 | { | ||
1749 | + /* Hildon: cursor is always displayed on an entire row anyway */ | ||
1750 | +#if 0 | ||
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); | ||
1756 | } | ||
1757 | gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column); | ||
1758 | +#endif | ||
1759 | } | ||
1760 | |||
1761 | static void | ||
1762 | gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view, | ||
1763 | gint count) | ||
1764 | { | ||
1765 | + /* Hildon: cursor is always displayed on an entire row anyway */ | ||
1766 | +#if 0 | ||
1767 | GtkRBTree *cursor_tree; | ||
1768 | GtkRBNode *cursor_node; | ||
1769 | GtkTreePath *path; | ||
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); | ||
1774 | +#endif | ||
1775 | } | ||
1776 | |||
1777 | static gboolean | ||
1778 | @@ -8670,7 +9703,7 @@ | ||
1779 | GtkTreePath *cursor_path = NULL; | ||
1780 | GtkTreeSelectMode mode = 0; | ||
1781 | |||
1782 | - if (! GTK_WIDGET_HAS_FOCUS (tree_view)) | ||
1783 | + if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode) | ||
1784 | return FALSE; | ||
1785 | |||
1786 | if (tree_view->priv->cursor) | ||
1787 | @@ -8731,7 +9764,7 @@ | ||
1788 | GtkRBNode *cursor_node = NULL; | ||
1789 | GtkTreePath *cursor_path = NULL; | ||
1790 | |||
1791 | - if (! GTK_WIDGET_HAS_FOCUS (tree_view)) | ||
1792 | + if (! GTK_WIDGET_HAS_FOCUS (tree_view) && !tree_view->priv->checkbox_mode) | ||
1793 | return FALSE; | ||
1794 | |||
1795 | cursor_path = NULL; | ||
1796 | @@ -8774,6 +9807,7 @@ | ||
1797 | GtkTreePath *cursor_path = NULL; | ||
1798 | GtkRBTree *tree; | ||
1799 | GtkRBNode *node; | ||
1800 | + gboolean hildon_row; | ||
1801 | |||
1802 | if (! GTK_WIDGET_HAS_FOCUS (tree_view)) | ||
1803 | return FALSE; | ||
1804 | @@ -8796,10 +9830,32 @@ | ||
1805 | && gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL) | ||
1806 | expand = !expand; | ||
1807 | |||
1808 | - if (expand) | ||
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) */ | ||
1812 | + if (expand) | ||
1813 | + { | ||
1814 | + hildon_row = gtk_tree_view_real_expand_row (tree_view, cursor_path, tree, | ||
1815 | + node, open_all, TRUE); | ||
1816 | + | ||
1817 | + if (!hildon_row || !node->children) | ||
1818 | + g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET (tree_view), | ||
1819 | + GTK_TYPE_WINDOW), | ||
1820 | + "move_focus", | ||
1821 | + GTK_DIR_TAB_FORWARD); | ||
1822 | + } | ||
1823 | else | ||
1824 | - gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE); | ||
1825 | + { | ||
1826 | + hildon_row = gtk_tree_view_real_collapse_row (tree_view, cursor_path, tree, node, TRUE); | ||
1827 | + | ||
1828 | + if (hildon_row == FALSE) | ||
1829 | + { | ||
1830 | + g_signal_emit_by_name (gtk_widget_get_ancestor (GTK_WIDGET(tree_view), | ||
1831 | + GTK_TYPE_WINDOW), | ||
1832 | + "move_focus", | ||
1833 | + GTK_DIR_TAB_BACKWARD); | ||
1834 | + gtk_tree_view_real_select_cursor_parent (tree_view); | ||
1835 | + } | ||
1836 | + } | ||
1837 | |||
1838 | gtk_tree_path_free (cursor_path); | ||
1839 | |||
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; | ||
1852 | |||
1853 | tree_view->priv->scroll_to_column = NULL; | ||
1854 | |||
1855 | @@ -9402,6 +10466,8 @@ | ||
1856 | install_presize_handler (tree_view); | ||
1857 | } | ||
1858 | |||
1859 | + check_if_can_focus (tree_view); | ||
1860 | + | ||
1861 | g_object_notify (G_OBJECT (tree_view), "model"); | ||
1862 | |||
1863 | if (GTK_WIDGET_REALIZED (tree_view)) | ||
1864 | @@ -9744,6 +10810,10 @@ | ||
1865 | G_CALLBACK (column_sizing_notify), | ||
1866 | tree_view); | ||
1867 | |||
1868 | + g_signal_handlers_disconnect_by_func (column, | ||
1869 | + G_CALLBACK (update_checkbox_mode), | ||
1870 | + tree_view); | ||
1871 | + | ||
1872 | _gtk_tree_view_column_unset_tree_view (column); | ||
1873 | |||
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); | ||
1878 | |||
1879 | + update_checkbox_mode (NULL, NULL, tree_view); | ||
1880 | + | ||
1881 | return tree_view->priv->n_columns; | ||
1882 | } | ||
1883 | |||
1884 | @@ -9815,6 +10887,9 @@ | ||
1885 | g_signal_connect (column, "notify::sizing", | ||
1886 | G_CALLBACK (column_sizing_notify), tree_view); | ||
1887 | |||
1888 | + g_signal_connect (column, "notify::visible", | ||
1889 | + G_CALLBACK (update_checkbox_mode), tree_view); | ||
1890 | + | ||
1891 | tree_view->priv->columns = g_list_insert (tree_view->priv->columns, | ||
1892 | column, position); | ||
1893 | tree_view->priv->n_columns++; | ||
1894 | @@ -9838,6 +10913,9 @@ | ||
1895 | |||
1896 | g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0); | ||
1897 | |||
1898 | + update_checkbox_mode (NULL, NULL, tree_view); | ||
1899 | + check_if_can_focus (tree_view); | ||
1900 | + | ||
1901 | return tree_view->priv->n_columns; | ||
1902 | } | ||
1903 | |||
1904 | @@ -10295,7 +11373,6 @@ | ||
1905 | GtkTreeViewColumn *column) | ||
1906 | { | ||
1907 | g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); | ||
1908 | - | ||
1909 | g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column); | ||
1910 | } | ||
1911 | |||
1912 | @@ -10560,6 +11637,16 @@ | ||
1913 | GtkTreeIter iter; | ||
1914 | GtkTreeIter temp; | ||
1915 | gboolean expand; | ||
1916 | + gint vertical_separator; | ||
1917 | + GtkTreePath *collapse_path; | ||
1918 | + GtkRBTree *tree2; | ||
1919 | + GtkRBNode *node2; | ||
1920 | + GtkTreePath *child_path = NULL; | ||
1921 | + GtkTreeIter parent_iter; | ||
1922 | + GtkTreeIter child_iter; | ||
1923 | + GdkRectangle visible_rect; | ||
1924 | + gint children, n; | ||
1925 | + guint total_height; | ||
1926 | |||
1927 | remove_auto_expand_timeout (tree_view); | ||
1928 | |||
1929 | @@ -10573,8 +11660,12 @@ | ||
1930 | if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter)) | ||
1931 | return FALSE; | ||
1932 | |||
1933 | + /* Hildon: insensitive rows cannot be expanded */ | ||
1934 | + if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, | ||
1935 | + node, path)) | ||
1936 | + return FALSE; | ||
1937 | |||
1938 | - if (node->children && open_all) | ||
1939 | + if (node->children && open_all) | ||
1940 | { | ||
1941 | gboolean retval = FALSE; | ||
1942 | GtkTreePath *tmp_path = gtk_tree_path_copy (path); | ||
1943 | @@ -10603,6 +11694,37 @@ | ||
1944 | return retval; | ||
1945 | } | ||
1946 | |||
1947 | + /* Hildon: collapse other items in the same level */ | ||
1948 | + gtk_widget_style_get (GTK_WIDGET (tree_view), | ||
1949 | + "vertical_separator", &vertical_separator, NULL); | ||
1950 | + | ||
1951 | + /* find the first child */ | ||
1952 | + collapse_path = gtk_tree_path_copy (path); | ||
1953 | + while (gtk_tree_path_prev (collapse_path)) | ||
1954 | + ; | ||
1955 | + | ||
1956 | + do { | ||
1957 | + if (gtk_tree_path_compare (collapse_path, path) != 0) | ||
1958 | + { | ||
1959 | + _gtk_tree_view_find_node (tree_view, collapse_path, &tree2, &node2); | ||
1960 | + | ||
1961 | + if (tree2 == NULL) | ||
1962 | + /* end reached already */ | ||
1963 | + break; | ||
1964 | + | ||
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 */ | ||
1970 | + break; | ||
1971 | + } | ||
1972 | + | ||
1973 | + gtk_tree_path_next (collapse_path); | ||
1974 | + } while (1); | ||
1975 | + | ||
1976 | + gtk_tree_path_free (collapse_path); | ||
1977 | + | ||
1978 | g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand); | ||
1979 | |||
1980 | if (expand) | ||
1981 | @@ -10643,6 +11765,42 @@ | ||
1982 | GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SEMI_COLLAPSED); | ||
1983 | } | ||
1984 | |||
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++) | ||
1993 | + { | ||
1994 | + gtk_tree_model_iter_nth_child (tree_view->priv->model, | ||
1995 | + &child_iter, &parent_iter, n); | ||
1996 | + | ||
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); | ||
2000 | + | ||
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); | ||
2003 | + | ||
2004 | + if (CELL_HEIGHT (node2, 0) == 0) | ||
2005 | + validate_row (tree_view, tree2, node2, &child_iter, child_path); | ||
2006 | + | ||
2007 | + total_height += CELL_HEIGHT (node2, vertical_separator); | ||
2008 | + } | ||
2009 | + | ||
2010 | + gtk_tree_view_get_visible_rect (tree_view, &visible_rect); | ||
2011 | + | ||
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); | ||
2016 | + else | ||
2017 | + gtk_tree_view_scroll_to_cell (tree_view, child_path, NULL, FALSE, 0.0, 0.0); | ||
2018 | + | ||
2019 | + gtk_tree_path_free (child_path); | ||
2020 | + | ||
2021 | install_presize_handler (tree_view); | ||
2022 | |||
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; | ||
2027 | |||
2028 | + _gtk_tree_view_find_node (tree_view, path, &tree, &node); | ||
2029 | + | ||
2030 | + /* Hildon: cursor cannot move to an insensitive row */ | ||
2031 | + if (!_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, | ||
2032 | + node, path)) | ||
2033 | + { | ||
2034 | + g_signal_emit (tree_view, tree_view_signals[ROW_INSENSITIVE], 0, path); | ||
2035 | + return; | ||
2036 | + } | ||
2037 | + | ||
2038 | if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) | ||
2039 | { | ||
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, | ||
2044 | path); | ||
2045 | - _gtk_tree_view_find_node (tree_view, path, &tree, &node); | ||
2046 | if (tree != NULL) | ||
2047 | { | ||
2048 | GtkRBTree *new_tree = NULL; | ||
2049 | @@ -11093,7 +12260,8 @@ | ||
2050 | { | ||
2051 | GtkTreeSelectMode mode = 0; | ||
2052 | |||
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 @@ | ||
2060 | { | ||
2061 | g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); | ||
2062 | g_return_if_fail (path != NULL); | ||
2063 | + | ||
2064 | + tree_view->priv->pen_focus = FALSE; | ||
2065 | + | ||
2066 | if (focus_column) | ||
2067 | g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column)); | ||
2068 | if (focus_cell) | ||
2069 | @@ -11414,6 +12585,7 @@ | ||
2070 | GtkRBNode *node = NULL; | ||
2071 | gint vertical_separator; | ||
2072 | gint horizontal_separator; | ||
2073 | + gint expander_indent; | ||
2074 | |||
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, | ||
2082 | NULL); | ||
2083 | |||
2084 | rect->x = 0; | ||
2085 | @@ -11453,9 +12626,11 @@ | ||
2086 | TREE_VIEW_DRAW_EXPANDERS (tree_view)) | ||
2087 | { | ||
2088 | gint depth = gtk_tree_path_get_depth (path) - 1; | ||
2089 | + gint adjust; | ||
2090 | |||
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); | ||
2097 | } | ||
2098 | } | ||
2099 | @@ -12077,8 +13252,13 @@ | ||
2100 | if (gtk_tree_view_is_expander_column (tree_view, column) && | ||
2101 | TREE_VIEW_DRAW_EXPANDERS(tree_view)) | ||
2102 | { | ||
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; | ||
2106 | + | ||
2107 | + gtk_widget_style_get (widget, "expander_indent", &expander_indent, NULL); | ||
2108 | + | ||
2109 | + adjust = depth * tree_view->priv->expander_size + (depth - 1) * expander_indent; | ||
2110 | + cell_area.x += adjust; | ||
2111 | + cell_area.width -= adjust; | ||
2112 | } | ||
2113 | |||
2114 | if (gtk_tree_view_column_cell_is_visible (column)) | ||
2115 | @@ -13062,3 +14242,138 @@ | ||
2116 | tree_view->priv->pressed_button = -1; | ||
2117 | } | ||
2118 | |||
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). | ||
2123 | + */ | ||
2124 | +static void | ||
2125 | +update_checkbox_mode (GObject *object, GParamSpec *pspec, gpointer data) | ||
2126 | +{ | ||
2127 | + GtkTreeView *tree_view = GTK_TREE_VIEW (data); | ||
2128 | + GList *columns = gtk_tree_view_get_columns (tree_view); | ||
2129 | + GList *list; | ||
2130 | + gboolean allow_checkbox_mode; | ||
2131 | + | ||
2132 | + g_object_get (GTK_WIDGET (data), | ||
2133 | + "allow_checkbox_mode", &allow_checkbox_mode, NULL); | ||
2134 | + g_return_if_fail (allow_checkbox_mode); | ||
2135 | + | ||
2136 | + for (list = columns; list; list = list->next) | ||
2137 | + { | ||
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)) | ||
2141 | + { | ||
2142 | + /* checkbox column found */ | ||
2143 | + tree_view->priv->checkbox_mode = TRUE; | ||
2144 | + g_list_free (columns); | ||
2145 | + return; | ||
2146 | + } | ||
2147 | + } | ||
2148 | + | ||
2149 | + /* no checkbox column was found */ | ||
2150 | + tree_view->priv->checkbox_mode = FALSE; | ||
2151 | + g_list_free (columns); | ||
2152 | +} | ||
2153 | + | ||
2154 | +static void | ||
2155 | +set_dotted_lines (GtkTreeView *tree_view, gboolean enable) | ||
2156 | +{ | ||
2157 | + if (enable != tree_view->priv->dotted_lines) | ||
2158 | + { | ||
2159 | + tree_view->priv->dotted_lines = enable; | ||
2160 | + gtk_widget_queue_draw (GTK_WIDGET (tree_view)); | ||
2161 | + } | ||
2162 | +} | ||
2163 | + | ||
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 | ||
2168 | + */ | ||
2169 | +static void | ||
2170 | +selection_changed (GtkTreeSelection *selection, gpointer data) | ||
2171 | +{ | ||
2172 | + GtkTreeView *tree_view = GTK_TREE_VIEW(data); | ||
2173 | + GtkTreePath *cursor_path = NULL; | ||
2174 | + GtkTreeIter iter; | ||
2175 | + | ||
2176 | + /* if there are checkboxes, cursor row doesn't have to be selected */ | ||
2177 | + if (tree_view->priv->checkbox_mode) | ||
2178 | + return; | ||
2179 | + | ||
2180 | + if (gtk_tree_row_reference_valid (tree_view->priv->cursor)) | ||
2181 | + cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor); | ||
2182 | + | ||
2183 | + if (cursor_path == NULL || | ||
2184 | + !gtk_tree_selection_path_is_selected (selection, cursor_path)) | ||
2185 | + { | ||
2186 | + GtkTreePath *selected_path; | ||
2187 | + GtkRBTree *tree = NULL; | ||
2188 | + GtkRBNode *node = NULL; | ||
2189 | + | ||
2190 | + if (gtk_tree_selection_get_mode (selection) != GTK_SELECTION_MULTIPLE && | ||
2191 | + gtk_tree_selection_get_selected (selection, NULL, &iter)) | ||
2192 | + { | ||
2193 | + selected_path = gtk_tree_model_get_path (tree_view->priv->model, | ||
2194 | + &iter); | ||
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)); | ||
2200 | + } | ||
2201 | + else | ||
2202 | + { | ||
2203 | + gtk_tree_row_reference_free (tree_view->priv->cursor); | ||
2204 | + tree_view->priv->cursor = NULL; | ||
2205 | + } | ||
2206 | + } | ||
2207 | + | ||
2208 | + if (cursor_path) | ||
2209 | + gtk_tree_path_free (cursor_path); | ||
2210 | +} | ||
2211 | + | ||
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. | ||
2216 | + */ | ||
2217 | +static void | ||
2218 | +check_if_can_focus (GtkTreeView *tree_view) | ||
2219 | +{ | ||
2220 | + GtkTreeModel *model = gtk_tree_view_get_model (tree_view); | ||
2221 | + GtkTreeIter iter; | ||
2222 | + | ||
2223 | + if (model == NULL || !GTK_WIDGET_MAPPED (tree_view)) | ||
2224 | + return; | ||
2225 | + | ||
2226 | + if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) | ||
2227 | + { | ||
2228 | + GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS); | ||
2229 | + return; | ||
2230 | + } | ||
2231 | + | ||
2232 | + do { | ||
2233 | + GtkTreePath *path = gtk_tree_model_get_path (model, &iter); | ||
2234 | + GtkRBTree *tree; | ||
2235 | + GtkRBNode *node; | ||
2236 | + | ||
2237 | + _gtk_tree_view_find_node (tree_view, path, &tree, &node); | ||
2238 | + | ||
2239 | + if (_gtk_tree_selection_is_row_selectable (tree_view->priv->selection, | ||
2240 | + node, path)) | ||
2241 | + { | ||
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, | ||
2246 | + TRUE); | ||
2247 | + | ||
2248 | + return; | ||
2249 | + } | ||
2250 | + } while (gtk_tree_model_iter_next (model, &iter)); | ||
2251 | + | ||
2252 | + GTK_WIDGET_UNSET_FLAGS (tree_view, GTK_CAN_FOCUS); | ||
2253 | +} | ||