Bug Summary

File:ctk/ctktreeview.c
Warning:line 4535, column 11
Access to field 'children' results in a dereference of a null pointer (loaded from variable 'start_node')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctktreeview.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-170505-43637-1 -x c ctktreeview.c
1/* ctktreeview.c
2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19#include "config.h"
20
21#include <math.h>
22#include <string.h>
23
24#include "ctktreeview.h"
25
26#include "ctkadjustmentprivate.h"
27#include "ctkcssnumbervalueprivate.h"
28#include "ctkrbtree.h"
29#include "ctktreednd.h"
30#include "ctktreeprivate.h"
31#include "ctkcellrenderer.h"
32#include "ctkmarshalers.h"
33#include "ctkbuildable.h"
34#include "ctkbutton.h"
35#include "ctklabel.h"
36#include "ctkbox.h"
37#include "ctkintl.h"
38#include "ctkbindings.h"
39#include "ctkcontainer.h"
40#include "ctkentry.h"
41#include "ctkframe.h"
42#include "ctkmain.h"
43#include "ctktreemodelsort.h"
44#include "ctktooltip.h"
45#include "ctkscrollable.h"
46#include "ctkcelllayout.h"
47#include "ctkprivate.h"
48#include "ctkwidgetprivate.h"
49#include "ctkentryprivate.h"
50#include "ctkstylecontextprivate.h"
51#include "ctkcssstylepropertyprivate.h"
52#include "ctkcssrgbavalueprivate.h"
53#include "ctktypebuiltins.h"
54#include "ctkmain.h"
55#include "ctksettingsprivate.h"
56#include "ctkwidgetpath.h"
57#include "ctkpixelcacheprivate.h"
58#include "a11y/ctktreeviewaccessibleprivate.h"
59
60
61/**
62 * SECTION:ctktreeview
63 * @Short_description: A widget for displaying both trees and lists
64 * @Title: CtkTreeView
65 * @See_also: #CtkTreeViewColumn, #CtkTreeSelection, #CtkTreeModel,
66 * [CtkTreeView drag-and-drop][ctk3-CtkTreeView-drag-and-drop],
67 * #CtkTreeSortable, #CtkTreeModelSort, #CtkListStore, #CtkTreeStore,
68 * #CtkCellRenderer, #CtkCellEditable, #CtkCellRendererPixbuf,
69 * #CtkCellRendererText, #CtkCellRendererToggle
70 *
71 * Widget that displays any object that implements the #CtkTreeModel interface.
72 *
73 * Please refer to the
74 * [tree widget conceptual overview][TreeWidget]
75 * for an overview of all the objects and data types related
76 * to the tree widget and how they work together.
77 *
78 * Several different coordinate systems are exposed in the CtkTreeView API.
79 * These are:
80 *
81 * ![](tree-view-coordinates.png)
82 *
83 * Coordinate systems in CtkTreeView API:
84 *
85 * - Widget coordinates: Coordinates relative to the widget (usually `widget->window`).
86 *
87 * - Bin window coordinates: Coordinates relative to the window that CtkTreeView renders to.
88 *
89 * - Tree coordinates: Coordinates relative to the entire scrollable area of CtkTreeView. These
90 * coordinates start at (0, 0) for row 0 of the tree.
91 *
92 * Several functions are available for converting between the different
93 * coordinate systems. The most common translations are between widget and bin
94 * window coordinates and between bin window and tree coordinates. For the
95 * former you can use ctk_tree_view_convert_widget_to_bin_window_coords()
96 * (and vice versa), for the latter ctk_tree_view_convert_bin_window_to_tree_coords()
97 * (and vice versa).
98 *
99 * # CtkTreeView as CtkBuildable
100 *
101 * The CtkTreeView implementation of the CtkBuildable interface accepts
102 * #CtkTreeViewColumn objects as <child> elements and exposes the internal
103 * #CtkTreeSelection in UI definitions.
104 *
105 * An example of a UI definition fragment with CtkTreeView:
106 * |[
107 * <object class="CtkTreeView" id="treeview">
108 * <property name="model">liststore1</property>
109 * <child>
110 * <object class="CtkTreeViewColumn" id="test-column">
111 * <property name="title">Test</property>
112 * <child>
113 * <object class="CtkCellRendererText" id="test-renderer"/>
114 * <attributes>
115 * <attribute name="text">1</attribute>
116 * </attributes>
117 * </child>
118 * </object>
119 * </child>
120 * <child internal-child="selection">
121 * <object class="CtkTreeSelection" id="selection">
122 * <signal name="changed" handler="on_treeview_selection_changed"/>
123 * </object>
124 * </child>
125 * </object>
126 * ]|
127 *
128 * # CSS nodes
129 *
130 * |[<!-- language="plain" -->
131 * treeview.view
132 * ├── header
133 * │ ├── <column header>
134 * ┊ ┊
135 * │ ╰── <column header>
136 * │
137 * ╰── [rubberband]
138 * ]|
139 *
140 * CtkTreeView has a main CSS node with name treeview and style class .view.
141 * It has a subnode with name header, which is the parent for all the column
142 * header widgets' CSS nodes.
143 * For rubberband selection, a subnode with name rubberband is used.
144 */
145
146enum
147{
148 DRAG_COLUMN_WINDOW_STATE_UNSET = 0,
149 DRAG_COLUMN_WINDOW_STATE_ORIGINAL = 1,
150 DRAG_COLUMN_WINDOW_STATE_ARROW = 2,
151 DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT = 3,
152 DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT = 4
153};
154
155enum
156{
157 RUBBER_BAND_OFF = 0,
158 RUBBER_BAND_MAYBE_START = 1,
159 RUBBER_BAND_ACTIVE = 2
160};
161
162typedef enum {
163 CLEAR_AND_SELECT = (1 << 0),
164 CLAMP_NODE = (1 << 1),
165 CURSOR_INVALID = (1 << 2)
166} SetCursorFlags;
167
168 /* This lovely little value is used to determine how far away from the title bar
169 * you can move the mouse and still have a column drag work.
170 */
171#define TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER(tree_view)(10*ctk_tree_view_get_effective_header_height(tree_view)) (10*ctk_tree_view_get_effective_header_height(tree_view))
172
173#ifdef __GNUC__4
174
175#define TREE_VIEW_INTERNAL_ASSERT(expr, ret)do{ if (!(expr)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "175", ((const char*)
(__func__)), "expr"); return ret; }; }while (0)
G_STMT_STARTdo{ \
176 if (!(expr)) \
177 { \
178 g_log (G_LOG_DOMAIN"Ctk", \
179 G_LOG_LEVEL_CRITICAL, \
180 "%s (%s): assertion `%s' failed.\n" \
181 "There is a disparity between the internal view of the CtkTreeView,\n" \
182 "and the CtkTreeModel. This generally means that the model has changed\n"\
183 "without letting the view know. Any display from now on is likely to\n" \
184 "be incorrect.\n", \
185 G_STRLOC"ctktreeview.c" ":" "185", \
186 G_STRFUNC((const char*) (__func__)), \
187 #expr); \
188 return ret; \
189 }; }G_STMT_ENDwhile (0)
190
191#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr)do{ if (!(expr)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "191", ((const char*)
(__func__)), "expr"); return; }; }while (0)
G_STMT_STARTdo{ \
192 if (!(expr)) \
193 { \
194 g_log (G_LOG_DOMAIN"Ctk", \
195 G_LOG_LEVEL_CRITICAL, \
196 "%s (%s): assertion `%s' failed.\n" \
197 "There is a disparity between the internal view of the CtkTreeView,\n" \
198 "and the CtkTreeModel. This generally means that the model has changed\n"\
199 "without letting the view know. Any display from now on is likely to\n" \
200 "be incorrect.\n", \
201 G_STRLOC"ctktreeview.c" ":" "201", \
202 G_STRFUNC((const char*) (__func__)), \
203 #expr); \
204 return; \
205 }; }G_STMT_ENDwhile (0)
206
207#else
208
209#define TREE_VIEW_INTERNAL_ASSERT(expr, ret)do{ if (!(expr)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "209", ((const char*)
(__func__)), "expr"); return ret; }; }while (0)
G_STMT_STARTdo{ \
210 if (!(expr)) \
211 { \
212 g_log (G_LOG_DOMAIN"Ctk", \
213 G_LOG_LEVEL_CRITICAL, \
214 "file %s: line %d: assertion `%s' failed.\n" \
215 "There is a disparity between the internal view of the CtkTreeView,\n" \
216 "and the CtkTreeModel. This generally means that the model has changed\n"\
217 "without letting the view know. Any display from now on is likely to\n" \
218 "be incorrect.\n", \
219 __FILE__"ctktreeview.c", \
220 __LINE__220, \
221 #expr); \
222 return ret; \
223 }; }G_STMT_ENDwhile (0)
224
225#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr)do{ if (!(expr)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "225", ((const char*)
(__func__)), "expr"); return; }; }while (0)
G_STMT_STARTdo{ \
226 if (!(expr)) \
227 { \
228 g_log (G_LOG_DOMAIN"Ctk", \
229 G_LOG_LEVEL_CRITICAL, \
230 "file %s: line %d: assertion '%s' failed.\n" \
231 "There is a disparity between the internal view of the CtkTreeView,\n" \
232 "and the CtkTreeModel. This generally means that the model has changed\n"\
233 "without letting the view know. Any display from now on is likely to\n" \
234 "be incorrect.\n", \
235 __FILE__"ctktreeview.c", \
236 __LINE__236, \
237 #expr); \
238 return; \
239 }; }G_STMT_ENDwhile (0)
240#endif
241
242#define CTK_TREE_VIEW_PRIORITY_VALIDATE((100 + 20) + 5) (CDK_PRIORITY_REDRAW(100 + 20) + 5)
243#define CTK_TREE_VIEW_PRIORITY_SCROLL_SYNC(((100 + 20) + 5) + 2) (CTK_TREE_VIEW_PRIORITY_VALIDATE((100 + 20) + 5) + 2)
244/* 3/5 of cdkframeclockidle.c's FRAME_INTERVAL (16667 microsecs) */
245#define CTK_TREE_VIEW_TIME_MS_PER_IDLE10 10
246#define SCROLL_EDGE_SIZE15 15
247#define CTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT5000 5000
248#define AUTO_EXPAND_TIMEOUT500 500
249
250/* Translate from bin_window coordinates to rbtree (tree coordinates) and
251 * vice versa.
252 */
253#define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y)((y) + tree_view->priv->dy) ((y) + tree_view->priv->dy)
254#define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y)((y) - tree_view->priv->dy) ((y) - tree_view->priv->dy)
255
256typedef struct _CtkTreeViewColumnReorder CtkTreeViewColumnReorder;
257struct _CtkTreeViewColumnReorder
258{
259 gint left_align;
260 gint right_align;
261 CtkTreeViewColumn *left_column;
262 CtkTreeViewColumn *right_column;
263};
264
265typedef struct _CtkTreeViewChild CtkTreeViewChild;
266struct _CtkTreeViewChild
267{
268 CtkWidget *widget;
269 CtkRBNode *node;
270 CtkRBTree *tree;
271 CtkTreeViewColumn *column;
272 CtkBorder border;
273};
274
275
276typedef struct _TreeViewDragInfo TreeViewDragInfo;
277struct _TreeViewDragInfo
278{
279 CdkModifierType start_button_mask;
280 CtkTargetList *_unused_source_target_list;
281 CdkDragAction source_actions;
282
283 CtkTargetList *_unused_dest_target_list;
284
285 guint source_set : 1;
286 guint dest_set : 1;
287};
288
289
290struct _CtkTreeViewPrivate
291{
292 CtkTreeModel *model;
293
294 /* tree information */
295 CtkRBTree *tree;
296
297 /* Container info */
298 GList *children;
299 gint width;
300
301 guint presize_handler_tick_cb;
302
303 /* Adjustments */
304 CtkAdjustment *hadjustment;
305 CtkAdjustment *vadjustment;
306 gint min_display_width;
307 gint min_display_height;
308
309 /* Sub windows */
310 CdkWindow *bin_window;
311 CdkWindow *header_window;
312
313 CtkPixelCache *pixel_cache;
314
315 /* CSS nodes */
316 CtkCssNode *header_node;
317
318 /* Scroll position state keeping */
319 CtkTreeRowReference *top_row;
320 gint top_row_dy;
321 /* dy == y pos of top_row + top_row_dy */
322 /* we cache it for simplicity of the code */
323 gint dy;
324
325 guint validate_rows_timer;
326 guint scroll_sync_timer;
327
328 /* Indentation and expander layout */
329 CtkTreeViewColumn *expander_column;
330
331 gint level_indentation;
332
333 /* Key navigation (focus), selection */
334 gint cursor_offset;
335
336 CtkTreeRowReference *anchor;
337 CtkRBNode *cursor_node;
338 CtkRBTree *cursor_tree;
339
340 CtkTreeViewColumn *focus_column;
341
342 /* Current pressed node, previously pressed, prelight */
343 CtkRBNode *button_pressed_node;
344 CtkRBTree *button_pressed_tree;
345
346 gint press_start_x;
347 gint press_start_y;
348
349 gint event_last_x;
350 gint event_last_y;
351
352 CtkRBNode *prelight_node;
353 CtkRBTree *prelight_tree;
354
355 /* Cell Editing */
356 CtkTreeViewColumn *edited_column;
357
358 /* Auto expand/collapse timeout in hover mode */
359 guint auto_expand_timeout;
360
361 /* Selection information */
362 CtkTreeSelection *selection;
363
364 /* Header information */
365 gint header_height;
366 gint n_columns;
367 GList *columns;
368
369 CtkTreeViewColumnDropFunc column_drop_func;
370 gpointer column_drop_func_data;
371 GDestroyNotify column_drop_func_data_destroy;
372 GList *column_drag_info;
373 CtkTreeViewColumnReorder *cur_reorder;
374
375 gint prev_width_before_expander;
376
377 /* Scroll timeout (e.g. during dnd, rubber banding) */
378 guint scroll_timeout;
379
380 /* Interactive Header reordering */
381 CdkWindow *drag_window;
382 CdkWindow *drag_highlight_window;
383 CtkTreeViewColumn *drag_column;
384 gint drag_column_x;
385
386 /* Interactive Header Resizing */
387 gint drag_pos;
388 gint x_drag;
389
390 /* Non-interactive Header Resizing, expand flag support */
391 gint last_extra_space;
392 gint last_extra_space_per_column;
393 gint last_number_of_expand_columns;
394
395 /* ATK Hack */
396 CtkTreeDestroyCountFunc destroy_count_func;
397 gpointer destroy_count_data;
398 GDestroyNotify destroy_count_destroy;
399
400 /* Row drag-and-drop */
401 CtkTreeRowReference *drag_dest_row;
402 CtkTreeViewDropPosition drag_dest_pos;
403 guint open_dest_timeout;
404
405 /* Rubber banding */
406 gint rubber_band_status;
407 gint rubber_band_x;
408 gint rubber_band_y;
409 gint rubber_band_extend;
410 gint rubber_band_modify;
411
412 /* fixed height */
413 gint fixed_height;
414
415 CtkRBNode *rubber_band_start_node;
416 CtkRBTree *rubber_band_start_tree;
417
418 CtkRBNode *rubber_band_end_node;
419 CtkRBTree *rubber_band_end_tree;
420 CtkCssNode *rubber_band_cssnode;
421
422 /* Scroll-to functionality when unrealized */
423 CtkTreeRowReference *scroll_to_path;
424 CtkTreeViewColumn *scroll_to_column;
425 gfloat scroll_to_row_align;
426 gfloat scroll_to_col_align;
427
428 /* Interactive search */
429 gint selected_iter;
430 gint search_column;
431 CtkTreeViewSearchPositionFunc search_position_func;
432 CtkTreeViewSearchEqualFunc search_equal_func;
433 gpointer search_user_data;
434 GDestroyNotify search_destroy;
435 gpointer search_position_user_data;
436 GDestroyNotify search_position_destroy;
437 CtkWidget *search_window;
438 CtkWidget *search_entry;
439 gulong search_entry_changed_id;
440 guint typeselect_flush_timeout;
441
442 /* Grid and tree lines */
443 CtkTreeViewGridLines grid_lines;
444 double grid_line_dashes[2];
445 int grid_line_width;
446
447 gboolean tree_lines_enabled;
448 double tree_line_dashes[2];
449 int tree_line_width;
450
451 /* Row separators */
452 CtkTreeViewRowSeparatorFunc row_separator_func;
453 gpointer row_separator_data;
454 GDestroyNotify row_separator_destroy;
455
456 /* Gestures */
457 CtkGesture *multipress_gesture;
458 CtkGesture *column_multipress_gesture;
459 CtkGesture *drag_gesture; /* Rubberbanding, row DnD */
460 CtkGesture *column_drag_gesture; /* Column reordering, resizing */
461
462 /* Tooltip support */
463 gint tooltip_column;
464
465 /* Here comes the bitfield */
466 guint scroll_to_use_align : 1;
467
468 guint fixed_height_mode : 1;
469 guint fixed_height_check : 1;
470
471 guint activate_on_single_click : 1;
472 guint reorderable : 1;
473 guint header_has_focus : 1;
474 guint drag_column_window_state : 3;
475 /* hint to display rows in alternating colors */
476 guint has_rules : 1;
477 guint mark_rows_col_dirty : 1;
478
479 /* for DnD */
480 guint empty_view_drop : 1;
481
482 guint modify_selection_pressed : 1;
483 guint extend_selection_pressed : 1;
484
485 guint init_hadjust_value : 1;
486
487 guint in_top_row_to_dy : 1;
488
489 /* interactive search */
490 guint enable_search : 1;
491 guint disable_popdown : 1;
492 guint search_custom_entry_set : 1;
493
494 guint hover_selection : 1;
495 guint hover_expand : 1;
496 guint imcontext_changed : 1;
497
498 guint rubber_banding_enable : 1;
499
500 guint in_grab : 1;
501
502 guint post_validation_flag : 1;
503
504 /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */
505 guint search_entry_avoid_unhandled_binding : 1;
506
507 /* CtkScrollablePolicy needs to be checked when
508 * driving the scrollable adjustment values */
509 guint hscroll_policy : 1;
510 guint vscroll_policy : 1;
511
512 /* CtkTreeView flags */
513 guint is_list : 1;
514 guint show_expanders : 1;
515 guint in_column_resize : 1;
516 guint arrow_prelit : 1;
517 guint headers_visible : 1;
518 guint draw_keyfocus : 1;
519 guint model_setup : 1;
520 guint in_column_drag : 1;
521};
522
523
524/* Signals */
525enum
526{
527 ROW_ACTIVATED,
528 TEST_EXPAND_ROW,
529 TEST_COLLAPSE_ROW,
530 ROW_EXPANDED,
531 ROW_COLLAPSED,
532 COLUMNS_CHANGED,
533 CURSOR_CHANGED,
534 MOVE_CURSOR,
535 SELECT_ALL,
536 UNSELECT_ALL,
537 SELECT_CURSOR_ROW,
538 TOGGLE_CURSOR_ROW,
539 EXPAND_COLLAPSE_CURSOR_ROW,
540 SELECT_CURSOR_PARENT,
541 START_INTERACTIVE_SEARCH,
542 LAST_SIGNAL
543};
544
545/* Properties */
546enum {
547 PROP_0,
548 PROP_MODEL,
549 PROP_HEADERS_VISIBLE,
550 PROP_HEADERS_CLICKABLE,
551 PROP_EXPANDER_COLUMN,
552 PROP_REORDERABLE,
553 PROP_RULES_HINT,
554 PROP_ENABLE_SEARCH,
555 PROP_SEARCH_COLUMN,
556 PROP_FIXED_HEIGHT_MODE,
557 PROP_HOVER_SELECTION,
558 PROP_HOVER_EXPAND,
559 PROP_SHOW_EXPANDERS,
560 PROP_LEVEL_INDENTATION,
561 PROP_RUBBER_BANDING,
562 PROP_ENABLE_GRID_LINES,
563 PROP_ENABLE_TREE_LINES,
564 PROP_TOOLTIP_COLUMN,
565 PROP_ACTIVATE_ON_SINGLE_CLICK,
566 LAST_PROP,
567 /* overridden */
568 PROP_HADJUSTMENT = LAST_PROP,
569 PROP_VADJUSTMENT,
570 PROP_HSCROLL_POLICY,
571 PROP_VSCROLL_POLICY,
572};
573
574/* object signals */
575static void ctk_tree_view_finalize (GObject *object);
576static void ctk_tree_view_set_property (GObject *object,
577 guint prop_id,
578 const GValue *value,
579 GParamSpec *pspec);
580static void ctk_tree_view_get_property (GObject *object,
581 guint prop_id,
582 GValue *value,
583 GParamSpec *pspec);
584
585/* ctkwidget signals */
586static void ctk_tree_view_destroy (CtkWidget *widget);
587static void ctk_tree_view_realize (CtkWidget *widget);
588static void ctk_tree_view_unrealize (CtkWidget *widget);
589static void ctk_tree_view_map (CtkWidget *widget);
590static void ctk_tree_view_unmap (CtkWidget *widget);
591static void ctk_tree_view_get_preferred_width (CtkWidget *widget,
592 gint *minimum,
593 gint *natural);
594static void ctk_tree_view_get_preferred_height (CtkWidget *widget,
595 gint *minimum,
596 gint *natural);
597static void ctk_tree_view_size_allocate (CtkWidget *widget,
598 CtkAllocation *allocation);
599static gboolean ctk_tree_view_draw (CtkWidget *widget,
600 cairo_t *cr);
601static gboolean ctk_tree_view_key_press (CtkWidget *widget,
602 CdkEventKey *event);
603static gboolean ctk_tree_view_key_release (CtkWidget *widget,
604 CdkEventKey *event);
605static gboolean ctk_tree_view_motion (CtkWidget *widget,
606 CdkEventMotion *event);
607static gboolean ctk_tree_view_enter_notify (CtkWidget *widget,
608 CdkEventCrossing *event);
609static gboolean ctk_tree_view_leave_notify (CtkWidget *widget,
610 CdkEventCrossing *event);
611
612static void ctk_tree_view_set_focus_child (CtkContainer *container,
613 CtkWidget *child);
614static gint ctk_tree_view_focus_out (CtkWidget *widget,
615 CdkEventFocus *event);
616static gint ctk_tree_view_focus (CtkWidget *widget,
617 CtkDirectionType direction);
618static void ctk_tree_view_grab_focus (CtkWidget *widget);
619static void ctk_tree_view_style_updated (CtkWidget *widget);
620
621/* container signals */
622static void ctk_tree_view_remove (CtkContainer *container,
623 CtkWidget *widget);
624static void ctk_tree_view_forall (CtkContainer *container,
625 gboolean include_internals,
626 CtkCallback callback,
627 gpointer callback_data);
628
629/* Source side drag signals */
630static void ctk_tree_view_drag_begin (CtkWidget *widget,
631 CdkDragContext *context);
632static void ctk_tree_view_drag_end (CtkWidget *widget,
633 CdkDragContext *context);
634static void ctk_tree_view_drag_data_get (CtkWidget *widget,
635 CdkDragContext *context,
636 CtkSelectionData *selection_data,
637 guint info,
638 guint time);
639static void ctk_tree_view_drag_data_delete (CtkWidget *widget,
640 CdkDragContext *context);
641
642/* Target side drag signals */
643static void ctk_tree_view_drag_leave (CtkWidget *widget,
644 CdkDragContext *context,
645 guint time);
646static gboolean ctk_tree_view_drag_motion (CtkWidget *widget,
647 CdkDragContext *context,
648 gint x,
649 gint y,
650 guint time);
651static gboolean ctk_tree_view_drag_drop (CtkWidget *widget,
652 CdkDragContext *context,
653 gint x,
654 gint y,
655 guint time);
656static void ctk_tree_view_drag_data_received (CtkWidget *widget,
657 CdkDragContext *context,
658 gint x,
659 gint y,
660 CtkSelectionData *selection_data,
661 guint info,
662 guint time);
663
664/* tree_model signals */
665static gboolean ctk_tree_view_real_move_cursor (CtkTreeView *tree_view,
666 CtkMovementStep step,
667 gint count);
668static gboolean ctk_tree_view_real_select_all (CtkTreeView *tree_view);
669static gboolean ctk_tree_view_real_unselect_all (CtkTreeView *tree_view);
670static gboolean ctk_tree_view_real_select_cursor_row (CtkTreeView *tree_view,
671 gboolean start_editing);
672static gboolean ctk_tree_view_real_toggle_cursor_row (CtkTreeView *tree_view);
673static gboolean ctk_tree_view_real_expand_collapse_cursor_row (CtkTreeView *tree_view,
674 gboolean logical,
675 gboolean expand,
676 gboolean open_all);
677static gboolean ctk_tree_view_real_select_cursor_parent (CtkTreeView *tree_view);
678static void ctk_tree_view_row_changed (CtkTreeModel *model,
679 CtkTreePath *path,
680 CtkTreeIter *iter,
681 gpointer data);
682static void ctk_tree_view_row_inserted (CtkTreeModel *model,
683 CtkTreePath *path,
684 CtkTreeIter *iter,
685 gpointer data);
686static void ctk_tree_view_row_has_child_toggled (CtkTreeModel *model,
687 CtkTreePath *path,
688 CtkTreeIter *iter,
689 gpointer data);
690static void ctk_tree_view_row_deleted (CtkTreeModel *model,
691 CtkTreePath *path,
692 gpointer data);
693static void ctk_tree_view_rows_reordered (CtkTreeModel *model,
694 CtkTreePath *parent,
695 CtkTreeIter *iter,
696 gint *new_order,
697 gpointer data);
698
699/* Incremental reflow */
700static gboolean validate_row (CtkTreeView *tree_view,
701 CtkRBTree *tree,
702 CtkRBNode *node,
703 CtkTreeIter *iter,
704 CtkTreePath *path);
705static void validate_visible_area (CtkTreeView *tree_view);
706static gboolean do_validate_rows (CtkTreeView *tree_view,
707 gboolean queue_resize);
708static gboolean validate_rows (CtkTreeView *tree_view);
709static void install_presize_handler (CtkTreeView *tree_view);
710static void install_scroll_sync_handler (CtkTreeView *tree_view);
711static void ctk_tree_view_set_top_row (CtkTreeView *tree_view,
712 CtkTreePath *path,
713 gint offset);
714static void ctk_tree_view_dy_to_top_row (CtkTreeView *tree_view);
715static void ctk_tree_view_top_row_to_dy (CtkTreeView *tree_view);
716static void invalidate_empty_focus (CtkTreeView *tree_view);
717
718/* Internal functions */
719static gboolean ctk_tree_view_is_expander_column (CtkTreeView *tree_view,
720 CtkTreeViewColumn *column);
721static inline gboolean ctk_tree_view_draw_expanders (CtkTreeView *tree_view);
722static void ctk_tree_view_add_move_binding (CtkBindingSet *binding_set,
723 guint keyval,
724 guint modmask,
725 gboolean add_shifted_binding,
726 CtkMovementStep step,
727 gint count);
728static gint ctk_tree_view_unref_and_check_selection_tree (CtkTreeView *tree_view,
729 CtkRBTree *tree);
730static void ctk_tree_view_queue_draw_path (CtkTreeView *tree_view,
731 CtkTreePath *path,
732 const CdkRectangle *clip_rect);
733static void ctk_tree_view_queue_draw_arrow (CtkTreeView *tree_view,
734 CtkRBTree *tree,
735 CtkRBNode *node);
736static void ctk_tree_view_draw_arrow (CtkTreeView *tree_view,
737 cairo_t *cr,
738 CtkRBTree *tree,
739 CtkRBNode *node);
740static void ctk_tree_view_get_arrow_xrange (CtkTreeView *tree_view,
741 CtkRBTree *tree,
742 gint *x1,
743 gint *x2);
744static void ctk_tree_view_adjustment_changed (CtkAdjustment *adjustment,
745 CtkTreeView *tree_view);
746static void ctk_tree_view_build_tree (CtkTreeView *tree_view,
747 CtkRBTree *tree,
748 CtkTreeIter *iter,
749 gint depth,
750 gboolean recurse);
751static void ctk_tree_view_clamp_node_visible (CtkTreeView *tree_view,
752 CtkRBTree *tree,
753 CtkRBNode *node);
754static void ctk_tree_view_clamp_column_visible (CtkTreeView *tree_view,
755 CtkTreeViewColumn *column,
756 gboolean focus_to_cell);
757static gboolean ctk_tree_view_maybe_begin_dragging_row (CtkTreeView *tree_view);
758static void ctk_tree_view_focus_to_cursor (CtkTreeView *tree_view);
759static void ctk_tree_view_move_cursor_up_down (CtkTreeView *tree_view,
760 gint count);
761static void ctk_tree_view_move_cursor_page_up_down (CtkTreeView *tree_view,
762 gint count);
763static void ctk_tree_view_move_cursor_left_right (CtkTreeView *tree_view,
764 gint count);
765static void ctk_tree_view_move_cursor_start_end (CtkTreeView *tree_view,
766 gint count);
767static gboolean ctk_tree_view_real_collapse_row (CtkTreeView *tree_view,
768 CtkTreePath *path,
769 CtkRBTree *tree,
770 CtkRBNode *node,
771 gboolean animate);
772static gboolean ctk_tree_view_real_expand_row (CtkTreeView *tree_view,
773 CtkTreePath *path,
774 CtkRBTree *tree,
775 CtkRBNode *node,
776 gboolean open_all,
777 gboolean animate);
778static void ctk_tree_view_real_set_cursor (CtkTreeView *tree_view,
779 CtkTreePath *path,
780 SetCursorFlags flags);
781static gboolean ctk_tree_view_has_can_focus_cell (CtkTreeView *tree_view);
782static void column_sizing_notify (GObject *object,
783 GParamSpec *pspec,
784 gpointer data);
785static void ctk_tree_view_stop_rubber_band (CtkTreeView *tree_view);
786static void update_prelight (CtkTreeView *tree_view,
787 int x,
788 int y);
789static void ctk_tree_view_queue_draw_region (CtkWidget *widget,
790 const cairo_region_t *region);
791
792static inline gint ctk_tree_view_get_effective_header_height (CtkTreeView *tree_view);
793
794static inline gint ctk_tree_view_get_cell_area_y_offset (CtkTreeView *tree_view,
795 CtkRBTree *tree,
796 CtkRBNode *node,
797 gint vertical_separator);
798static inline gint ctk_tree_view_get_cell_area_height (CtkTreeView *tree_view,
799 CtkRBNode *node,
800 gint vertical_separator);
801
802static inline gint ctk_tree_view_get_row_y_offset (CtkTreeView *tree_view,
803 CtkRBTree *tree,
804 CtkRBNode *node);
805static inline gint ctk_tree_view_get_row_height (CtkTreeView *tree_view,
806 CtkRBNode *node);
807
808/* interactive search */
809static void ctk_tree_view_ensure_interactive_directory (CtkTreeView *tree_view);
810static void ctk_tree_view_search_window_hide (CtkWidget *search_window,
811 CtkTreeView *tree_view,
812 CdkDevice *device);
813static void ctk_tree_view_search_position_func (CtkTreeView *tree_view,
814 CtkWidget *search_window,
815 gpointer user_data);
816static void ctk_tree_view_search_disable_popdown (CtkEntry *entry,
817 CtkMenu *menu,
818 gpointer data);
819static void ctk_tree_view_search_preedit_changed (CtkIMContext *im_context,
820 CtkTreeView *tree_view);
821static void ctk_tree_view_search_commit (CtkIMContext *im_context,
822 gchar *buf,
823 CtkTreeView *tree_view);
824static void ctk_tree_view_search_activate (CtkEntry *entry,
825 CtkTreeView *tree_view);
826static gboolean ctk_tree_view_real_search_enable_popdown(gpointer data);
827static void ctk_tree_view_search_enable_popdown (CtkWidget *widget,
828 gpointer data);
829static gboolean ctk_tree_view_search_delete_event (CtkWidget *widget,
830 CdkEventAny *event,
831 CtkTreeView *tree_view);
832static gboolean ctk_tree_view_search_button_press_event (CtkWidget *widget,
833 CdkEventButton *event,
834 CtkTreeView *tree_view);
835static gboolean ctk_tree_view_search_scroll_event (CtkWidget *entry,
836 CdkEventScroll *event,
837 CtkTreeView *tree_view);
838static gboolean ctk_tree_view_search_key_press_event (CtkWidget *entry,
839 CdkEventKey *event,
840 CtkTreeView *tree_view);
841static gboolean ctk_tree_view_search_move (CtkWidget *window,
842 CtkTreeView *tree_view,
843 gboolean up);
844static gboolean ctk_tree_view_search_equal_func (CtkTreeModel *model,
845 gint column,
846 const gchar *key,
847 CtkTreeIter *iter,
848 gpointer search_data);
849static gboolean ctk_tree_view_search_iter (CtkTreeModel *model,
850 CtkTreeSelection *selection,
851 CtkTreeIter *iter,
852 const gchar *text,
853 gint *count,
854 gint n);
855static void ctk_tree_view_search_init (CtkWidget *entry,
856 CtkTreeView *tree_view);
857static void ctk_tree_view_put (CtkTreeView *tree_view,
858 CtkWidget *child_widget,
859 CtkTreePath *path,
860 CtkTreeViewColumn*column,
861 const CtkBorder *border);
862static gboolean ctk_tree_view_start_editing (CtkTreeView *tree_view,
863 CtkTreePath *cursor_path,
864 gboolean edit_only);
865static void ctk_tree_view_stop_editing (CtkTreeView *tree_view,
866 gboolean cancel_editing);
867static gboolean ctk_tree_view_real_start_interactive_search (CtkTreeView *tree_view,
868 CdkDevice *device,
869 gboolean keybinding);
870static gboolean ctk_tree_view_start_interactive_search (CtkTreeView *tree_view);
871static CtkTreeViewColumn *ctk_tree_view_get_drop_column (CtkTreeView *tree_view,
872 CtkTreeViewColumn *column,
873 gint drop_position);
874
875/* CtkBuildable */
876static void ctk_tree_view_buildable_add_child (CtkBuildable *tree_view,
877 CtkBuilder *builder,
878 GObject *child,
879 const gchar *type);
880static GObject *ctk_tree_view_buildable_get_internal_child (CtkBuildable *buildable,
881 CtkBuilder *builder,
882 const gchar *childname);
883static void ctk_tree_view_buildable_init (CtkBuildableIface *iface);
884
885/* CtkScrollable */
886static void ctk_tree_view_scrollable_init (CtkScrollableInterface *iface);
887
888static CtkAdjustment *ctk_tree_view_do_get_hadjustment (CtkTreeView *tree_view);
889static void ctk_tree_view_do_set_hadjustment (CtkTreeView *tree_view,
890 CtkAdjustment *adjustment);
891static CtkAdjustment *ctk_tree_view_do_get_vadjustment (CtkTreeView *tree_view);
892static void ctk_tree_view_do_set_vadjustment (CtkTreeView *tree_view,
893 CtkAdjustment *adjustment);
894
895static gboolean scroll_row_timeout (gpointer data);
896static void add_scroll_timeout (CtkTreeView *tree_view);
897static void remove_scroll_timeout (CtkTreeView *tree_view);
898
899static void grab_focus_and_unset_draw_keyfocus (CtkTreeView *tree_view);
900
901/* Gestures */
902static void ctk_tree_view_column_multipress_gesture_pressed (CtkGestureMultiPress *gesture,
903 gint n_press,
904 gdouble x,
905 gdouble y,
906 CtkTreeView *tree_view);
907
908static void ctk_tree_view_multipress_gesture_pressed (CtkGestureMultiPress *gesture,
909 gint n_press,
910 gdouble x,
911 gdouble y,
912 CtkTreeView *tree_view);
913static void ctk_tree_view_multipress_gesture_released (CtkGestureMultiPress *gesture,
914 gint n_press,
915 gdouble x,
916 gdouble y,
917 CtkTreeView *tree_view);
918
919static void ctk_tree_view_column_drag_gesture_begin (CtkGestureDrag *gesture,
920 gdouble start_x,
921 gdouble start_y,
922 CtkTreeView *tree_view);
923static void ctk_tree_view_column_drag_gesture_update (CtkGestureDrag *gesture,
924 gdouble offset_x,
925 gdouble offset_y,
926 CtkTreeView *tree_view);
927static void ctk_tree_view_column_drag_gesture_end (CtkGestureDrag *gesture,
928 gdouble offset_x,
929 gdouble offset_y,
930 CtkTreeView *tree_view);
931
932static void ctk_tree_view_drag_gesture_begin (CtkGestureDrag *gesture,
933 gdouble start_x,
934 gdouble start_y,
935 CtkTreeView *tree_view);
936static void ctk_tree_view_drag_gesture_update (CtkGestureDrag *gesture,
937 gdouble offset_x,
938 gdouble offset_y,
939 CtkTreeView *tree_view);
940static void ctk_tree_view_drag_gesture_end (CtkGestureDrag *gesture,
941 gdouble offset_x,
942 gdouble offset_y,
943 CtkTreeView *tree_view);
944
945static guint tree_view_signals [LAST_SIGNAL] = { 0 };
946static GParamSpec *tree_view_props [LAST_PROP] = { NULL((void*)0) };
947
948
949
950/* GType Methods
951 */
952
953G_DEFINE_TYPE_WITH_CODE (CtkTreeView, ctk_tree_view, CTK_TYPE_CONTAINER,static void ctk_tree_view_init (CtkTreeView *self); static void
ctk_tree_view_class_init (CtkTreeViewClass *klass); static GType
ctk_tree_view_get_type_once (void); static gpointer ctk_tree_view_parent_class
= ((void*)0); static gint CtkTreeView_private_offset; static
void ctk_tree_view_class_intern_init (gpointer klass) { ctk_tree_view_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeView_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeView_private_offset
); ctk_tree_view_class_init ((CtkTreeViewClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_tree_view_get_instance_private
(CtkTreeView *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CtkTreeView_private_offset)))); } GType ctk_tree_view_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_view_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_view_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkTreeView"
), sizeof (CtkTreeViewClass), (GClassInitFunc)(void (*)(void)
) ctk_tree_view_class_intern_init, sizeof (CtkTreeView), (GInstanceInitFunc
)(void (*)(void)) ctk_tree_view_init, (GTypeFlags) 0); { {{ CtkTreeView_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (CtkTreeViewPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_tree_view_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_view_scrollable_init, ((void*)0), (
(void*)0) }; g_type_add_interface_static (g_define_type_id, (
ctk_scrollable_get_type ()), &g_implement_interface_info)
; };} } return g_define_type_id; }
954 G_ADD_PRIVATE (CtkTreeView)static void ctk_tree_view_init (CtkTreeView *self); static void
ctk_tree_view_class_init (CtkTreeViewClass *klass); static GType
ctk_tree_view_get_type_once (void); static gpointer ctk_tree_view_parent_class
= ((void*)0); static gint CtkTreeView_private_offset; static
void ctk_tree_view_class_intern_init (gpointer klass) { ctk_tree_view_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeView_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeView_private_offset
); ctk_tree_view_class_init ((CtkTreeViewClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_tree_view_get_instance_private
(CtkTreeView *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CtkTreeView_private_offset)))); } GType ctk_tree_view_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_view_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_view_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkTreeView"
), sizeof (CtkTreeViewClass), (GClassInitFunc)(void (*)(void)
) ctk_tree_view_class_intern_init, sizeof (CtkTreeView), (GInstanceInitFunc
)(void (*)(void)) ctk_tree_view_init, (GTypeFlags) 0); { {{ CtkTreeView_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (CtkTreeViewPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_tree_view_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_view_scrollable_init, ((void*)0), (
(void*)0) }; g_type_add_interface_static (g_define_type_id, (
ctk_scrollable_get_type ()), &g_implement_interface_info)
; };} } return g_define_type_id; }
955 G_IMPLEMENT_INTERFACE (CTK_TYPE_BUILDABLE,static void ctk_tree_view_init (CtkTreeView *self); static void
ctk_tree_view_class_init (CtkTreeViewClass *klass); static GType
ctk_tree_view_get_type_once (void); static gpointer ctk_tree_view_parent_class
= ((void*)0); static gint CtkTreeView_private_offset; static
void ctk_tree_view_class_intern_init (gpointer klass) { ctk_tree_view_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeView_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeView_private_offset
); ctk_tree_view_class_init ((CtkTreeViewClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_tree_view_get_instance_private
(CtkTreeView *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CtkTreeView_private_offset)))); } GType ctk_tree_view_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_view_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_view_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkTreeView"
), sizeof (CtkTreeViewClass), (GClassInitFunc)(void (*)(void)
) ctk_tree_view_class_intern_init, sizeof (CtkTreeView), (GInstanceInitFunc
)(void (*)(void)) ctk_tree_view_init, (GTypeFlags) 0); { {{ CtkTreeView_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (CtkTreeViewPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_tree_view_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_view_scrollable_init, ((void*)0), (
(void*)0) }; g_type_add_interface_static (g_define_type_id, (
ctk_scrollable_get_type ()), &g_implement_interface_info)
; };} } return g_define_type_id; }
956 ctk_tree_view_buildable_init)static void ctk_tree_view_init (CtkTreeView *self); static void
ctk_tree_view_class_init (CtkTreeViewClass *klass); static GType
ctk_tree_view_get_type_once (void); static gpointer ctk_tree_view_parent_class
= ((void*)0); static gint CtkTreeView_private_offset; static
void ctk_tree_view_class_intern_init (gpointer klass) { ctk_tree_view_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeView_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeView_private_offset
); ctk_tree_view_class_init ((CtkTreeViewClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_tree_view_get_instance_private
(CtkTreeView *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CtkTreeView_private_offset)))); } GType ctk_tree_view_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_view_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_view_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkTreeView"
), sizeof (CtkTreeViewClass), (GClassInitFunc)(void (*)(void)
) ctk_tree_view_class_intern_init, sizeof (CtkTreeView), (GInstanceInitFunc
)(void (*)(void)) ctk_tree_view_init, (GTypeFlags) 0); { {{ CtkTreeView_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (CtkTreeViewPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_tree_view_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_view_scrollable_init, ((void*)0), (
(void*)0) }; g_type_add_interface_static (g_define_type_id, (
ctk_scrollable_get_type ()), &g_implement_interface_info)
; };} } return g_define_type_id; }
957 G_IMPLEMENT_INTERFACE (CTK_TYPE_SCROLLABLE,static void ctk_tree_view_init (CtkTreeView *self); static void
ctk_tree_view_class_init (CtkTreeViewClass *klass); static GType
ctk_tree_view_get_type_once (void); static gpointer ctk_tree_view_parent_class
= ((void*)0); static gint CtkTreeView_private_offset; static
void ctk_tree_view_class_intern_init (gpointer klass) { ctk_tree_view_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeView_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeView_private_offset
); ctk_tree_view_class_init ((CtkTreeViewClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_tree_view_get_instance_private
(CtkTreeView *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CtkTreeView_private_offset)))); } GType ctk_tree_view_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_view_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_view_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkTreeView"
), sizeof (CtkTreeViewClass), (GClassInitFunc)(void (*)(void)
) ctk_tree_view_class_intern_init, sizeof (CtkTreeView), (GInstanceInitFunc
)(void (*)(void)) ctk_tree_view_init, (GTypeFlags) 0); { {{ CtkTreeView_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (CtkTreeViewPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_tree_view_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_view_scrollable_init, ((void*)0), (
(void*)0) }; g_type_add_interface_static (g_define_type_id, (
ctk_scrollable_get_type ()), &g_implement_interface_info)
; };} } return g_define_type_id; }
958 ctk_tree_view_scrollable_init))static void ctk_tree_view_init (CtkTreeView *self); static void
ctk_tree_view_class_init (CtkTreeViewClass *klass); static GType
ctk_tree_view_get_type_once (void); static gpointer ctk_tree_view_parent_class
= ((void*)0); static gint CtkTreeView_private_offset; static
void ctk_tree_view_class_intern_init (gpointer klass) { ctk_tree_view_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeView_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeView_private_offset
); ctk_tree_view_class_init ((CtkTreeViewClass*) klass); } __attribute__
((__unused__)) static inline gpointer ctk_tree_view_get_instance_private
(CtkTreeView *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CtkTreeView_private_offset)))); } GType ctk_tree_view_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_view_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_view_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("CtkTreeView"
), sizeof (CtkTreeViewClass), (GClassInitFunc)(void (*)(void)
) ctk_tree_view_class_intern_init, sizeof (CtkTreeView), (GInstanceInitFunc
)(void (*)(void)) ctk_tree_view_init, (GTypeFlags) 0); { {{ CtkTreeView_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (CtkTreeViewPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_tree_view_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_view_scrollable_init, ((void*)0), (
(void*)0) }; g_type_add_interface_static (g_define_type_id, (
ctk_scrollable_get_type ()), &g_implement_interface_info)
; };} } return g_define_type_id; }
959
960static void
961ctk_tree_view_class_init (CtkTreeViewClass *class)
962{
963 GObjectClass *o_class;
964 CtkWidgetClass *widget_class;
965 CtkContainerClass *container_class;
966 CtkBindingSet *binding_set;
967
968 binding_set = ctk_binding_set_by_class (class);
969
970 o_class = (GObjectClass *) class;
971 widget_class = (CtkWidgetClass *) class;
972 container_class = (CtkContainerClass *) class;
973
974 /* GObject signals */
975 o_class->set_property = ctk_tree_view_set_property;
976 o_class->get_property = ctk_tree_view_get_property;
977 o_class->finalize = ctk_tree_view_finalize;
978
979 /* CtkWidget signals */
980 widget_class->destroy = ctk_tree_view_destroy;
981 widget_class->map = ctk_tree_view_map;
982 widget_class->unmap = ctk_tree_view_unmap;
983 widget_class->realize = ctk_tree_view_realize;
984 widget_class->unrealize = ctk_tree_view_unrealize;
985 widget_class->get_preferred_width = ctk_tree_view_get_preferred_width;
986 widget_class->get_preferred_height = ctk_tree_view_get_preferred_height;
987 widget_class->size_allocate = ctk_tree_view_size_allocate;
988 widget_class->motion_notify_event = ctk_tree_view_motion;
989 widget_class->draw = ctk_tree_view_draw;
990 widget_class->key_press_event = ctk_tree_view_key_press;
991 widget_class->key_release_event = ctk_tree_view_key_release;
992 widget_class->enter_notify_event = ctk_tree_view_enter_notify;
993 widget_class->leave_notify_event = ctk_tree_view_leave_notify;
994 widget_class->focus_out_event = ctk_tree_view_focus_out;
995 widget_class->drag_begin = ctk_tree_view_drag_begin;
996 widget_class->drag_end = ctk_tree_view_drag_end;
997 widget_class->drag_data_get = ctk_tree_view_drag_data_get;
998 widget_class->drag_data_delete = ctk_tree_view_drag_data_delete;
999 widget_class->drag_leave = ctk_tree_view_drag_leave;
1000 widget_class->drag_motion = ctk_tree_view_drag_motion;
1001 widget_class->drag_drop = ctk_tree_view_drag_drop;
1002 widget_class->drag_data_received = ctk_tree_view_drag_data_received;
1003 widget_class->focus = ctk_tree_view_focus;
1004 widget_class->grab_focus = ctk_tree_view_grab_focus;
1005 widget_class->style_updated = ctk_tree_view_style_updated;
1006 widget_class->queue_draw_region = ctk_tree_view_queue_draw_region;
1007
1008 /* CtkContainer signals */
1009 container_class->remove = ctk_tree_view_remove;
1010 container_class->forall = ctk_tree_view_forall;
1011 container_class->set_focus_child = ctk_tree_view_set_focus_child;
1012
1013 class->move_cursor = ctk_tree_view_real_move_cursor;
1014 class->select_all = ctk_tree_view_real_select_all;
1015 class->unselect_all = ctk_tree_view_real_unselect_all;
1016 class->select_cursor_row = ctk_tree_view_real_select_cursor_row;
1017 class->toggle_cursor_row = ctk_tree_view_real_toggle_cursor_row;
1018 class->expand_collapse_cursor_row = ctk_tree_view_real_expand_collapse_cursor_row;
1019 class->select_cursor_parent = ctk_tree_view_real_select_cursor_parent;
1020 class->start_interactive_search = ctk_tree_view_start_interactive_search;
1021
1022 /* Properties */
1023
1024 g_object_class_override_property (o_class, PROP_HADJUSTMENT, "hadjustment");
1025 g_object_class_override_property (o_class, PROP_VADJUSTMENT, "vadjustment");
1026 g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
1027 g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
1028
1029 tree_view_props[PROP_MODEL] =
1030 g_param_spec_object ("model",
1031 P_("TreeView Model")g_dgettext("ctk30" "-properties","TreeView Model"),
1032 P_("The model for the tree view")g_dgettext("ctk30" "-properties","The model for the tree view"
)
,
1033 CTK_TYPE_TREE_MODEL(ctk_tree_model_get_type ()),
1034 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1035
1036 tree_view_props[PROP_HEADERS_VISIBLE] =
1037 g_param_spec_boolean ("headers-visible",
1038 P_("Headers Visible")g_dgettext("ctk30" "-properties","Headers Visible"),
1039 P_("Show the column header buttons")g_dgettext("ctk30" "-properties","Show the column header buttons"
)
,
1040 TRUE(!(0)),
1041 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1042
1043 tree_view_props[PROP_HEADERS_CLICKABLE] =
1044 g_param_spec_boolean ("headers-clickable",
1045 P_("Headers Clickable")g_dgettext("ctk30" "-properties","Headers Clickable"),
1046 P_("Column headers respond to click events")g_dgettext("ctk30" "-properties","Column headers respond to click events"
)
,
1047 TRUE(!(0)),
1048 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1049
1050 tree_view_props[PROP_EXPANDER_COLUMN] =
1051 g_param_spec_object ("expander-column",
1052 P_("Expander Column")g_dgettext("ctk30" "-properties","Expander Column"),
1053 P_("Set the column for the expander column")g_dgettext("ctk30" "-properties","Set the column for the expander column"
)
,
1054 CTK_TYPE_TREE_VIEW_COLUMN(ctk_tree_view_column_get_type ()),
1055 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1056
1057 tree_view_props[PROP_REORDERABLE] =
1058 g_param_spec_boolean ("reorderable",
1059 P_("Reorderable")g_dgettext("ctk30" "-properties","Reorderable"),
1060 P_("View is reorderable")g_dgettext("ctk30" "-properties","View is reorderable"),
1061 FALSE(0),
1062 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1063
1064 /**
1065 * CtkTreeView:rules-hint:
1066 *
1067 * Sets a hint to the theme to draw rows in alternating colors.
1068 *
1069 * Deprecated: 3.14: The theme is responsible for drawing rows
1070 * using zebra striping
1071 */
1072 tree_view_props[PROP_RULES_HINT] =
1073 g_param_spec_boolean ("rules-hint",
1074 P_("Rules Hint")g_dgettext("ctk30" "-properties","Rules Hint"),
1075 P_("Set a hint to the theme engine to draw rows in alternating colors")g_dgettext("ctk30" "-properties","Set a hint to the theme engine to draw rows in alternating colors"
)
,
1076 FALSE(0),
1077 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_DEPRECATED);
1078
1079 tree_view_props[PROP_ENABLE_SEARCH] =
1080 g_param_spec_boolean ("enable-search",
1081 P_("Enable Search")g_dgettext("ctk30" "-properties","Enable Search"),
1082 P_("View allows user to search through columns interactively")g_dgettext("ctk30" "-properties","View allows user to search through columns interactively"
)
,
1083 TRUE(!(0)),
1084 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1085
1086 tree_view_props[PROP_SEARCH_COLUMN] =
1087 g_param_spec_int ("search-column",
1088 P_("Search Column")g_dgettext("ctk30" "-properties","Search Column"),
1089 P_("Model column to search through during interactive search")g_dgettext("ctk30" "-properties","Model column to search through during interactive search"
)
,
1090 -1, G_MAXINT2147483647,
1091 -1,
1092 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1093
1094 /**
1095 * CtkTreeView:fixed-height-mode:
1096 *
1097 * Setting the ::fixed-height-mode property to %TRUE speeds up
1098 * #CtkTreeView by assuming that all rows have the same height.
1099 * Only enable this option if all rows are the same height.
1100 * Please see ctk_tree_view_set_fixed_height_mode() for more
1101 * information on this option.
1102 *
1103 * Since: 2.4
1104 */
1105 tree_view_props[PROP_FIXED_HEIGHT_MODE] =
1106 g_param_spec_boolean ("fixed-height-mode",
1107 P_("Fixed Height Mode")g_dgettext("ctk30" "-properties","Fixed Height Mode"),
1108 P_("Speeds up CtkTreeView by assuming that all rows have the same height")g_dgettext("ctk30" "-properties","Speeds up CtkTreeView by assuming that all rows have the same height"
)
,
1109 FALSE(0),
1110 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1111
1112 /**
1113 * CtkTreeView:hover-selection:
1114 *
1115 * Enables or disables the hover selection mode of @tree_view.
1116 * Hover selection makes the selected row follow the pointer.
1117 * Currently, this works only for the selection modes
1118 * %CTK_SELECTION_SINGLE and %CTK_SELECTION_BROWSE.
1119 *
1120 * This mode is primarily intended for treeviews in popups, e.g.
1121 * in #CtkComboBox or #CtkEntryCompletion.
1122 *
1123 * Since: 2.6
1124 */
1125 tree_view_props[PROP_HOVER_SELECTION] =
1126 g_param_spec_boolean ("hover-selection",
1127 P_("Hover Selection")g_dgettext("ctk30" "-properties","Hover Selection"),
1128 P_("Whether the selection should follow the pointer")g_dgettext("ctk30" "-properties","Whether the selection should follow the pointer"
)
,
1129 FALSE(0),
1130 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1131
1132 /**
1133 * CtkTreeView:hover-expand:
1134 *
1135 * Enables or disables the hover expansion mode of @tree_view.
1136 * Hover expansion makes rows expand or collapse if the pointer moves
1137 * over them.
1138 *
1139 * This mode is primarily intended for treeviews in popups, e.g.
1140 * in #CtkComboBox or #CtkEntryCompletion.
1141 *
1142 * Since: 2.6
1143 */
1144 tree_view_props[PROP_HOVER_EXPAND] =
1145 g_param_spec_boolean ("hover-expand",
1146 P_("Hover Expand")g_dgettext("ctk30" "-properties","Hover Expand"),
1147 P_("Whether rows should be expanded/collapsed when the pointer moves over them")g_dgettext("ctk30" "-properties","Whether rows should be expanded/collapsed when the pointer moves over them"
)
,
1148 FALSE(0),
1149 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1150
1151 /**
1152 * CtkTreeView:show-expanders:
1153 *
1154 * %TRUE if the view has expanders.
1155 *
1156 * Since: 2.12
1157 */
1158 tree_view_props[PROP_SHOW_EXPANDERS] =
1159 g_param_spec_boolean ("show-expanders",
1160 P_("Show Expanders")g_dgettext("ctk30" "-properties","Show Expanders"),
1161 P_("View has expanders")g_dgettext("ctk30" "-properties","View has expanders"),
1162 TRUE(!(0)),
1163 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1164
1165 /**
1166 * CtkTreeView:level-indentation:
1167 *
1168 * Extra indentation for each level.
1169 *
1170 * Since: 2.12
1171 */
1172 tree_view_props[PROP_LEVEL_INDENTATION] =
1173 g_param_spec_int ("level-indentation",
1174 P_("Level Indentation")g_dgettext("ctk30" "-properties","Level Indentation"),
1175 P_("Extra indentation for each level")g_dgettext("ctk30" "-properties","Extra indentation for each level"
)
,
1176 0, G_MAXINT2147483647,
1177 0,
1178 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1179
1180 tree_view_props[PROP_RUBBER_BANDING] =
1181 g_param_spec_boolean ("rubber-banding",
1182 P_("Rubber Banding")g_dgettext("ctk30" "-properties","Rubber Banding"),
1183 P_("Whether to enable selection of multiple items by dragging the mouse pointer")g_dgettext("ctk30" "-properties","Whether to enable selection of multiple items by dragging the mouse pointer"
)
,
1184 FALSE(0),
1185 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1186
1187 tree_view_props[PROP_ENABLE_GRID_LINES] =
1188 g_param_spec_enum ("enable-grid-lines",
1189 P_("Enable Grid Lines")g_dgettext("ctk30" "-properties","Enable Grid Lines"),
1190 P_("Whether grid lines should be drawn in the tree view")g_dgettext("ctk30" "-properties","Whether grid lines should be drawn in the tree view"
)
,
1191 CTK_TYPE_TREE_VIEW_GRID_LINES(ctk_tree_view_grid_lines_get_type ()),
1192 CTK_TREE_VIEW_GRID_LINES_NONE,
1193 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1194
1195 tree_view_props[PROP_ENABLE_TREE_LINES] =
1196 g_param_spec_boolean ("enable-tree-lines",
1197 P_("Enable Tree Lines")g_dgettext("ctk30" "-properties","Enable Tree Lines"),
1198 P_("Whether tree lines should be drawn in the tree view")g_dgettext("ctk30" "-properties","Whether tree lines should be drawn in the tree view"
)
,
1199 FALSE(0),
1200 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1201
1202 tree_view_props[PROP_TOOLTIP_COLUMN] =
1203 g_param_spec_int ("tooltip-column",
1204 P_("Tooltip Column")g_dgettext("ctk30" "-properties","Tooltip Column"),
1205 P_("The column in the model containing the tooltip texts for the rows")g_dgettext("ctk30" "-properties","The column in the model containing the tooltip texts for the rows"
)
,
1206 -1, G_MAXINT2147483647,
1207 -1,
1208 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1209
1210 /**
1211 * CtkTreeView:activate-on-single-click:
1212 *
1213 * The activate-on-single-click property specifies whether the "row-activated" signal
1214 * will be emitted after a single click.
1215 *
1216 * Since: 3.8
1217 */
1218 tree_view_props[PROP_ACTIVATE_ON_SINGLE_CLICK] =
1219 g_param_spec_boolean ("activate-on-single-click",
1220 P_("Activate on Single Click")g_dgettext("ctk30" "-properties","Activate on Single Click"),
1221 P_("Activate row on a single click")g_dgettext("ctk30" "-properties","Activate row on a single click"
)
,
1222 FALSE(0),
1223 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1224
1225 g_object_class_install_properties (o_class, LAST_PROP, tree_view_props);
1226
1227 /* Style properties */
1228#define _TREE_VIEW_EXPANDER_SIZE14 14
1229#define _TREE_VIEW_VERTICAL_SEPARATOR2 2
1230#define _TREE_VIEW_HORIZONTAL_SEPARATOR2 2
1231
1232 ctk_widget_class_install_style_property (widget_class,
1233 g_param_spec_int ("expander-size",
1234 P_("Expander Size")g_dgettext("ctk30" "-properties","Expander Size"),
1235 P_("Size of the expander arrow")g_dgettext("ctk30" "-properties","Size of the expander arrow"
)
,
1236 0,
1237 G_MAXINT2147483647,
1238 _TREE_VIEW_EXPANDER_SIZE14,
1239 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1240
1241 ctk_widget_class_install_style_property (widget_class,
1242 g_param_spec_int ("vertical-separator",
1243 P_("Vertical Separator Width")g_dgettext("ctk30" "-properties","Vertical Separator Width"),
1244 P_("Vertical space between cells. Must be an even number")g_dgettext("ctk30" "-properties","Vertical space between cells. Must be an even number"
)
,
1245 0,
1246 G_MAXINT2147483647,
1247 _TREE_VIEW_VERTICAL_SEPARATOR2,
1248 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1249
1250 ctk_widget_class_install_style_property (widget_class,
1251 g_param_spec_int ("horizontal-separator",
1252 P_("Horizontal Separator Width")g_dgettext("ctk30" "-properties","Horizontal Separator Width"
)
,
1253 P_("Horizontal space between cells. Must be an even number")g_dgettext("ctk30" "-properties","Horizontal space between cells. Must be an even number"
)
,
1254 0,
1255 G_MAXINT2147483647,
1256 _TREE_VIEW_HORIZONTAL_SEPARATOR2,
1257 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1258
1259 ctk_widget_class_install_style_property (widget_class,
1260 g_param_spec_boolean ("allow-rules",
1261 P_("Allow Rules")g_dgettext("ctk30" "-properties","Allow Rules"),
1262 P_("Allow drawing of alternating color rows")g_dgettext("ctk30" "-properties","Allow drawing of alternating color rows"
)
,
1263 TRUE(!(0)),
1264 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1265
1266 ctk_widget_class_install_style_property (widget_class,
1267 g_param_spec_boolean ("indent-expanders",
1268 P_("Indent Expanders")g_dgettext("ctk30" "-properties","Indent Expanders"),
1269 P_("Make the expanders indented")g_dgettext("ctk30" "-properties","Make the expanders indented"
)
,
1270 TRUE(!(0)),
1271 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1272G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
1273 ctk_widget_class_install_style_property (widget_class,
1274 g_param_spec_boxed ("even-row-color",
1275 P_("Even Row Color")g_dgettext("ctk30" "-properties","Even Row Color"),
1276 P_("Color to use for even rows")g_dgettext("ctk30" "-properties","Color to use for even rows"
)
,
1277 CDK_TYPE_COLOR(cdk_color_get_type ()),
1278 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1279
1280 ctk_widget_class_install_style_property (widget_class,
1281 g_param_spec_boxed ("odd-row-color",
1282 P_("Odd Row Color")g_dgettext("ctk30" "-properties","Odd Row Color"),
1283 P_("Color to use for odd rows")g_dgettext("ctk30" "-properties","Color to use for odd rows"),
1284 CDK_TYPE_COLOR(cdk_color_get_type ()),
1285 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1286G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
1287
1288 ctk_widget_class_install_style_property (widget_class,
1289 g_param_spec_int ("grid-line-width",
1290 P_("Grid line width")g_dgettext("ctk30" "-properties","Grid line width"),
1291 P_("Width, in pixels, of the tree view grid lines")g_dgettext("ctk30" "-properties","Width, in pixels, of the tree view grid lines"
)
,
1292 0, G_MAXINT2147483647, 1,
1293 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1294
1295 ctk_widget_class_install_style_property (widget_class,
1296 g_param_spec_int ("tree-line-width",
1297 P_("Tree line width")g_dgettext("ctk30" "-properties","Tree line width"),
1298 P_("Width, in pixels, of the tree view lines")g_dgettext("ctk30" "-properties","Width, in pixels, of the tree view lines"
)
,
1299 0, G_MAXINT2147483647, 1,
1300 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1301
1302 ctk_widget_class_install_style_property (widget_class,
1303 g_param_spec_string ("grid-line-pattern",
1304 P_("Grid line pattern")g_dgettext("ctk30" "-properties","Grid line pattern"),
1305 P_("Dash pattern used to draw the tree view grid lines")g_dgettext("ctk30" "-properties","Dash pattern used to draw the tree view grid lines"
)
,
1306 "\1\1",
1307 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1308
1309 ctk_widget_class_install_style_property (widget_class,
1310 g_param_spec_string ("tree-line-pattern",
1311 P_("Tree line pattern")g_dgettext("ctk30" "-properties","Tree line pattern"),
1312 P_("Dash pattern used to draw the tree view lines")g_dgettext("ctk30" "-properties","Dash pattern used to draw the tree view lines"
)
,
1313 "\1\1",
1314 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
1315
1316 /* Signals */
1317 /**
1318 * CtkTreeView::row-activated:
1319 * @tree_view: the object on which the signal is emitted
1320 * @path: the #CtkTreePath for the activated row
1321 * @column: the #CtkTreeViewColumn in which the activation occurred
1322 *
1323 * The "row-activated" signal is emitted when the method
1324 * ctk_tree_view_row_activated() is called, when the user double
1325 * clicks a treeview row with the "activate-on-single-click"
1326 * property set to %FALSE, or when the user single clicks a row when
1327 * the "activate-on-single-click" property set to %TRUE. It is also
1328 * emitted when a non-editable row is selected and one of the keys:
1329 * Space, Shift+Space, Return or Enter is pressed.
1330 *
1331 * For selection handling refer to the
1332 * [tree widget conceptual overview][TreeWidget]
1333 * as well as #CtkTreeSelection.
1334 */
1335 tree_view_signals[ROW_ACTIVATED] =
1336 g_signal_new (I_("row-activated")g_intern_static_string ("row-activated"),
1337 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1338 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1339 G_STRUCT_OFFSET (CtkTreeViewClass, row_activated)((glong) __builtin_offsetof(CtkTreeViewClass, row_activated)),
1340 NULL((void*)0), NULL((void*)0),
1341 _ctk_marshal_VOID__BOXED_OBJECT,
1342 G_TYPE_NONE((GType) ((1) << (2))), 2,
1343 CTK_TYPE_TREE_PATH(ctk_tree_path_get_type ()),
1344 CTK_TYPE_TREE_VIEW_COLUMN(ctk_tree_view_column_get_type ()));
1345 g_signal_set_va_marshaller (tree_view_signals[ROW_ACTIVATED],
1346 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1347 _ctk_marshal_VOID__BOXED_OBJECTv);
1348
1349 /**
1350 * CtkTreeView::test-expand-row:
1351 * @tree_view: the object on which the signal is emitted
1352 * @iter: the tree iter of the row to expand
1353 * @path: a tree path that points to the row
1354 *
1355 * The given row is about to be expanded (show its children nodes). Use this
1356 * signal if you need to control the expandability of individual rows.
1357 *
1358 * Returns: %FALSE to allow expansion, %TRUE to reject
1359 */
1360 tree_view_signals[TEST_EXPAND_ROW] =
1361 g_signal_new (I_("test-expand-row")g_intern_static_string ("test-expand-row"),
1362 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1363 G_SIGNAL_RUN_LAST,
1364 G_STRUCT_OFFSET (CtkTreeViewClass, test_expand_row)((glong) __builtin_offsetof(CtkTreeViewClass, test_expand_row
))
,
1365 _ctk_boolean_handled_accumulator, NULL((void*)0),
1366 _ctk_marshal_BOOLEAN__BOXED_BOXEDg_cclosure_marshal_BOOLEAN__BOXED_BOXED,
1367 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
1368 CTK_TYPE_TREE_ITER(ctk_tree_iter_get_type ()),
1369 CTK_TYPE_TREE_PATH(ctk_tree_path_get_type ()));
1370 g_signal_set_va_marshaller (tree_view_signals[TEST_EXPAND_ROW],
1371 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1372 _ctk_marshal_BOOLEAN__BOXED_BOXEDvg_cclosure_marshal_BOOLEAN__BOXED_BOXEDv);
1373
1374 /**
1375 * CtkTreeView::test-collapse-row:
1376 * @tree_view: the object on which the signal is emitted
1377 * @iter: the tree iter of the row to collapse
1378 * @path: a tree path that points to the row
1379 *
1380 * The given row is about to be collapsed (hide its children nodes). Use this
1381 * signal if you need to control the collapsibility of individual rows.
1382 *
1383 * Returns: %FALSE to allow collapsing, %TRUE to reject
1384 */
1385 tree_view_signals[TEST_COLLAPSE_ROW] =
1386 g_signal_new (I_("test-collapse-row")g_intern_static_string ("test-collapse-row"),
1387 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1388 G_SIGNAL_RUN_LAST,
1389 G_STRUCT_OFFSET (CtkTreeViewClass, test_collapse_row)((glong) __builtin_offsetof(CtkTreeViewClass, test_collapse_row
))
,
1390 _ctk_boolean_handled_accumulator, NULL((void*)0),
1391 _ctk_marshal_BOOLEAN__BOXED_BOXEDg_cclosure_marshal_BOOLEAN__BOXED_BOXED,
1392 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
1393 CTK_TYPE_TREE_ITER(ctk_tree_iter_get_type ()),
1394 CTK_TYPE_TREE_PATH(ctk_tree_path_get_type ()));
1395 g_signal_set_va_marshaller (tree_view_signals[TEST_COLLAPSE_ROW],
1396 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1397 _ctk_marshal_BOOLEAN__BOXED_BOXEDvg_cclosure_marshal_BOOLEAN__BOXED_BOXEDv);
1398
1399 /**
1400 * CtkTreeView::row-expanded:
1401 * @tree_view: the object on which the signal is emitted
1402 * @iter: the tree iter of the expanded row
1403 * @path: a tree path that points to the row
1404 *
1405 * The given row has been expanded (child nodes are shown).
1406 */
1407 tree_view_signals[ROW_EXPANDED] =
1408 g_signal_new (I_("row-expanded")g_intern_static_string ("row-expanded"),
1409 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1410 G_SIGNAL_RUN_LAST,
1411 G_STRUCT_OFFSET (CtkTreeViewClass, row_expanded)((glong) __builtin_offsetof(CtkTreeViewClass, row_expanded)),
1412 NULL((void*)0), NULL((void*)0),
1413 _ctk_marshal_VOID__BOXED_BOXED,
1414 G_TYPE_NONE((GType) ((1) << (2))), 2,
1415 CTK_TYPE_TREE_ITER(ctk_tree_iter_get_type ()),
1416 CTK_TYPE_TREE_PATH(ctk_tree_path_get_type ()));
1417 g_signal_set_va_marshaller (tree_view_signals[ROW_EXPANDED],
1418 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1419 _ctk_marshal_VOID__BOXED_BOXEDv);
1420
1421 /**
1422 * CtkTreeView::row-collapsed:
1423 * @tree_view: the object on which the signal is emitted
1424 * @iter: the tree iter of the collapsed row
1425 * @path: a tree path that points to the row
1426 *
1427 * The given row has been collapsed (child nodes are hidden).
1428 */
1429 tree_view_signals[ROW_COLLAPSED] =
1430 g_signal_new (I_("row-collapsed")g_intern_static_string ("row-collapsed"),
1431 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1432 G_SIGNAL_RUN_LAST,
1433 G_STRUCT_OFFSET (CtkTreeViewClass, row_collapsed)((glong) __builtin_offsetof(CtkTreeViewClass, row_collapsed)),
1434 NULL((void*)0), NULL((void*)0),
1435 _ctk_marshal_VOID__BOXED_BOXED,
1436 G_TYPE_NONE((GType) ((1) << (2))), 2,
1437 CTK_TYPE_TREE_ITER(ctk_tree_iter_get_type ()),
1438 CTK_TYPE_TREE_PATH(ctk_tree_path_get_type ()));
1439 g_signal_set_va_marshaller (tree_view_signals[ROW_COLLAPSED],
1440 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1441 _ctk_marshal_VOID__BOXED_BOXEDv);
1442
1443 /**
1444 * CtkTreeView::columns-changed:
1445 * @tree_view: the object on which the signal is emitted
1446 *
1447 * The number of columns of the treeview has changed.
1448 */
1449 tree_view_signals[COLUMNS_CHANGED] =
1450 g_signal_new (I_("columns-changed")g_intern_static_string ("columns-changed"),
1451 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1452 G_SIGNAL_RUN_LAST,
1453 G_STRUCT_OFFSET (CtkTreeViewClass, columns_changed)((glong) __builtin_offsetof(CtkTreeViewClass, columns_changed
))
,
1454 NULL((void*)0), NULL((void*)0),
1455 NULL((void*)0),
1456 G_TYPE_NONE((GType) ((1) << (2))), 0);
1457
1458 /**
1459 * CtkTreeView::cursor-changed:
1460 * @tree_view: the object on which the signal is emitted
1461 *
1462 * The position of the cursor (focused cell) has changed.
1463 */
1464 tree_view_signals[CURSOR_CHANGED] =
1465 g_signal_new (I_("cursor-changed")g_intern_static_string ("cursor-changed"),
1466 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1467 G_SIGNAL_RUN_LAST,
1468 G_STRUCT_OFFSET (CtkTreeViewClass, cursor_changed)((glong) __builtin_offsetof(CtkTreeViewClass, cursor_changed)
)
,
1469 NULL((void*)0), NULL((void*)0),
1470 NULL((void*)0),
1471 G_TYPE_NONE((GType) ((1) << (2))), 0);
1472
1473 /**
1474 * CtkTreeView::move-cursor:
1475 * @tree_view: the object on which the signal is emitted.
1476 * @step: the granularity of the move, as a
1477 * #CtkMovementStep. %CTK_MOVEMENT_LOGICAL_POSITIONS,
1478 * %CTK_MOVEMENT_VISUAL_POSITIONS, %CTK_MOVEMENT_DISPLAY_LINES,
1479 * %CTK_MOVEMENT_PAGES and %CTK_MOVEMENT_BUFFER_ENDS are
1480 * supported. %CTK_MOVEMENT_LOGICAL_POSITIONS and
1481 * %CTK_MOVEMENT_VISUAL_POSITIONS are treated identically.
1482 * @direction: the direction to move: +1 to move forwards;
1483 * -1 to move backwards. The resulting movement is
1484 * undefined for all other values.
1485 *
1486 * The #CtkTreeView::move-cursor signal is a [keybinding
1487 * signal][CtkBindingSignal] which gets emitted when the user
1488 * presses one of the cursor keys.
1489 *
1490 * Applications should not connect to it, but may emit it with
1491 * g_signal_emit_by_name() if they need to control the cursor
1492 * programmatically. In contrast to ctk_tree_view_set_cursor() and
1493 * ctk_tree_view_set_cursor_on_cell() when moving horizontally
1494 * #CtkTreeView::move-cursor does not reset the current selection.
1495 *
1496 * Returns: %TRUE if @step is supported, %FALSE otherwise.
1497 */
1498 tree_view_signals[MOVE_CURSOR] =
1499 g_signal_new (I_("move-cursor")g_intern_static_string ("move-cursor"),
1500 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1501 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1502 G_STRUCT_OFFSET (CtkTreeViewClass, move_cursor)((glong) __builtin_offsetof(CtkTreeViewClass, move_cursor)),
1503 NULL((void*)0), NULL((void*)0),
1504 _ctk_marshal_BOOLEAN__ENUM_INT,
1505 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
1506 CTK_TYPE_MOVEMENT_STEP(ctk_movement_step_get_type ()),
1507 G_TYPE_INT((GType) ((6) << (2))));
1508 g_signal_set_va_marshaller (tree_view_signals[MOVE_CURSOR],
1509 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1510 _ctk_marshal_BOOLEAN__ENUM_INTv);
1511
1512 tree_view_signals[SELECT_ALL] =
1513 g_signal_new (I_("select-all")g_intern_static_string ("select-all"),
1514 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1515 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1516 G_STRUCT_OFFSET (CtkTreeViewClass, select_all)((glong) __builtin_offsetof(CtkTreeViewClass, select_all)),
1517 NULL((void*)0), NULL((void*)0),
1518 _ctk_marshal_BOOLEAN__VOID,
1519 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
1520 g_signal_set_va_marshaller (tree_view_signals[SELECT_ALL],
1521 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1522 _ctk_marshal_BOOLEAN__VOIDv);
1523
1524 tree_view_signals[UNSELECT_ALL] =
1525 g_signal_new (I_("unselect-all")g_intern_static_string ("unselect-all"),
1526 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1527 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1528 G_STRUCT_OFFSET (CtkTreeViewClass, unselect_all)((glong) __builtin_offsetof(CtkTreeViewClass, unselect_all)),
1529 NULL((void*)0), NULL((void*)0),
1530 _ctk_marshal_BOOLEAN__VOID,
1531 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
1532 g_signal_set_va_marshaller (tree_view_signals[UNSELECT_ALL],
1533 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1534 _ctk_marshal_BOOLEAN__VOIDv);
1535
1536 tree_view_signals[SELECT_CURSOR_ROW] =
1537 g_signal_new (I_("select-cursor-row")g_intern_static_string ("select-cursor-row"),
1538 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1539 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1540 G_STRUCT_OFFSET (CtkTreeViewClass, select_cursor_row)((glong) __builtin_offsetof(CtkTreeViewClass, select_cursor_row
))
,
1541 NULL((void*)0), NULL((void*)0),
1542 _ctk_marshal_BOOLEAN__BOOLEAN,
1543 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1,
1544 G_TYPE_BOOLEAN((GType) ((5) << (2))));
1545 g_signal_set_va_marshaller (tree_view_signals[SELECT_CURSOR_ROW],
1546 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1547 _ctk_marshal_BOOLEAN__BOOLEANv);
1548
1549 tree_view_signals[TOGGLE_CURSOR_ROW] =
1550 g_signal_new (I_("toggle-cursor-row")g_intern_static_string ("toggle-cursor-row"),
1551 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1552 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1553 G_STRUCT_OFFSET (CtkTreeViewClass, toggle_cursor_row)((glong) __builtin_offsetof(CtkTreeViewClass, toggle_cursor_row
))
,
1554 NULL((void*)0), NULL((void*)0),
1555 _ctk_marshal_BOOLEAN__VOID,
1556 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
1557 g_signal_set_va_marshaller (tree_view_signals[TOGGLE_CURSOR_ROW],
1558 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1559 _ctk_marshal_BOOLEAN__VOIDv);
1560
1561 tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
1562 g_signal_new (I_("expand-collapse-cursor-row")g_intern_static_string ("expand-collapse-cursor-row"),
1563 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1564 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1565 G_STRUCT_OFFSET (CtkTreeViewClass, expand_collapse_cursor_row)((glong) __builtin_offsetof(CtkTreeViewClass, expand_collapse_cursor_row
))
,
1566 NULL((void*)0), NULL((void*)0),
1567 _ctk_marshal_BOOLEAN__BOOLEAN_BOOLEAN_BOOLEAN,
1568 G_TYPE_BOOLEAN((GType) ((5) << (2))), 3,
1569 G_TYPE_BOOLEAN((GType) ((5) << (2))),
1570 G_TYPE_BOOLEAN((GType) ((5) << (2))),
1571 G_TYPE_BOOLEAN((GType) ((5) << (2))));
1572 g_signal_set_va_marshaller (tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW],
1573 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1574 _ctk_marshal_BOOLEAN__BOOLEAN_BOOLEAN_BOOLEANv);
1575
1576 tree_view_signals[SELECT_CURSOR_PARENT] =
1577 g_signal_new (I_("select-cursor-parent")g_intern_static_string ("select-cursor-parent"),
1578 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1579 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1580 G_STRUCT_OFFSET (CtkTreeViewClass, select_cursor_parent)((glong) __builtin_offsetof(CtkTreeViewClass, select_cursor_parent
))
,
1581 NULL((void*)0), NULL((void*)0),
1582 _ctk_marshal_BOOLEAN__VOID,
1583 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
1584 g_signal_set_va_marshaller (tree_view_signals[SELECT_CURSOR_PARENT],
1585 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1586 _ctk_marshal_BOOLEAN__VOIDv);
1587
1588 tree_view_signals[START_INTERACTIVE_SEARCH] =
1589 g_signal_new (I_("start-interactive-search")g_intern_static_string ("start-interactive-search"),
1590 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1591 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1592 G_STRUCT_OFFSET (CtkTreeViewClass, start_interactive_search)((glong) __builtin_offsetof(CtkTreeViewClass, start_interactive_search
))
,
1593 NULL((void*)0), NULL((void*)0),
1594 _ctk_marshal_BOOLEAN__VOID,
1595 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
1596 g_signal_set_va_marshaller (tree_view_signals[START_INTERACTIVE_SEARCH],
1597 G_TYPE_FROM_CLASS (o_class)(((GTypeClass*) (o_class))->g_type),
1598 _ctk_marshal_BOOLEAN__VOIDv);
1599
1600 /* Key bindings */
1601 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_Up0xff52, 0, TRUE(!(0)),
1602 CTK_MOVEMENT_DISPLAY_LINES, -1);
1603 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_KP_Up0xff97, 0, TRUE(!(0)),
1604 CTK_MOVEMENT_DISPLAY_LINES, -1);
1605
1606 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_Down0xff54, 0, TRUE(!(0)),
1607 CTK_MOVEMENT_DISPLAY_LINES, 1);
1608 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_KP_Down0xff99, 0, TRUE(!(0)),
1609 CTK_MOVEMENT_DISPLAY_LINES, 1);
1610
1611 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_p0x070, CDK_CONTROL_MASK, FALSE(0),
1612 CTK_MOVEMENT_DISPLAY_LINES, -1);
1613
1614 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_n0x06e, CDK_CONTROL_MASK, FALSE(0),
1615 CTK_MOVEMENT_DISPLAY_LINES, 1);
1616
1617 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_Home0xff50, 0, TRUE(!(0)),
1618 CTK_MOVEMENT_BUFFER_ENDS, -1);
1619 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_KP_Home0xff95, 0, TRUE(!(0)),
1620 CTK_MOVEMENT_BUFFER_ENDS, -1);
1621
1622 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_End0xff57, 0, TRUE(!(0)),
1623 CTK_MOVEMENT_BUFFER_ENDS, 1);
1624 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_KP_End0xff9c, 0, TRUE(!(0)),
1625 CTK_MOVEMENT_BUFFER_ENDS, 1);
1626
1627 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_Page_Up0xff55, 0, TRUE(!(0)),
1628 CTK_MOVEMENT_PAGES, -1);
1629 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_KP_Page_Up0xff9a, 0, TRUE(!(0)),
1630 CTK_MOVEMENT_PAGES, -1);
1631
1632 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_Page_Down0xff56, 0, TRUE(!(0)),
1633 CTK_MOVEMENT_PAGES, 1);
1634 ctk_tree_view_add_move_binding (binding_set, CDK_KEY_KP_Page_Down0xff9b, 0, TRUE(!(0)),
1635 CTK_MOVEMENT_PAGES, 1);
1636
1637
1638 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Right0xff53, 0, "move-cursor", 2,
1639 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1640 G_TYPE_INT((GType) ((6) << (2))), 1);
1641
1642 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Left0xff51, 0, "move-cursor", 2,
1643 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1644 G_TYPE_INT((GType) ((6) << (2))), -1);
1645
1646 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Right0xff98, 0, "move-cursor", 2,
1647 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1648 G_TYPE_INT((GType) ((6) << (2))), 1);
1649
1650 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Left0xff96, 0, "move-cursor", 2,
1651 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1652 G_TYPE_INT((GType) ((6) << (2))), -1);
1653
1654 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Right0xff53, CDK_CONTROL_MASK,
1655 "move-cursor", 2,
1656 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1657 G_TYPE_INT((GType) ((6) << (2))), 1);
1658
1659 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Left0xff51, CDK_CONTROL_MASK,
1660 "move-cursor", 2,
1661 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1662 G_TYPE_INT((GType) ((6) << (2))), -1);
1663
1664 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Right0xff98, CDK_CONTROL_MASK,
1665 "move-cursor", 2,
1666 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1667 G_TYPE_INT((GType) ((6) << (2))), 1);
1668
1669 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Left0xff96, CDK_CONTROL_MASK,
1670 "move-cursor", 2,
1671 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_VISUAL_POSITIONS,
1672 G_TYPE_INT((GType) ((6) << (2))), -1);
1673
1674 ctk_binding_entry_add_signal (binding_set, CDK_KEY_space0x020, CDK_CONTROL_MASK, "toggle-cursor-row", 0);
1675 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Space0xff80, CDK_CONTROL_MASK, "toggle-cursor-row", 0);
1676
1677 ctk_binding_entry_add_signal (binding_set, CDK_KEY_a0x061, CDK_CONTROL_MASK, "select-all", 0);
1678 ctk_binding_entry_add_signal (binding_set, CDK_KEY_slash0x02f, CDK_CONTROL_MASK, "select-all", 0);
1679
1680 ctk_binding_entry_add_signal (binding_set, CDK_KEY_A0x041, CDK_CONTROL_MASK | CDK_SHIFT_MASK, "unselect-all", 0);
1681 ctk_binding_entry_add_signal (binding_set, CDK_KEY_backslash0x05c, CDK_CONTROL_MASK, "unselect-all", 0);
1682
1683 ctk_binding_entry_add_signal (binding_set, CDK_KEY_space0x020, CDK_SHIFT_MASK, "select-cursor-row", 1,
1684 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1685 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Space0xff80, CDK_SHIFT_MASK, "select-cursor-row", 1,
1686 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1687
1688 ctk_binding_entry_add_signal (binding_set, CDK_KEY_space0x020, 0, "select-cursor-row", 1,
1689 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1690 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Space0xff80, 0, "select-cursor-row", 1,
1691 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1692 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Return0xff0d, 0, "select-cursor-row", 1,
1693 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1694 ctk_binding_entry_add_signal (binding_set, CDK_KEY_ISO_Enter0xfe34, 0, "select-cursor-row", 1,
1695 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1696 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Enter0xff8d, 0, "select-cursor-row", 1,
1697 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1698
1699 /* expand and collapse rows */
1700 ctk_binding_entry_add_signal (binding_set, CDK_KEY_plus0x02b, 0, "expand-collapse-cursor-row", 3,
1701 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1702 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1703 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1704
1705 ctk_binding_entry_add_signal (binding_set, CDK_KEY_asterisk0x02a, 0,
1706 "expand-collapse-cursor-row", 3,
1707 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1708 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1709 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1710 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Multiply0xffaa, 0,
1711 "expand-collapse-cursor-row", 3,
1712 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1713 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1714 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1715
1716 ctk_binding_entry_add_signal (binding_set, CDK_KEY_slash0x02f, 0,
1717 "expand-collapse-cursor-row", 3,
1718 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1719 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1720 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1721 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Divide0xffaf, 0,
1722 "expand-collapse-cursor-row", 3,
1723 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1724 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1725 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1726
1727 /* Not doable on US keyboards */
1728 ctk_binding_entry_add_signal (binding_set, CDK_KEY_plus0x02b, CDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1729 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1730 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1731 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1732 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Add0xffab, 0, "expand-collapse-cursor-row", 3,
1733 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1734 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1735 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1736 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Add0xffab, CDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1737 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1738 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1739 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1740 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Add0xffab, CDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1741 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1742 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1743 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1744 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Right0xff53, CDK_SHIFT_MASK,
1745 "expand-collapse-cursor-row", 3,
1746 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1747 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1748 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1749 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Right0xff98, CDK_SHIFT_MASK,
1750 "expand-collapse-cursor-row", 3,
1751 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1752 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1753 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1754 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Right0xff53,
1755 CDK_CONTROL_MASK | CDK_SHIFT_MASK,
1756 "expand-collapse-cursor-row", 3,
1757 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1758 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1759 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1760 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Right0xff98,
1761 CDK_CONTROL_MASK | CDK_SHIFT_MASK,
1762 "expand-collapse-cursor-row", 3,
1763 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1764 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1765 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1766
1767 ctk_binding_entry_add_signal (binding_set, CDK_KEY_minus0x02d, 0, "expand-collapse-cursor-row", 3,
1768 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1769 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1770 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1771 ctk_binding_entry_add_signal (binding_set, CDK_KEY_minus0x02d, CDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1772 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1773 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1774 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1775 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Subtract0xffad, 0, "expand-collapse-cursor-row", 3,
1776 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1777 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1778 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1779 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Subtract0xffad, CDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
1780 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)),
1781 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1782 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1783 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Left0xff51, CDK_SHIFT_MASK,
1784 "expand-collapse-cursor-row", 3,
1785 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1786 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1787 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1788 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Left0xff96, CDK_SHIFT_MASK,
1789 "expand-collapse-cursor-row", 3,
1790 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1791 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1792 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1793 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Left0xff51,
1794 CDK_CONTROL_MASK | CDK_SHIFT_MASK,
1795 "expand-collapse-cursor-row", 3,
1796 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1797 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1798 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1799 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Left0xff96,
1800 CDK_CONTROL_MASK | CDK_SHIFT_MASK,
1801 "expand-collapse-cursor-row", 3,
1802 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1803 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0),
1804 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1805
1806 ctk_binding_entry_add_signal (binding_set, CDK_KEY_BackSpace0xff08, 0, "select-cursor-parent", 0);
1807 ctk_binding_entry_add_signal (binding_set, CDK_KEY_BackSpace0xff08, CDK_CONTROL_MASK, "select-cursor-parent", 0);
1808
1809 ctk_binding_entry_add_signal (binding_set, CDK_KEY_f0x066, CDK_CONTROL_MASK, "start-interactive-search", 0);
1810
1811 ctk_binding_entry_add_signal (binding_set, CDK_KEY_F0x046, CDK_CONTROL_MASK, "start-interactive-search", 0);
1812
1813 ctk_widget_class_set_accessible_type (widget_class, CTK_TYPE_TREE_VIEW_ACCESSIBLE(ctk_tree_view_accessible_get_type ()));
1814 ctk_widget_class_set_css_name (widget_class, "treeview");
1815}
1816
1817static void
1818ctk_tree_view_init (CtkTreeView *tree_view)
1819{
1820 CtkTreeViewPrivate *priv;
1821 CtkCssNode *widget_node;
1822
1823 priv = tree_view->priv = ctk_tree_view_get_instance_private (tree_view);
1824
1825 ctk_widget_set_can_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, TRUE(!(0)));
1826
1827 priv->show_expanders = TRUE(!(0));
1828 priv->draw_keyfocus = TRUE(!(0));
1829 priv->headers_visible = TRUE(!(0));
1830 priv->activate_on_single_click = FALSE(0);
1831
1832 priv->pixel_cache = _ctk_pixel_cache_new ();
1833
1834 /* We need some padding */
1835 priv->dy = 0;
1836 priv->cursor_offset = 0;
1837 priv->n_columns = 0;
1838 priv->header_height = 1;
1839 priv->x_drag = 0;
1840 priv->drag_pos = -1;
1841 priv->header_has_focus = FALSE(0);
1842 priv->press_start_x = -1;
1843 priv->press_start_y = -1;
1844 priv->reorderable = FALSE(0);
1845 priv->presize_handler_tick_cb = 0;
1846 priv->scroll_sync_timer = 0;
1847 priv->fixed_height = -1;
1848 priv->fixed_height_mode = FALSE(0);
1849 priv->fixed_height_check = 0;
1850 priv->selection = _ctk_tree_selection_new_with_tree_view (tree_view);
1851 priv->enable_search = TRUE(!(0));
1852 priv->search_column = -1;
1853 priv->search_position_func = ctk_tree_view_search_position_func;
1854 priv->search_equal_func = ctk_tree_view_search_equal_func;
1855 priv->search_custom_entry_set = FALSE(0);
1856 priv->typeselect_flush_timeout = 0;
1857 priv->init_hadjust_value = TRUE(!(0));
1858 priv->width = 0;
1859
1860 priv->hover_selection = FALSE(0);
1861 priv->hover_expand = FALSE(0);
1862
1863 priv->level_indentation = 0;
1864
1865 priv->rubber_banding_enable = FALSE(0);
1866
1867 priv->grid_lines = CTK_TREE_VIEW_GRID_LINES_NONE;
1868 priv->tree_lines_enabled = FALSE(0);
1869
1870 priv->tooltip_column = -1;
1871
1872 priv->post_validation_flag = FALSE(0);
1873
1874 priv->event_last_x = -10000;
1875 priv->event_last_y = -10000;
1876
1877 ctk_tree_view_do_set_vadjustment (tree_view, NULL((void*)0));
1878 ctk_tree_view_do_set_hadjustment (tree_view, NULL((void*)0));
1879
1880 ctk_style_context_add_class (ctk_widget_get_style_context (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
),
1881 CTK_STYLE_CLASS_VIEW"view");
1882
1883 widget_node = ctk_widget_get_css_node (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1884 priv->header_node = ctk_css_node_new ();
1885 ctk_css_node_set_name (priv->header_node, I_("header")g_intern_static_string ("header"));
1886 ctk_css_node_set_parent (priv->header_node, widget_node);
1887 ctk_css_node_set_state (priv->header_node, ctk_css_node_get_state (widget_node));
1888 g_object_unref (priv->header_node);
1889
1890 priv->multipress_gesture = ctk_gesture_multi_press_new (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1891 ctk_gesture_single_set_button (CTK_GESTURE_SINGLE (priv->multipress_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((priv->multipress_gesture)), ((ctk_gesture_single_get_type
()))))))
, 0);
1892 g_signal_connect (priv->multipress_gesture, "pressed",g_signal_connect_data ((priv->multipress_gesture), ("pressed"
), (((GCallback) (ctk_tree_view_multipress_gesture_pressed)))
, (tree_view), ((void*)0), (GConnectFlags) 0)
1893 G_CALLBACK (ctk_tree_view_multipress_gesture_pressed), tree_view)g_signal_connect_data ((priv->multipress_gesture), ("pressed"
), (((GCallback) (ctk_tree_view_multipress_gesture_pressed)))
, (tree_view), ((void*)0), (GConnectFlags) 0)
;
1894 g_signal_connect (priv->multipress_gesture, "released",g_signal_connect_data ((priv->multipress_gesture), ("released"
), (((GCallback) (ctk_tree_view_multipress_gesture_released))
), (tree_view), ((void*)0), (GConnectFlags) 0)
1895 G_CALLBACK (ctk_tree_view_multipress_gesture_released), tree_view)g_signal_connect_data ((priv->multipress_gesture), ("released"
), (((GCallback) (ctk_tree_view_multipress_gesture_released))
), (tree_view), ((void*)0), (GConnectFlags) 0)
;
1896
1897 priv->column_multipress_gesture = ctk_gesture_multi_press_new (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1898 g_signal_connect (priv->column_multipress_gesture, "pressed",g_signal_connect_data ((priv->column_multipress_gesture), (
"pressed"), (((GCallback) (ctk_tree_view_column_multipress_gesture_pressed
))), (tree_view), ((void*)0), (GConnectFlags) 0)
1899 G_CALLBACK (ctk_tree_view_column_multipress_gesture_pressed), tree_view)g_signal_connect_data ((priv->column_multipress_gesture), (
"pressed"), (((GCallback) (ctk_tree_view_column_multipress_gesture_pressed
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
1900 ctk_event_controller_set_propagation_phase (CTK_EVENT_CONTROLLER (priv->column_multipress_gesture)((((CtkEventController*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->column_multipress_gesture)), ((ctk_event_controller_get_type
()))))))
,
1901 CTK_PHASE_CAPTURE);
1902
1903 priv->drag_gesture = ctk_gesture_drag_new (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1904 g_signal_connect (priv->drag_gesture, "drag-begin",g_signal_connect_data ((priv->drag_gesture), ("drag-begin"
), (((GCallback) (ctk_tree_view_drag_gesture_begin))), (tree_view
), ((void*)0), (GConnectFlags) 0)
1905 G_CALLBACK (ctk_tree_view_drag_gesture_begin), tree_view)g_signal_connect_data ((priv->drag_gesture), ("drag-begin"
), (((GCallback) (ctk_tree_view_drag_gesture_begin))), (tree_view
), ((void*)0), (GConnectFlags) 0)
;
1906 g_signal_connect (priv->drag_gesture, "drag-update",g_signal_connect_data ((priv->drag_gesture), ("drag-update"
), (((GCallback) (ctk_tree_view_drag_gesture_update))), (tree_view
), ((void*)0), (GConnectFlags) 0)
1907 G_CALLBACK (ctk_tree_view_drag_gesture_update), tree_view)g_signal_connect_data ((priv->drag_gesture), ("drag-update"
), (((GCallback) (ctk_tree_view_drag_gesture_update))), (tree_view
), ((void*)0), (GConnectFlags) 0)
;
1908 g_signal_connect (priv->drag_gesture, "drag-end",g_signal_connect_data ((priv->drag_gesture), ("drag-end"),
(((GCallback) (ctk_tree_view_drag_gesture_end))), (tree_view
), ((void*)0), (GConnectFlags) 0)
1909 G_CALLBACK (ctk_tree_view_drag_gesture_end), tree_view)g_signal_connect_data ((priv->drag_gesture), ("drag-end"),
(((GCallback) (ctk_tree_view_drag_gesture_end))), (tree_view
), ((void*)0), (GConnectFlags) 0)
;
1910
1911 priv->column_drag_gesture = ctk_gesture_drag_new (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1912 g_signal_connect (priv->column_drag_gesture, "drag-begin",g_signal_connect_data ((priv->column_drag_gesture), ("drag-begin"
), (((GCallback) (ctk_tree_view_column_drag_gesture_begin))),
(tree_view), ((void*)0), (GConnectFlags) 0)
1913 G_CALLBACK (ctk_tree_view_column_drag_gesture_begin), tree_view)g_signal_connect_data ((priv->column_drag_gesture), ("drag-begin"
), (((GCallback) (ctk_tree_view_column_drag_gesture_begin))),
(tree_view), ((void*)0), (GConnectFlags) 0)
;
1914 g_signal_connect (priv->column_drag_gesture, "drag-update",g_signal_connect_data ((priv->column_drag_gesture), ("drag-update"
), (((GCallback) (ctk_tree_view_column_drag_gesture_update)))
, (tree_view), ((void*)0), (GConnectFlags) 0)
1915 G_CALLBACK (ctk_tree_view_column_drag_gesture_update), tree_view)g_signal_connect_data ((priv->column_drag_gesture), ("drag-update"
), (((GCallback) (ctk_tree_view_column_drag_gesture_update)))
, (tree_view), ((void*)0), (GConnectFlags) 0)
;
1916 g_signal_connect (priv->column_drag_gesture, "drag-end",g_signal_connect_data ((priv->column_drag_gesture), ("drag-end"
), (((GCallback) (ctk_tree_view_column_drag_gesture_end))), (
tree_view), ((void*)0), (GConnectFlags) 0)
1917 G_CALLBACK (ctk_tree_view_column_drag_gesture_end), tree_view)g_signal_connect_data ((priv->column_drag_gesture), ("drag-end"
), (((GCallback) (ctk_tree_view_column_drag_gesture_end))), (
tree_view), ((void*)0), (GConnectFlags) 0)
;
1918 ctk_event_controller_set_propagation_phase (CTK_EVENT_CONTROLLER (priv->column_drag_gesture)((((CtkEventController*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->column_drag_gesture)), ((ctk_event_controller_get_type
()))))))
,
1919 CTK_PHASE_CAPTURE);
1920}
1921
1922
1923
1924/* GObject Methods
1925 */
1926
1927static void
1928ctk_tree_view_set_property (GObject *object,
1929 guint prop_id,
1930 const GValue *value,
1931 GParamSpec *pspec)
1932{
1933 CtkTreeView *tree_view;
1934
1935 tree_view = CTK_TREE_VIEW (object)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_tree_view_get_type ()))))))
;
1936
1937 switch (prop_id)
1938 {
1939 case PROP_MODEL:
1940 ctk_tree_view_set_model (tree_view, g_value_get_object (value));
1941 break;
1942 case PROP_HADJUSTMENT:
1943 ctk_tree_view_do_set_hadjustment (tree_view, g_value_get_object (value));
1944 break;
1945 case PROP_VADJUSTMENT:
1946 ctk_tree_view_do_set_vadjustment (tree_view, g_value_get_object (value));
1947 break;
1948 case PROP_HSCROLL_POLICY:
1949 if (tree_view->priv->hscroll_policy != g_value_get_enum (value))
1950 {
1951 tree_view->priv->hscroll_policy = g_value_get_enum (value);
1952 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1953 g_object_notify_by_pspec (object, pspec);
1954 }
1955 break;
1956 case PROP_VSCROLL_POLICY:
1957 if (tree_view->priv->vscroll_policy != g_value_get_enum (value))
1958 {
1959 tree_view->priv->vscroll_policy = g_value_get_enum (value);
1960 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1961 g_object_notify_by_pspec (object, pspec);
1962 }
1963 break;
1964 case PROP_HEADERS_VISIBLE:
1965 ctk_tree_view_set_headers_visible (tree_view, g_value_get_boolean (value));
1966 break;
1967 case PROP_HEADERS_CLICKABLE:
1968 ctk_tree_view_set_headers_clickable (tree_view, g_value_get_boolean (value));
1969 break;
1970 case PROP_EXPANDER_COLUMN:
1971 ctk_tree_view_set_expander_column (tree_view, g_value_get_object (value));
1972 break;
1973 case PROP_REORDERABLE:
1974 ctk_tree_view_set_reorderable (tree_view, g_value_get_boolean (value));
1975 break;
1976 case PROP_RULES_HINT:
1977G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
1978 ctk_tree_view_set_rules_hint (tree_view, g_value_get_boolean (value));
1979G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
1980 break;
1981 case PROP_ENABLE_SEARCH:
1982 ctk_tree_view_set_enable_search (tree_view, g_value_get_boolean (value));
1983 break;
1984 case PROP_SEARCH_COLUMN:
1985 ctk_tree_view_set_search_column (tree_view, g_value_get_int (value));
1986 break;
1987 case PROP_FIXED_HEIGHT_MODE:
1988 ctk_tree_view_set_fixed_height_mode (tree_view, g_value_get_boolean (value));
1989 break;
1990 case PROP_HOVER_SELECTION:
1991 if (tree_view->priv->hover_selection != g_value_get_boolean (value))
1992 {
1993 tree_view->priv->hover_selection = g_value_get_boolean (value);
1994 g_object_notify_by_pspec (object, pspec);
1995 }
1996 break;
1997 case PROP_HOVER_EXPAND:
1998 if (tree_view->priv->hover_expand != g_value_get_boolean (value))
1999 {
2000 tree_view->priv->hover_expand = g_value_get_boolean (value);
2001 g_object_notify_by_pspec (object, pspec);
2002 }
2003 break;
2004 case PROP_SHOW_EXPANDERS:
2005 ctk_tree_view_set_show_expanders (tree_view, g_value_get_boolean (value));
2006 break;
2007 case PROP_LEVEL_INDENTATION:
2008 if (tree_view->priv->level_indentation != g_value_get_int (value))
2009 {
2010 tree_view->priv->level_indentation = g_value_get_int (value);
2011 g_object_notify_by_pspec (object, pspec);
2012 }
2013 break;
2014 case PROP_RUBBER_BANDING:
2015 if (tree_view->priv->rubber_banding_enable != g_value_get_boolean (value))
2016 {
2017 tree_view->priv->rubber_banding_enable = g_value_get_boolean (value);
2018 g_object_notify_by_pspec (object, pspec);
2019 }
2020 break;
2021 case PROP_ENABLE_GRID_LINES:
2022 ctk_tree_view_set_grid_lines (tree_view, g_value_get_enum (value));
2023 break;
2024 case PROP_ENABLE_TREE_LINES:
2025 ctk_tree_view_set_enable_tree_lines (tree_view, g_value_get_boolean (value));
2026 break;
2027 case PROP_TOOLTIP_COLUMN:
2028 ctk_tree_view_set_tooltip_column (tree_view, g_value_get_int (value));
2029 break;
2030 case PROP_ACTIVATE_ON_SINGLE_CLICK:
2031 ctk_tree_view_set_activate_on_single_click (tree_view, g_value_get_boolean (value));
2032 break;
2033 default:
2034 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctktreeview.c", 2034, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
2035 break;
2036 }
2037}
2038
2039static void
2040ctk_tree_view_get_property (GObject *object,
2041 guint prop_id,
2042 GValue *value,
2043 GParamSpec *pspec)
2044{
2045 CtkTreeView *tree_view;
2046
2047 tree_view = CTK_TREE_VIEW (object)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_tree_view_get_type ()))))))
;
2048
2049 switch (prop_id)
2050 {
2051 case PROP_MODEL:
2052 g_value_set_object (value, tree_view->priv->model);
2053 break;
2054 case PROP_HADJUSTMENT:
2055 g_value_set_object (value, tree_view->priv->hadjustment);
2056 break;
2057 case PROP_VADJUSTMENT:
2058 g_value_set_object (value, tree_view->priv->vadjustment);
2059 break;
2060 case PROP_HSCROLL_POLICY:
2061 g_value_set_enum (value, tree_view->priv->hscroll_policy);
2062 break;
2063 case PROP_VSCROLL_POLICY:
2064 g_value_set_enum (value, tree_view->priv->vscroll_policy);
2065 break;
2066 case PROP_HEADERS_VISIBLE:
2067 g_value_set_boolean (value, ctk_tree_view_get_headers_visible (tree_view));
2068 break;
2069 case PROP_HEADERS_CLICKABLE:
2070 g_value_set_boolean (value, ctk_tree_view_get_headers_clickable (tree_view));
2071 break;
2072 case PROP_EXPANDER_COLUMN:
2073 g_value_set_object (value, tree_view->priv->expander_column);
2074 break;
2075 case PROP_REORDERABLE:
2076 g_value_set_boolean (value, tree_view->priv->reorderable);
2077 break;
2078 case PROP_RULES_HINT:
2079 g_value_set_boolean (value, tree_view->priv->has_rules);
2080 break;
2081 case PROP_ENABLE_SEARCH:
2082 g_value_set_boolean (value, tree_view->priv->enable_search);
2083 break;
2084 case PROP_SEARCH_COLUMN:
2085 g_value_set_int (value, tree_view->priv->search_column);
2086 break;
2087 case PROP_FIXED_HEIGHT_MODE:
2088 g_value_set_boolean (value, tree_view->priv->fixed_height_mode);
2089 break;
2090 case PROP_HOVER_SELECTION:
2091 g_value_set_boolean (value, tree_view->priv->hover_selection);
2092 break;
2093 case PROP_HOVER_EXPAND:
2094 g_value_set_boolean (value, tree_view->priv->hover_expand);
2095 break;
2096 case PROP_SHOW_EXPANDERS:
2097 g_value_set_boolean (value, tree_view->priv->show_expanders);
2098 break;
2099 case PROP_LEVEL_INDENTATION:
2100 g_value_set_int (value, tree_view->priv->level_indentation);
2101 break;
2102 case PROP_RUBBER_BANDING:
2103 g_value_set_boolean (value, tree_view->priv->rubber_banding_enable);
2104 break;
2105 case PROP_ENABLE_GRID_LINES:
2106 g_value_set_enum (value, tree_view->priv->grid_lines);
2107 break;
2108 case PROP_ENABLE_TREE_LINES:
2109 g_value_set_boolean (value, tree_view->priv->tree_lines_enabled);
2110 break;
2111 case PROP_TOOLTIP_COLUMN:
2112 g_value_set_int (value, tree_view->priv->tooltip_column);
2113 break;
2114 case PROP_ACTIVATE_ON_SINGLE_CLICK:
2115 g_value_set_boolean (value, tree_view->priv->activate_on_single_click);
2116 break;
2117 default:
2118 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctktreeview.c", 2118, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
2119 break;
2120 }
2121}
2122
2123static void
2124ctk_tree_view_finalize (GObject *object)
2125{
2126 G_OBJECT_CLASS (ctk_tree_view_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), (((GType) ((20) << (
2))))))))
->finalize (object);
2127}
2128
2129
2130static CtkBuildableIface *parent_buildable_iface;
2131
2132static void
2133ctk_tree_view_buildable_init (CtkBuildableIface *iface)
2134{
2135 parent_buildable_iface = g_type_interface_peek_parent (iface);
2136 iface->add_child = ctk_tree_view_buildable_add_child;
2137 iface->get_internal_child = ctk_tree_view_buildable_get_internal_child;
2138}
2139
2140static void
2141ctk_tree_view_buildable_add_child (CtkBuildable *tree_view,
2142 CtkBuilder *builder G_GNUC_UNUSED__attribute__ ((__unused__)),
2143 GObject *child,
2144 const gchar *type G_GNUC_UNUSED__attribute__ ((__unused__)))
2145{
2146 ctk_tree_view_append_column (CTK_TREE_VIEW (tree_view)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_tree_view_get_type ()))))))
, CTK_TREE_VIEW_COLUMN (child)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((child)), ((ctk_tree_view_column_get_type (
)))))))
);
2147}
2148
2149static GObject *
2150ctk_tree_view_buildable_get_internal_child (CtkBuildable *buildable,
2151 CtkBuilder *builder,
2152 const gchar *childname)
2153{
2154 if (strcmp (childname, "selection") == 0)
2155 return G_OBJECT (CTK_TREE_VIEW (buildable)->priv->selection)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((((CtkTreeView*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((buildable)), ((ctk_tree_view_get_type ())))
)))->priv->selection)), (((GType) ((20) << (2))))
))))
;
2156
2157 return parent_buildable_iface->get_internal_child (buildable,
2158 builder,
2159 childname);
2160}
2161
2162/* CtkWidget Methods
2163 */
2164
2165static void
2166ctk_tree_view_free_rbtree (CtkTreeView *tree_view)
2167{
2168 _ctk_rbtree_free (tree_view->priv->tree);
2169
2170 tree_view->priv->tree = NULL((void*)0);
2171 tree_view->priv->button_pressed_node = NULL((void*)0);
2172 tree_view->priv->button_pressed_tree = NULL((void*)0);
2173 tree_view->priv->prelight_tree = NULL((void*)0);
2174 tree_view->priv->prelight_node = NULL((void*)0);
2175}
2176
2177static void
2178ctk_tree_view_destroy_search_window (CtkTreeView *tree_view)
2179{
2180 ctk_widget_destroy (tree_view->priv->search_window);
2181
2182 tree_view->priv->search_window = NULL((void*)0);
2183 tree_view->priv->search_entry = NULL((void*)0);
2184 tree_view->priv->search_entry_changed_id = 0;
2185}
2186
2187static void
2188ctk_tree_view_destroy (CtkWidget *widget)
2189{
2190 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2191 GList *list;
2192
2193 ctk_tree_view_stop_editing (tree_view, TRUE(!(0)));
2194 ctk_tree_view_stop_rubber_band (tree_view);
2195
2196 if (tree_view->priv->columns != NULL((void*)0))
2197 {
2198 list = tree_view->priv->columns;
2199 while (list)
2200 {
2201 CtkTreeViewColumn *column;
2202 column = CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
;
2203 list = list->next;
2204 ctk_tree_view_remove_column (tree_view, column);
2205 }
2206 tree_view->priv->columns = NULL((void*)0);
2207 }
2208
2209 if (tree_view->priv->tree != NULL((void*)0))
2210 {
2211 ctk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
2212
2213 ctk_tree_view_free_rbtree (tree_view);
2214 }
2215
2216 if (tree_view->priv->selection != NULL((void*)0))
2217 {
2218 _ctk_tree_selection_set_tree_view (tree_view->priv->selection, NULL((void*)0));
2219 g_object_unref (tree_view->priv->selection);
2220 tree_view->priv->selection = NULL((void*)0);
2221 }
2222
2223 if (tree_view->priv->scroll_to_path != NULL((void*)0))
2224 {
2225 ctk_tree_row_reference_free (tree_view->priv->scroll_to_path);
2226 tree_view->priv->scroll_to_path = NULL((void*)0);
2227 }
2228
2229 if (tree_view->priv->drag_dest_row != NULL((void*)0))
2230 {
2231 ctk_tree_row_reference_free (tree_view->priv->drag_dest_row);
2232 tree_view->priv->drag_dest_row = NULL((void*)0);
2233 }
2234
2235 if (tree_view->priv->top_row != NULL((void*)0))
2236 {
2237 ctk_tree_row_reference_free (tree_view->priv->top_row);
2238 tree_view->priv->top_row = NULL((void*)0);
2239 }
2240
2241 if (tree_view->priv->column_drop_func_data &&
2242 tree_view->priv->column_drop_func_data_destroy)
2243 {
2244 tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
2245 tree_view->priv->column_drop_func_data = NULL((void*)0);
2246 }
2247
2248 if (tree_view->priv->destroy_count_destroy &&
2249 tree_view->priv->destroy_count_data)
2250 {
2251 tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
2252 tree_view->priv->destroy_count_data = NULL((void*)0);
2253 }
2254
2255 ctk_tree_row_reference_free (tree_view->priv->anchor);
2256 tree_view->priv->anchor = NULL((void*)0);
2257
2258 /* destroy interactive search dialog */
2259 if (tree_view->priv->search_window)
2260 {
2261 ctk_tree_view_destroy_search_window (tree_view);
2262 if (tree_view->priv->typeselect_flush_timeout)
2263 {
2264 g_source_remove (tree_view->priv->typeselect_flush_timeout);
2265 tree_view->priv->typeselect_flush_timeout = 0;
2266 }
2267 }
2268
2269 if (tree_view->priv->search_custom_entry_set)
2270 {
2271 g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_init
))), (tree_view))
2272 G_CALLBACK (ctk_tree_view_search_init),g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_init
))), (tree_view))
2273 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_init
))), (tree_view))
;
2274 g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view))
2275 G_CALLBACK (ctk_tree_view_search_key_press_event),g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view))
2276 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view))
;
2277
2278 g_object_unref (tree_view->priv->search_entry);
2279
2280 tree_view->priv->search_entry = NULL((void*)0);
2281 tree_view->priv->search_custom_entry_set = FALSE(0);
2282 }
2283
2284 if (tree_view->priv->search_destroy && tree_view->priv->search_user_data)
2285 {
2286 tree_view->priv->search_destroy (tree_view->priv->search_user_data);
2287 tree_view->priv->search_user_data = NULL((void*)0);
2288 }
2289
2290 if (tree_view->priv->search_position_destroy && tree_view->priv->search_position_user_data)
2291 {
2292 tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
2293 tree_view->priv->search_position_user_data = NULL((void*)0);
2294 }
2295
2296 if (tree_view->priv->row_separator_destroy && tree_view->priv->row_separator_data)
2297 {
2298 tree_view->priv->row_separator_destroy (tree_view->priv->row_separator_data);
2299 tree_view->priv->row_separator_data = NULL((void*)0);
2300 }
2301
2302 ctk_tree_view_set_model (tree_view, NULL((void*)0));
2303
2304 if (tree_view->priv->hadjustment)
2305 {
2306 g_object_unref (tree_view->priv->hadjustment);
2307 tree_view->priv->hadjustment = NULL((void*)0);
2308 }
2309 if (tree_view->priv->vadjustment)
2310 {
2311 g_object_unref (tree_view->priv->vadjustment);
2312 tree_view->priv->vadjustment = NULL((void*)0);
2313 }
2314
2315 if (tree_view->priv->pixel_cache)
2316 _ctk_pixel_cache_free (tree_view->priv->pixel_cache);
2317 tree_view->priv->pixel_cache = NULL((void*)0);
2318
2319 g_clear_object (&tree_view->priv->multipress_gesture)do { _Static_assert (sizeof *((&tree_view->priv->multipress_gesture
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&tree_view->priv->multipress_gesture))) _pp = (
(&tree_view->priv->multipress_gesture)); __typeof__
(*((&tree_view->priv->multipress_gesture))) _ptr =
*_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); }
while (0)
;
2320 g_clear_object (&tree_view->priv->drag_gesture)do { _Static_assert (sizeof *((&tree_view->priv->drag_gesture
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&tree_view->priv->drag_gesture))) _pp = ((&
tree_view->priv->drag_gesture)); __typeof__ (*((&tree_view
->priv->drag_gesture))) _ptr = *_pp; *_pp = ((void*)0);
if (_ptr) (g_object_unref) (_ptr); } while (0)
;
2321 g_clear_object (&tree_view->priv->column_multipress_gesture)do { _Static_assert (sizeof *((&tree_view->priv->column_multipress_gesture
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&tree_view->priv->column_multipress_gesture))) _pp
= ((&tree_view->priv->column_multipress_gesture));
__typeof__ (*((&tree_view->priv->column_multipress_gesture
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
2322 g_clear_object (&tree_view->priv->column_drag_gesture)do { _Static_assert (sizeof *((&tree_view->priv->column_drag_gesture
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&tree_view->priv->column_drag_gesture))) _pp = (
(&tree_view->priv->column_drag_gesture)); __typeof__
(*((&tree_view->priv->column_drag_gesture))) _ptr =
*_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); }
while (0)
;
2323
2324 CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->destroy (widget);
2325}
2326
2327/* CtkWidget::map helper */
2328static void
2329ctk_tree_view_map_buttons (CtkTreeView *tree_view)
2330{
2331 GList *list;
2332
2333 g_return_if_fail (ctk_widget_get_mapped (CTK_WIDGET (tree_view)))do { if ((ctk_widget_get_mapped (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((tree_view)), ((ctk_widget_get_type ())))
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "ctk_widget_get_mapped (CTK_WIDGET (tree_view))"
); return; } } while (0)
;
2334
2335 if (tree_view->priv->headers_visible)
2336 {
2337 CtkTreeViewColumn *column;
2338 CtkWidget *button;
2339 CdkWindow *window;
2340
2341 for (list = tree_view->priv->columns; list; list = list->next)
2342 {
2343 column = list->data;
2344 button = ctk_tree_view_column_get_button (column);
2345
2346 if (ctk_tree_view_column_get_visible (column) && button)
2347 ctk_widget_show_now (button);
2348
2349 if (ctk_widget_get_visible (button) &&
2350 !ctk_widget_get_mapped (button))
2351 ctk_widget_map (button);
2352 }
2353 for (list = tree_view->priv->columns; list; list = list->next)
2354 {
2355 column = list->data;
2356 if (ctk_tree_view_column_get_visible (column) == FALSE(0))
2357 continue;
2358
2359 window = _ctk_tree_view_column_get_window (column);
2360 if (ctk_tree_view_column_get_resizable (column))
2361 {
2362 cdk_window_raise (window);
2363 cdk_window_show (window);
2364 }
2365 else
2366 cdk_window_hide (window);
2367 }
2368 cdk_window_show (tree_view->priv->header_window);
2369 }
2370}
2371
2372static void
2373ctk_tree_view_map (CtkWidget *widget)
2374{
2375 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2376 GList *tmp_list;
2377
2378 _ctk_pixel_cache_map (tree_view->priv->pixel_cache);
2379
2380 ctk_widget_set_mapped (widget, TRUE(!(0)));
2381
2382 tmp_list = tree_view->priv->children;
2383 while (tmp_list)
2384 {
2385 CtkTreeViewChild *child = tmp_list->data;
2386 tmp_list = tmp_list->next;
2387
2388 if (ctk_widget_get_visible (child->widget))
2389 {
2390 if (!ctk_widget_get_mapped (child->widget))
2391 ctk_widget_map (child->widget);
2392 }
2393 }
2394 cdk_window_show (tree_view->priv->bin_window);
2395
2396 ctk_tree_view_map_buttons (tree_view);
2397
2398 cdk_window_show (ctk_widget_get_window (widget));
2399}
2400
2401static void
2402ctk_tree_view_unmap (CtkWidget *widget)
2403{
2404 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2405
2406 CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->unmap (widget);
2407
2408 _ctk_pixel_cache_unmap (tree_view->priv->pixel_cache);
2409}
2410
2411static void
2412ctk_tree_view_bin_window_invalidate_handler (CdkWindow *window,
2413 cairo_region_t *region)
2414{
2415 gpointer widget;
2416 CtkTreeView *tree_view;
2417 int y;
2418
2419 cdk_window_get_user_data (window, &widget);
2420 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2421
2422 y = ctk_adjustment_get_value (tree_view->priv->vadjustment);
2423 cairo_region_translate (region,
2424 0, y);
2425 _ctk_pixel_cache_invalidate (tree_view->priv->pixel_cache, region);
2426 cairo_region_translate (region,
2427 0, -y);
2428}
2429
2430static void
2431ctk_tree_view_queue_draw_region (CtkWidget *widget,
2432 const cairo_region_t *region)
2433{
2434 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2435
2436 /* There is no way we can know if a region targets the
2437 not-currently-visible but in pixel cache region, so we
2438 always just invalidate the whole thing whenever the
2439 tree view gets a queue draw. This doesn't normally happen
2440 in normal scrolling cases anyway. */
2441 _ctk_pixel_cache_invalidate (tree_view->priv->pixel_cache, NULL((void*)0));
2442
2443 CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->queue_draw_region (widget,
2444 region);
2445}
2446
2447static void
2448ctk_tree_view_realize (CtkWidget *widget)
2449{
2450 CtkAllocation allocation;
2451 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2452 CdkWindow *window;
2453 CdkWindowAttr attributes;
2454 GList *tmp_list;
2455 gint attributes_mask;
2456
2457 ctk_widget_set_realized (widget, TRUE(!(0)));
2458
2459 ctk_widget_get_allocation (widget, &allocation);
2460
2461 /* Make the main, clipping window */
2462 attributes.window_type = CDK_WINDOW_CHILD;
2463 attributes.x = allocation.x;
2464 attributes.y = allocation.y;
2465 attributes.width = allocation.width;
2466 attributes.height = allocation.height;
2467 attributes.wclass = CDK_INPUT_OUTPUT;
2468 attributes.visual = ctk_widget_get_visual (widget);
2469 attributes.event_mask = CDK_VISIBILITY_NOTIFY_MASK;
2470
2471 attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL;
2472
2473 window = cdk_window_new (ctk_widget_get_parent_window (widget),
2474 &attributes, attributes_mask);
2475 ctk_widget_set_window (widget, window);
2476 ctk_widget_register_window (widget, window);
2477
2478 ctk_widget_get_allocation (widget, &allocation);
2479
2480 /* Make the window for the tree */
2481 attributes.x = 0;
2482 attributes.y = ctk_tree_view_get_effective_header_height (tree_view);
2483 attributes.width = MAX (tree_view->priv->width, allocation.width)(((tree_view->priv->width) > (allocation.width)) ? (
tree_view->priv->width) : (allocation.width))
;
2484 attributes.height = allocation.height;
2485 attributes.event_mask = (CDK_SCROLL_MASK |
2486 CDK_SMOOTH_SCROLL_MASK |
2487 CDK_POINTER_MOTION_MASK |
2488 CDK_ENTER_NOTIFY_MASK |
2489 CDK_LEAVE_NOTIFY_MASK |
2490 CDK_BUTTON_PRESS_MASK |
2491 CDK_BUTTON_RELEASE_MASK |
2492 ctk_widget_get_events (widget));
2493
2494 tree_view->priv->bin_window = cdk_window_new (window,
2495 &attributes, attributes_mask);
2496 ctk_widget_register_window (widget, tree_view->priv->bin_window);
2497 cdk_window_set_invalidate_handler (tree_view->priv->bin_window,
2498 ctk_tree_view_bin_window_invalidate_handler);
2499
2500 ctk_widget_get_allocation (widget, &allocation);
2501
2502 /* Make the column header window */
2503 attributes.x = 0;
2504 attributes.y = 0;
2505 attributes.width = MAX (tree_view->priv->width, allocation.width)(((tree_view->priv->width) > (allocation.width)) ? (
tree_view->priv->width) : (allocation.width))
;
2506 attributes.height = tree_view->priv->header_height;
2507 attributes.event_mask = (CDK_SCROLL_MASK |
2508 CDK_ENTER_NOTIFY_MASK |
2509 CDK_LEAVE_NOTIFY_MASK |
2510 CDK_BUTTON_PRESS_MASK |
2511 CDK_BUTTON_RELEASE_MASK |
2512 CDK_KEY_PRESS_MASK |
2513 CDK_KEY_RELEASE_MASK |
2514 ctk_widget_get_events (widget));
2515
2516 tree_view->priv->header_window = cdk_window_new (window,
2517 &attributes, attributes_mask);
2518 ctk_widget_register_window (widget, tree_view->priv->header_window);
2519
2520 tmp_list = tree_view->priv->children;
2521 while (tmp_list)
2522 {
2523 CtkTreeViewChild *child = tmp_list->data;
2524 tmp_list = tmp_list->next;
2525
2526 ctk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
2527 }
2528
2529 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
2530 _ctk_tree_view_column_realize_button (CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
);
2531
2532 /* Need to call those here, since they create GCs */
2533 ctk_tree_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
2534 ctk_tree_view_set_enable_tree_lines (tree_view, tree_view->priv->tree_lines_enabled);
2535
2536 install_presize_handler (tree_view);
2537
2538 ctk_gesture_set_window (tree_view->priv->multipress_gesture,
2539 tree_view->priv->bin_window);
2540 ctk_gesture_set_window (tree_view->priv->drag_gesture,
2541 tree_view->priv->bin_window);
2542}
2543
2544static void
2545ctk_tree_view_unrealize (CtkWidget *widget)
2546{
2547 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2548 CtkTreeViewPrivate *priv = tree_view->priv;
2549 GList *list;
2550
2551 if (priv->scroll_timeout != 0)
2552 {
2553 g_source_remove (priv->scroll_timeout);
2554 priv->scroll_timeout = 0;
2555 }
2556
2557 if (priv->auto_expand_timeout != 0)
2558 {
2559 g_source_remove (priv->auto_expand_timeout);
2560 priv->auto_expand_timeout = 0;
2561 }
2562
2563 if (priv->open_dest_timeout != 0)
2564 {
2565 g_source_remove (priv->open_dest_timeout);
2566 priv->open_dest_timeout = 0;
2567 }
2568
2569 if (priv->presize_handler_tick_cb != 0)
2570 {
2571 ctk_widget_remove_tick_callback (widget, priv->presize_handler_tick_cb);
2572 priv->presize_handler_tick_cb = 0;
2573 }
2574
2575 if (priv->validate_rows_timer != 0)
2576 {
2577 g_source_remove (priv->validate_rows_timer);
2578 priv->validate_rows_timer = 0;
2579 }
2580
2581 if (priv->scroll_sync_timer != 0)
2582 {
2583 g_source_remove (priv->scroll_sync_timer);
2584 priv->scroll_sync_timer = 0;
2585 }
2586
2587 if (priv->typeselect_flush_timeout)
2588 {
2589 g_source_remove (priv->typeselect_flush_timeout);
2590 priv->typeselect_flush_timeout = 0;
2591 }
2592
2593 for (list = priv->columns; list; list = list->next)
2594 _ctk_tree_view_column_unrealize_button (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
);
2595
2596 ctk_widget_unregister_window (widget, priv->bin_window);
2597 cdk_window_destroy (priv->bin_window);
2598 priv->bin_window = NULL((void*)0);
2599
2600 ctk_widget_unregister_window (widget, priv->header_window);
2601 cdk_window_destroy (priv->header_window);
2602 priv->header_window = NULL((void*)0);
2603
2604 if (priv->drag_window)
2605 {
2606 ctk_widget_unregister_window (widget, priv->drag_window);
2607 cdk_window_destroy (priv->drag_window);
2608 priv->drag_window = NULL((void*)0);
2609 }
2610
2611 if (priv->drag_highlight_window)
2612 {
2613 ctk_widget_unregister_window (widget, priv->drag_highlight_window);
2614 cdk_window_destroy (priv->drag_highlight_window);
2615 priv->drag_highlight_window = NULL((void*)0);
2616 }
2617
2618 ctk_gesture_set_window (tree_view->priv->multipress_gesture, NULL((void*)0));
2619 ctk_gesture_set_window (tree_view->priv->drag_gesture, NULL((void*)0));
2620
2621 CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->unrealize (widget);
2622}
2623
2624/* CtkWidget::get_preferred_height helper */
2625static void
2626ctk_tree_view_update_height (CtkTreeView *tree_view)
2627{
2628 GList *list;
2629
2630 tree_view->priv->header_height = 0;
2631
2632 for (list = tree_view->priv->columns; list; list = list->next)
2633 {
2634 CtkRequisition requisition;
2635 CtkTreeViewColumn *column = list->data;
2636 CtkWidget *button = ctk_tree_view_column_get_button (column);
2637
2638 if (button == NULL((void*)0))
2639 continue;
2640
2641 ctk_widget_get_preferred_size (button, &requisition, NULL((void*)0));
2642 tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height)(((tree_view->priv->header_height) > (requisition.height
)) ? (tree_view->priv->header_height) : (requisition.height
))
;
2643 }
2644}
2645
2646static gint
2647ctk_tree_view_get_height (CtkTreeView *tree_view)
2648{
2649 if (tree_view->priv->tree == NULL((void*)0))
2650 return 0;
2651 else
2652 return tree_view->priv->tree->root->offset;
2653}
2654
2655static void
2656ctk_tree_view_get_preferred_width (CtkWidget *widget,
2657 gint *minimum,
2658 gint *natural)
2659{
2660 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2661 GList *list;
2662 CtkTreeViewColumn *column;
2663 gint width = 0;
2664
2665 /* we validate some rows initially just to make sure we have some size.
2666 * In practice, with a lot of static lists, this should get a good width.
2667 */
2668 do_validate_rows (tree_view, FALSE(0));
2669
2670 /* keep this in sync with size_allocate below */
2671 for (list = tree_view->priv->columns; list; list = list->next)
2672 {
2673 column = list->data;
2674 if (!ctk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column)
2675 continue;
2676
2677 width += _ctk_tree_view_column_request_width (column);
2678 }
2679
2680 *minimum = *natural = width;
2681}
2682
2683static void
2684ctk_tree_view_get_preferred_height (CtkWidget *widget,
2685 gint *minimum,
2686 gint *natural)
2687{
2688 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2689 gint height;
2690
2691 ctk_tree_view_update_height (tree_view);
2692
2693 height = ctk_tree_view_get_height (tree_view) + ctk_tree_view_get_effective_header_height (tree_view);
2694
2695 *minimum = *natural = height;
2696}
2697
2698static int
2699ctk_tree_view_calculate_width_before_expander (CtkTreeView *tree_view)
2700{
2701 int width = 0;
2702 GList *list;
2703 gboolean rtl;
2704
2705 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
2706 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
2707 list->data != tree_view->priv->expander_column;
2708 list = (rtl ? list->prev : list->next))
2709 {
2710 CtkTreeViewColumn *column = list->data;
2711
2712 width += ctk_tree_view_column_get_width (column);
2713 }
2714
2715 return width;
2716}
2717
2718/* CtkWidget::size_allocate helper */
2719static void
2720ctk_tree_view_size_allocate_columns (CtkWidget *widget,
2721 gboolean *width_changed)
2722{
2723 CtkTreeView *tree_view;
2724 GList *list, *first_column, *last_column;
2725 CtkTreeViewColumn *column;
2726 CtkAllocation widget_allocation;
2727 gint width = 0;
2728 gint extra, extra_per_column, extra_for_last;
2729 gint full_requested_width = 0;
2730 gint number_of_expand_columns = 0;
2731 gboolean rtl;
2732 gboolean update_expand;
2733
2734 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2735
2736 for (last_column = g_list_last (tree_view->priv->columns);
2737 last_column &&
2738 !(ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (last_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((last_column->data)), ((ctk_tree_view_column_get_type
()))))))
));
2739 last_column = last_column->prev)
2740 ;
2741 if (last_column == NULL((void*)0))
2742 return;
2743
2744 for (first_column = g_list_first (tree_view->priv->columns);
2745 first_column &&
2746 !(ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (first_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((first_column->data)), ((ctk_tree_view_column_get_type
()))))))
));
2747 first_column = first_column->next)
2748 ;
2749
2750 if (first_column == NULL((void*)0))
2751 return;
2752
2753 rtl = (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
2754
2755 /* find out how many extra space and expandable columns we have */
2756 for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
2757 {
2758 column = (CtkTreeViewColumn *)list->data;
2759
2760 if (!ctk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column)
2761 continue;
2762
2763 full_requested_width += _ctk_tree_view_column_request_width (column);
2764
2765 if (ctk_tree_view_column_get_expand (column))
2766 number_of_expand_columns++;
2767 }
2768
2769 /* Only update the expand value if the width of the widget has changed,
2770 * or the number of expand columns has changed, or if there are no expand
2771 * columns, or if we didn't have an size-allocation yet after the
2772 * last validated node.
2773 */
2774 update_expand = (width_changed && *width_changed == TRUE(!(0)))
2775 || number_of_expand_columns != tree_view->priv->last_number_of_expand_columns
2776 || number_of_expand_columns == 0
2777 || tree_view->priv->post_validation_flag == TRUE(!(0));
2778
2779 tree_view->priv->post_validation_flag = FALSE(0);
2780
2781 ctk_widget_get_allocation (widget, &widget_allocation);
2782 if (!update_expand)
2783 {
2784 extra = tree_view->priv->last_extra_space;
2785 extra_for_last = MAX (widget_allocation.width - full_requested_width - extra, 0)(((widget_allocation.width - full_requested_width - extra) >
(0)) ? (widget_allocation.width - full_requested_width - extra
) : (0))
;
2786 }
2787 else
2788 {
2789 extra = MAX (widget_allocation.width - full_requested_width, 0)(((widget_allocation.width - full_requested_width) > (0)) ?
(widget_allocation.width - full_requested_width) : (0))
;
2790 extra_for_last = 0;
2791
2792 tree_view->priv->last_extra_space = extra;
2793 }
2794
2795 if (number_of_expand_columns > 0)
2796 extra_per_column = extra/number_of_expand_columns;
2797 else
2798 extra_per_column = 0;
2799
2800 if (update_expand)
2801 {
2802 tree_view->priv->last_extra_space_per_column = extra_per_column;
2803 tree_view->priv->last_number_of_expand_columns = number_of_expand_columns;
2804 }
2805
2806 for (list = (rtl ? last_column : first_column);
2807 list != (rtl ? first_column->prev : last_column->next);
2808 list = (rtl ? list->prev : list->next))
2809 {
2810 gint column_width;
2811
2812 column = list->data;
2813
2814 if (!ctk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column)
2815 continue;
2816
2817 column_width = _ctk_tree_view_column_request_width (column);
2818
2819 if (ctk_tree_view_column_get_expand (column))
2820 {
2821 if (number_of_expand_columns == 1)
2822 {
2823 /* We add the remander to the last column as
2824 * */
2825 column_width += extra;
2826 }
2827 else
2828 {
2829 column_width += extra_per_column;
2830 extra -= extra_per_column;
2831 number_of_expand_columns --;
2832 }
2833 }
2834 else if (number_of_expand_columns == 0 &&
2835 list == last_column)
2836 {
2837 column_width += extra;
2838 }
2839
2840 /* In addition to expand, the last column can get even more
2841 * extra space so all available space is filled up.
2842 */
2843 if (extra_for_last > 0 && list == last_column)
2844 column_width += extra_for_last;
2845
2846 _ctk_tree_view_column_allocate (column, width, column_width);
2847
2848 width += column_width;
2849 }
2850
2851 /* We change the width here. The user might have been resizing columns,
2852 * which changes the total width of the tree view. This is of
2853 * importance for getting the horizontal scroll bar right.
2854 */
2855 if (tree_view->priv->width != width)
2856 {
2857 tree_view->priv->width = width;
2858 if (width_changed)
2859 *width_changed = TRUE(!(0));
2860 }
2861}
2862
2863/* CtkWidget::size_allocate helper */
2864static void
2865ctk_tree_view_size_allocate_drag_column (CtkWidget *widget)
2866{
2867 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2868 CtkAllocation drag_allocation;
2869 CtkWidget *button;
2870
2871 if (tree_view->priv->drag_column == NULL((void*)0))
2872 return;
2873
2874 button = ctk_tree_view_column_get_button (tree_view->priv->drag_column);
2875
2876 drag_allocation.x = 0;
2877 drag_allocation.y = 0;
2878 drag_allocation.width = cdk_window_get_width (tree_view->priv->drag_window);
2879 drag_allocation.height = cdk_window_get_height (tree_view->priv->drag_window);
2880 ctk_widget_size_allocate (button, &drag_allocation);
2881}
2882
2883static void
2884ctk_tree_view_size_allocate (CtkWidget *widget,
2885 CtkAllocation *allocation)
2886{
2887 CtkAllocation widget_allocation;
2888 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
2889 GList *tmp_list;
2890 gboolean width_changed = FALSE(0);
2891 gint old_width;
2892 double page_size;
2893
2894 ctk_widget_get_allocation (widget, &widget_allocation);
2895 old_width = widget_allocation.width;
2896 if (allocation->width != widget_allocation.width)
2897 width_changed = TRUE(!(0));
2898
2899 ctk_widget_set_allocation (widget, allocation);
2900
2901 /* We size-allocate the columns first because the width of the
2902 * tree view (used in updating the adjustments below) might change.
2903 */
2904 ctk_tree_view_size_allocate_columns (widget, &width_changed);
2905 ctk_tree_view_size_allocate_drag_column (widget);
2906
2907 g_object_freeze_notify (G_OBJECT (tree_view->priv->hadjustment)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->hadjustment)), (((GType) ((20) <<
(2))))))))
);
2908 ctk_adjustment_set_page_size (tree_view->priv->hadjustment,
2909 allocation->width);
2910 ctk_adjustment_set_page_increment (tree_view->priv->hadjustment,
2911 allocation->width * 0.9);
2912 ctk_adjustment_set_step_increment (tree_view->priv->hadjustment,
2913 allocation->width * 0.1);
2914 ctk_adjustment_set_lower (tree_view->priv->hadjustment, 0);
2915 ctk_adjustment_set_upper (tree_view->priv->hadjustment,
2916 MAX (ctk_adjustment_get_page_size (tree_view->priv->hadjustment),(((ctk_adjustment_get_page_size (tree_view->priv->hadjustment
)) > (tree_view->priv->width)) ? (ctk_adjustment_get_page_size
(tree_view->priv->hadjustment)) : (tree_view->priv->
width))
2917 tree_view->priv->width)(((ctk_adjustment_get_page_size (tree_view->priv->hadjustment
)) > (tree_view->priv->width)) ? (ctk_adjustment_get_page_size
(tree_view->priv->hadjustment)) : (tree_view->priv->
width))
);
2918 g_object_thaw_notify (G_OBJECT (tree_view->priv->hadjustment)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->hadjustment)), (((GType) ((20) <<
(2))))))))
);
2919
2920 if (ctk_widget_get_direction(widget) == CTK_TEXT_DIR_RTL)
2921 {
2922 if (allocation->width < tree_view->priv->width)
2923 {
2924 if (tree_view->priv->init_hadjust_value)
2925 {
2926 ctk_adjustment_set_value (tree_view->priv->hadjustment,
2927 MAX (tree_view->priv->width -(((tree_view->priv->width - allocation->width) > (
0)) ? (tree_view->priv->width - allocation->width) :
(0))
2928 allocation->width, 0)(((tree_view->priv->width - allocation->width) > (
0)) ? (tree_view->priv->width - allocation->width) :
(0))
);
2929 tree_view->priv->init_hadjust_value = FALSE(0);
2930 }
2931 else if (allocation->width != old_width)
2932 {
2933 ctk_adjustment_set_value (tree_view->priv->hadjustment,
2934 CLAMP (ctk_adjustment_get_value (tree_view->priv->hadjustment) - allocation->width + old_width,(((ctk_adjustment_get_value (tree_view->priv->hadjustment
) - allocation->width + old_width) > (tree_view->priv
->width - allocation->width)) ? (tree_view->priv->
width - allocation->width) : (((ctk_adjustment_get_value (
tree_view->priv->hadjustment) - allocation->width + old_width
) < (0)) ? (0) : (ctk_adjustment_get_value (tree_view->
priv->hadjustment) - allocation->width + old_width)))
2935 0,(((ctk_adjustment_get_value (tree_view->priv->hadjustment
) - allocation->width + old_width) > (tree_view->priv
->width - allocation->width)) ? (tree_view->priv->
width - allocation->width) : (((ctk_adjustment_get_value (
tree_view->priv->hadjustment) - allocation->width + old_width
) < (0)) ? (0) : (ctk_adjustment_get_value (tree_view->
priv->hadjustment) - allocation->width + old_width)))
2936 tree_view->priv->width - allocation->width)(((ctk_adjustment_get_value (tree_view->priv->hadjustment
) - allocation->width + old_width) > (tree_view->priv
->width - allocation->width)) ? (tree_view->priv->
width - allocation->width) : (((ctk_adjustment_get_value (
tree_view->priv->hadjustment) - allocation->width + old_width
) < (0)) ? (0) : (ctk_adjustment_get_value (tree_view->
priv->hadjustment) - allocation->width + old_width)))
);
2937 }
2938 }
2939 else
2940 {
2941 ctk_adjustment_set_value (tree_view->priv->hadjustment, 0);
2942 tree_view->priv->init_hadjust_value = TRUE(!(0));
2943 }
2944 }
2945 else
2946 if (ctk_adjustment_get_value (tree_view->priv->hadjustment) + allocation->width > tree_view->priv->width)
2947 ctk_adjustment_set_value (tree_view->priv->hadjustment,
2948 MAX (tree_view->priv->width -(((tree_view->priv->width - allocation->width) > (
0)) ? (tree_view->priv->width - allocation->width) :
(0))
2949 allocation->width, 0)(((tree_view->priv->width - allocation->width) > (
0)) ? (tree_view->priv->width - allocation->width) :
(0))
);
2950
2951 page_size = allocation->height - ctk_tree_view_get_effective_header_height (tree_view);
2952 ctk_adjustment_configure (tree_view->priv->vadjustment,
2953 ctk_adjustment_get_value (tree_view->priv->vadjustment),
2954 0,
2955 MAX (page_size, ctk_tree_view_get_height (tree_view))(((page_size) > (ctk_tree_view_get_height (tree_view))) ? (
page_size) : (ctk_tree_view_get_height (tree_view)))
,
2956 page_size * 0.1,
2957 page_size * 0.9,
2958 page_size);
2959
2960 /* now the adjustments and window sizes are in sync, we can sync toprow/dy again */
2961 if (ctk_tree_row_reference_valid (tree_view->priv->top_row))
2962 ctk_tree_view_top_row_to_dy (tree_view);
2963 else
2964 ctk_tree_view_dy_to_top_row (tree_view);
2965
2966 if (ctk_widget_get_realized (widget))
2967 {
2968 cdk_window_move_resize (ctk_widget_get_window (widget),
2969 allocation->x, allocation->y,
2970 allocation->width, allocation->height);
2971 cdk_window_move_resize (tree_view->priv->header_window,
2972 - (gint) ctk_adjustment_get_value (tree_view->priv->hadjustment),
2973 0,
2974 MAX (tree_view->priv->width, allocation->width)(((tree_view->priv->width) > (allocation->width))
? (tree_view->priv->width) : (allocation->width))
,
2975 tree_view->priv->header_height);
2976 cdk_window_move_resize (tree_view->priv->bin_window,
2977 - (gint) ctk_adjustment_get_value (tree_view->priv->hadjustment),
2978 ctk_tree_view_get_effective_header_height (tree_view),
2979 MAX (tree_view->priv->width, allocation->width)(((tree_view->priv->width) > (allocation->width))
? (tree_view->priv->width) : (allocation->width))
,
2980 allocation->height - ctk_tree_view_get_effective_header_height (tree_view));
2981
2982 if (tree_view->priv->tree == NULL((void*)0))
2983 invalidate_empty_focus (tree_view);
2984
2985 if (width_changed && tree_view->priv->expander_column)
2986 {
2987 /* Might seem awkward, but is the best heuristic I could come up
2988 * with. Only if the width of the columns before the expander
2989 * changes, we will update the prelight status. It is this
2990 * width that makes the expander move vertically. Always updating
2991 * prelight status causes trouble with hover selections.
2992 */
2993 gint width_before_expander;
2994
2995 width_before_expander = ctk_tree_view_calculate_width_before_expander (tree_view);
2996
2997 if (tree_view->priv->prev_width_before_expander
2998 != width_before_expander)
2999 update_prelight (tree_view,
3000 tree_view->priv->event_last_x,
3001 tree_view->priv->event_last_y);
3002
3003 tree_view->priv->prev_width_before_expander = width_before_expander;
3004 }
3005 }
3006
3007 for (tmp_list = tree_view->priv->children; tmp_list; tmp_list = tmp_list->next)
3008 {
3009 CtkTreeViewChild *child = tmp_list->data;
3010 CtkTreePath *path;
3011 CdkRectangle child_rect;
3012 int min_x, max_x, min_y, max_y;
3013 int size;
3014 CtkTextDirection direction;
3015
3016 direction = ctk_widget_get_direction (child->widget);
3017 path = _ctk_tree_path_new_from_rbtree (child->tree, child->node);
3018 ctk_tree_view_get_cell_area (tree_view, path, child->column, &child_rect);
3019 child_rect.x += child->border.left;
3020 child_rect.y += child->border.top;
3021 child_rect.width -= child->border.left + child->border.right;
3022 child_rect.height -= child->border.top + child->border.bottom;
3023
3024 ctk_widget_get_preferred_width (CTK_WIDGET (child->widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child->widget)), ((ctk_widget_get_type ()))))))
, &size, NULL((void*)0));
3025
3026 if (size > child_rect.width)
3027 {
3028 /* Enlarge the child, extending it to the left (RTL) */
3029 if (direction == CTK_TEXT_DIR_RTL)
3030 child_rect.x -= (size - child_rect.width);
3031 /* or to the right (LTR) */
3032 else
3033 child_rect.x += 0;
3034
3035 child_rect.width = size;
3036 }
3037
3038 ctk_widget_get_preferred_height_for_width (CTK_WIDGET (child->widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child->widget)), ((ctk_widget_get_type ()))))))
,
3039 child_rect.width,
3040 &size, NULL((void*)0));
3041 if (size > child_rect.height)
3042 {
3043 /* Enlarge the child, extending in both directions equally */
3044 child_rect.y -= (size - child_rect.height) / 2;
3045 child_rect.height = size;
3046 }
3047
3048 /* push the rect back in the visible area if needed,
3049 * preferring the top left corner (for RTL)
3050 * or top right corner (for LTR)
3051 */
3052 min_x = ctk_adjustment_get_value (tree_view->priv->hadjustment);
3053 max_x = min_x + allocation->width - child_rect.width;
3054 min_y = 0;
3055 max_y = min_y + allocation->height - ctk_tree_view_get_effective_header_height (tree_view) - child_rect.height;
3056
3057 if (direction == CTK_TEXT_DIR_LTR)
3058 /* Ensure that child's right edge is not sticking to the right
3059 * (if (child_rect.x > max_x) child_rect.x = max_x),
3060 * then ensure that child's left edge is visible and is not sticking to the left
3061 * (if (child_rect.x < min_x) child_rect.x = min_x).
3062 */
3063 child_rect.x = MAX (min_x, MIN (max_x, child_rect.x))(((min_x) > ((((max_x) < (child_rect.x)) ? (max_x) : (child_rect
.x)))) ? (min_x) : ((((max_x) < (child_rect.x)) ? (max_x) :
(child_rect.x))))
;
3064 else
3065 /* Ensure that child's left edge is not sticking to the left
3066 * (if (child_rect.x < min_x) child_rect.x = min_x),
3067 * then ensure that child's right edge is visible and is not sticking to the right
3068 * (if (child_rect.x > max_x) child_rect.x = max_x).
3069 */
3070 child_rect.x = MIN (max_x, MAX (min_x, child_rect.x))(((max_x) < ((((min_x) > (child_rect.x)) ? (min_x) : (child_rect
.x)))) ? (max_x) : ((((min_x) > (child_rect.x)) ? (min_x) :
(child_rect.x))))
;
3071
3072 child_rect.y = MAX (min_y, MIN (max_y, child_rect.y))(((min_y) > ((((max_y) < (child_rect.y)) ? (max_y) : (child_rect
.y)))) ? (min_y) : ((((max_y) < (child_rect.y)) ? (max_y) :
(child_rect.y))))
;
3073
3074 ctk_tree_path_free (path);
3075 ctk_widget_size_allocate (child->widget, &child_rect);
3076 }
3077}
3078
3079/* Grabs the focus and unsets the CTK_TREE_VIEW_DRAW_KEYFOCUS flag */
3080static void
3081grab_focus_and_unset_draw_keyfocus (CtkTreeView *tree_view)
3082{
3083 CtkWidget *widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
3084
3085 if (ctk_widget_get_can_focus (widget) &&
3086 !ctk_widget_has_focus (widget) &&
3087 !_ctk_widget_get_shadowed (widget))
3088 ctk_widget_grab_focus (widget);
3089
3090 tree_view->priv->draw_keyfocus = 0;
3091}
3092
3093static inline gboolean
3094row_is_separator (CtkTreeView *tree_view,
3095 CtkTreeIter *iter,
3096 CtkTreePath *path)
3097{
3098 gboolean is_separator = FALSE(0);
3099
3100 if (tree_view->priv->row_separator_func)
3101 {
3102 CtkTreeIter tmpiter;
3103
3104 if (iter)
3105 tmpiter = *iter;
3106 else
3107 {
3108 if (!ctk_tree_model_get_iter (tree_view->priv->model, &tmpiter, path))
3109 return FALSE(0);
3110 }
3111
3112 is_separator = tree_view->priv->row_separator_func (tree_view->priv->model,
3113 &tmpiter,
3114 tree_view->priv->row_separator_data);
3115 }
3116
3117 return is_separator;
3118}
3119
3120static int
3121ctk_tree_view_get_expander_size (CtkTreeView *tree_view)
3122{
3123 gint expander_size;
3124 gint horizontal_separator;
3125
3126 ctk_widget_style_get (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
3127 "expander-size", &expander_size,
3128 "horizontal-separator", &horizontal_separator,
3129 NULL((void*)0));
3130
3131 return expander_size + (horizontal_separator / 2);
3132}
3133
3134static void
3135get_current_selection_modifiers (CtkWidget *widget,
3136 gboolean *modify,
3137 gboolean *extend)
3138{
3139 CdkModifierType state = 0;
3140 CdkModifierType mask;
3141
3142 *modify = FALSE(0);
3143 *extend = FALSE(0);
3144
3145 if (ctk_get_current_event_state (&state))
3146 {
3147 mask = ctk_widget_get_modifier_mask (widget, CDK_MODIFIER_INTENT_MODIFY_SELECTION);
3148 if ((state & mask) == mask)
3149 *modify = TRUE(!(0));
3150 mask = ctk_widget_get_modifier_mask (widget, CDK_MODIFIER_INTENT_EXTEND_SELECTION);
3151 if ((state & mask) == mask)
3152 *extend = TRUE(!(0));
3153 }
3154}
3155
3156static void
3157ctk_tree_view_multipress_gesture_pressed (CtkGestureMultiPress *gesture,
3158 gint n_press,
3159 gdouble x,
3160 gdouble y,
3161 CtkTreeView *tree_view)
3162{
3163 gint vertical_separator, horizontal_separator;
3164 CtkWidget *widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
3165 CdkRectangle background_area, cell_area;
3166 CtkTreeViewColumn *column = NULL((void*)0);
3167 CdkEventSequence *sequence;
3168 CdkModifierType modifiers;
3169 const CdkEvent *event;
3170 gint new_y, y_offset;
3171 gint bin_x, bin_y;
3172 CtkTreePath *path;
3173 CtkRBNode *node;
3174 CtkRBTree *tree;
3175 gint depth;
3176 guint button;
3177 GList *list;
3178 gboolean rtl;
3179
3180 rtl = (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
3181 ctk_tree_view_stop_editing (tree_view, FALSE(0));
3182 ctk_widget_style_get (widget,
3183 "vertical-separator", &vertical_separator,
3184 "horizontal-separator", &horizontal_separator,
3185 NULL((void*)0));
3186 button = ctk_gesture_single_get_current_button (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
3187
3188 if (button > 3)
3189 {
3190 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
3191 return;
3192 }
3193
3194 /* Because grab_focus can cause reentrancy, we delay grab_focus until after
3195 * we're done handling the button press.
3196 */
3197 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, x, y,
3198 &bin_x, &bin_y);
3199 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_CLAIMED);
3200
3201 if (n_press > 1)
3202 ctk_gesture_set_state (tree_view->priv->drag_gesture,
3203 CTK_EVENT_SEQUENCE_DENIED);
3204
3205 /* Empty tree? */
3206 if (tree_view->priv->tree == NULL((void*)0))
3207 {
3208 grab_focus_and_unset_draw_keyfocus (tree_view);
3209 return;
3210 }
3211
3212 /* are we in an arrow? */
3213 if (tree_view->priv->prelight_node &&
3214 tree_view->priv->arrow_prelit &&
3215 ctk_tree_view_draw_expanders (tree_view))
3216 {
3217 if (button == CDK_BUTTON_PRIMARY(1))
3218 {
3219 tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
3220 tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
3221 ctk_tree_view_queue_draw_arrow (tree_view,
3222 tree_view->priv->prelight_tree,
3223 tree_view->priv->prelight_node);
3224 }
3225
3226 grab_focus_and_unset_draw_keyfocus (tree_view);
3227 return;
3228 }
3229
3230 /* find the node that was clicked */
3231 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, bin_y)((bin_y) + tree_view->priv->dy);
3232 if (new_y < 0)
3233 new_y = 0;
3234 y_offset = -_ctk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
3235
3236 if (node == NULL((void*)0))
3237 {
3238 /* We clicked in dead space */
3239 grab_focus_and_unset_draw_keyfocus (tree_view);
3240 return;
3241 }
3242
3243 /* Get the path and the node */
3244 path = _ctk_tree_path_new_from_rbtree (tree, node);
3245
3246 if (row_is_separator (tree_view, NULL((void*)0), path))
3247 {
3248 ctk_tree_path_free (path);
3249 grab_focus_and_unset_draw_keyfocus (tree_view);
3250 return;
3251 }
3252
3253 depth = ctk_tree_path_get_depth (path);
3254 background_area.y = y_offset + bin_y;
3255 background_area.height = ctk_tree_view_get_row_height (tree_view, node);
3256 background_area.x = 0;
3257
3258 /* Let the column have a chance at selecting it. */
3259 rtl = (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
3260 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
3261 list; list = (rtl ? list->prev : list->next))
3262 {
3263 CtkTreeViewColumn *candidate = list->data;
3264
3265 if (!ctk_tree_view_column_get_visible (candidate))
3266 continue;
3267
3268 background_area.width = ctk_tree_view_column_get_width (candidate);
3269 if ((background_area.x > bin_x) ||
3270 (background_area.x + background_area.width <= bin_x))
3271 {
3272 background_area.x += background_area.width;
3273 continue;
3274 }
3275
3276 /* we found the focus column */
3277 column = candidate;
3278 cell_area = background_area;
3279 cell_area.width -= horizontal_separator;
3280 cell_area.height -= vertical_separator;
3281 cell_area.x += horizontal_separator/2;
3282 cell_area.y += vertical_separator/2;
3283 if (ctk_tree_view_is_expander_column (tree_view, column))
3284 {
3285 if (!rtl)
3286 cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
3287 cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
3288
3289 if (ctk_tree_view_draw_expanders (tree_view))
3290 {
3291 gint expander_size = ctk_tree_view_get_expander_size (tree_view);
3292 if (!rtl)
3293 cell_area.x += depth * expander_size;
3294 cell_area.width -= depth * expander_size;
3295 }
3296 }
3297 break;
3298 }
3299
3300 if (column == NULL((void*)0))
3301 {
3302 ctk_tree_path_free (path);
3303 grab_focus_and_unset_draw_keyfocus (tree_view);
3304 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
3305 return;
3306 }
3307
3308 _ctk_tree_view_set_focus_column (tree_view, column);
3309
3310 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
3311 event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence);
3312 cdk_event_get_state (event, &modifiers);
3313
3314 /* decide if we edit */
3315 if (button == CDK_BUTTON_PRIMARY(1) &&
3316 !(modifiers & ctk_accelerator_get_default_mod_mask ()))
3317 {
3318 CtkTreePath *anchor;
3319 CtkTreeIter iter;
3320
3321 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
3322 ctk_tree_view_column_cell_set_cell_data (column,
3323 tree_view->priv->model,
3324 &iter,
3325 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
3326 node->children?TRUE(!(0)):FALSE(0));
3327
3328 if (tree_view->priv->anchor)
3329 anchor = ctk_tree_row_reference_get_path (tree_view->priv->anchor);
3330 else
3331 anchor = NULL((void*)0);
3332
3333 if ((anchor && !ctk_tree_path_compare (anchor, path))
3334 || !_ctk_tree_view_column_has_editable_cell (column))
3335 {
3336 CtkCellEditable *cell_editable = NULL((void*)0);
3337
3338 /* FIXME: get the right flags */
3339 guint flags = 0;
3340
3341 if (_ctk_tree_view_column_cell_event (column,
3342 (CdkEvent *)event,
3343 &cell_area, flags))
3344 {
3345 CtkCellArea *area = ctk_cell_layout_get_area (CTK_CELL_LAYOUT (column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((column)), ((ctk_cell_layout_get_type ()))))))
);
3346 cell_editable = ctk_cell_area_get_edit_widget (area);
3347
3348 if (cell_editable != NULL((void*)0))
3349 {
3350 ctk_tree_path_free (path);
3351 ctk_tree_path_free (anchor);
3352 return;
3353 }
3354 }
3355 }
3356 if (anchor)
3357 ctk_tree_path_free (anchor);
3358 }
3359
3360 /* we only handle selection modifications on the first button press
3361 */
3362 if (n_press == 1)
3363 {
3364 CtkCellRenderer *focus_cell;
3365 gboolean modify, extend;
3366
3367 get_current_selection_modifiers (widget, &modify, &extend);
3368 tree_view->priv->modify_selection_pressed = modify;
3369 tree_view->priv->extend_selection_pressed = extend;
3370
3371 /* We update the focus cell here, this is also needed if the
3372 * column does not contain an editable cell. In this case,
3373 * CtkCellArea did not receive the event for processing (and
3374 * could not update the focus cell).
3375 */
3376 focus_cell = _ctk_tree_view_column_get_cell_at_pos (column,
3377 &cell_area,
3378 &background_area,
3379 bin_x, bin_y);
3380
3381 if (focus_cell)
3382 ctk_tree_view_column_focus_cell (column, focus_cell);
3383
3384 if (modify)
3385 {
3386 ctk_tree_view_real_set_cursor (tree_view, path, CLAMP_NODE);
3387 ctk_tree_view_real_toggle_cursor_row (tree_view);
3388 }
3389 else if (extend)
3390 {
3391 ctk_tree_view_real_set_cursor (tree_view, path, CLAMP_NODE);
3392 ctk_tree_view_real_select_cursor_row (tree_view, FALSE(0));
3393 }
3394 else
3395 {
3396 ctk_tree_view_real_set_cursor (tree_view, path, CLEAR_AND_SELECT | CLAMP_NODE);
3397 }
3398
3399 tree_view->priv->modify_selection_pressed = FALSE(0);
3400 tree_view->priv->extend_selection_pressed = FALSE(0);
3401 }
3402
3403 if (button == CDK_BUTTON_PRIMARY(1) && n_press == 2)
3404 ctk_tree_view_row_activated (tree_view, path, column);
3405 else
3406 {
3407 if (n_press == 1)
3408 {
3409 tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
3410 tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
3411 }
3412
3413 grab_focus_and_unset_draw_keyfocus (tree_view);
3414 }
3415
3416 ctk_tree_path_free (path);
3417
3418 if (n_press >= 2)
3419 ctk_event_controller_reset (CTK_EVENT_CONTROLLER (gesture)((((CtkEventController*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((gesture)), ((ctk_event_controller_get_type
()))))))
);
3420}
3421
3422static void
3423ctk_tree_view_drag_gesture_begin (CtkGestureDrag *gesture,
3424 gdouble start_x,
3425 gdouble start_y,
3426 CtkTreeView *tree_view)
3427{
3428 gint bin_x, bin_y;
3429 CtkRBTree *tree;
3430 CtkRBNode *node;
3431
3432 if (tree_view->priv->tree == NULL((void*)0))
3433 {
3434 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
3435 return;
3436 }
3437
3438 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, start_x, start_y,
3439 &bin_x, &bin_y);
3440 tree_view->priv->press_start_x = tree_view->priv->rubber_band_x = bin_x;
3441 tree_view->priv->press_start_y = tree_view->priv->rubber_band_y = bin_y;
3442 _ctk_rbtree_find_offset (tree_view->priv->tree, bin_y + tree_view->priv->dy,
3443 &tree, &node);
3444
3445 if (tree_view->priv->rubber_banding_enable
3446 && !CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
3447 && ctk_tree_selection_get_mode (tree_view->priv->selection) == CTK_SELECTION_MULTIPLE)
3448 {
3449 gboolean modify, extend;
3450
3451 tree_view->priv->press_start_y += tree_view->priv->dy;
3452 tree_view->priv->rubber_band_y += tree_view->priv->dy;
3453 tree_view->priv->rubber_band_status = RUBBER_BAND_MAYBE_START;
3454
3455 get_current_selection_modifiers (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &modify, &extend);
3456 tree_view->priv->rubber_band_modify = modify;
3457 tree_view->priv->rubber_band_extend = extend;
3458 }
3459}
3460
3461static void
3462ctk_tree_view_column_multipress_gesture_pressed (CtkGestureMultiPress *gesture,
3463 gint n_press,
3464 gdouble x G_GNUC_UNUSED__attribute__ ((__unused__)),
3465 gdouble y G_GNUC_UNUSED__attribute__ ((__unused__)),
3466 CtkTreeView *tree_view)
3467{
3468 CdkEventSequence *sequence;
3469 CtkTreeViewColumn *column;
3470 const CdkEvent *event;
3471 GList *list;
3472 gint i;
3473
3474 if (n_press != 2)
3475 return;
3476
3477 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
3478 event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence);
3479
3480 for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
3481 {
3482 column = list->data;
3483
3484 if (event->any.window != _ctk_tree_view_column_get_window (column) ||
3485 !ctk_tree_view_column_get_resizable (column))
3486 continue;
3487
3488 if (ctk_tree_view_column_get_sizing (column) != CTK_TREE_VIEW_COLUMN_AUTOSIZE)
3489 {
3490 ctk_tree_view_column_set_fixed_width (column, -1);
3491 ctk_tree_view_column_set_expand (column, FALSE(0));
3492 _ctk_tree_view_column_autosize (tree_view, column);
3493 }
3494
3495 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_CLAIMED);
3496 break;
3497 }
3498}
3499
3500static void
3501ctk_tree_view_column_drag_gesture_begin (CtkGestureDrag *gesture,
3502 gdouble start_x,
3503 gdouble start_y G_GNUC_UNUSED__attribute__ ((__unused__)),
3504 CtkTreeView *tree_view)
3505{
3506 CdkEventSequence *sequence;
3507 CtkTreeViewColumn *column;
3508 const CdkEvent *event;
3509 CdkWindow *window;
3510 gboolean rtl;
3511 GList *list;
3512 gint i;
3513
3514 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
3515 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
3516 event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence);
3517 window = event->any.window;
3518
3519 for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
3520 {
3521 gpointer drag_data;
3522 gint column_width;
3523
3524 column = list->data;
3525
3526 if (window != _ctk_tree_view_column_get_window (column))
3527 continue;
3528
3529 if (!ctk_tree_view_column_get_resizable (column))
3530 break;
3531
3532 tree_view->priv->in_column_resize = TRUE(!(0));
3533
3534 /* block attached dnd signal handler */
3535 drag_data = g_object_get_data (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, "ctk-site-data");
3536 if (drag_data)
3537 g_signal_handlers_block_matched (tree_view,
3538 G_SIGNAL_MATCH_DATA,
3539 0, 0, NULL((void*)0), NULL((void*)0),
3540 drag_data);
3541
3542 column_width = ctk_tree_view_column_get_width (column);
3543 ctk_tree_view_column_set_fixed_width (column, column_width);
3544 ctk_tree_view_column_set_expand (column, FALSE(0));
3545
3546 tree_view->priv->drag_pos = i;
3547 tree_view->priv->x_drag = start_x + (rtl ? column_width : -column_width);
3548
3549 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
3550 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
3551
3552 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_CLAIMED);
3553 return;
3554 }
3555}
3556
3557static void
3558ctk_tree_view_update_button_position (CtkTreeView *tree_view,
3559 CtkTreeViewColumn *column)
3560{
3561 CtkTreeViewPrivate *priv = tree_view->priv;
3562 GList *column_el;
3563
3564 column_el = g_list_find (priv->columns, column);
3565 g_return_if_fail (column_el != NULL)do { if ((column_el != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "column_el != NULL"); return
; } } while (0)
;
3566
3567 ctk_css_node_insert_after (priv->header_node,
3568 ctk_widget_get_css_node (ctk_tree_view_column_get_button (column)),
3569 column_el->prev ? ctk_widget_get_css_node (
3570 ctk_tree_view_column_get_button (column_el->prev->data)) : NULL((void*)0));
3571}
3572
3573/* column drag gesture helper */
3574static gboolean
3575ctk_tree_view_button_release_drag_column (CtkTreeView *tree_view)
3576{
3577 CtkWidget *button, *widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
3578 GList *l;
3579 gboolean rtl;
3580 CtkStyleContext *context;
3581
3582 rtl = (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
3583
3584 /* Move the button back */
3585 button = ctk_tree_view_column_get_button (tree_view->priv->drag_column);
3586
3587 context = ctk_widget_get_style_context (button);
3588 ctk_style_context_remove_class (context, CTK_STYLE_CLASS_DND"dnd");
3589
3590 g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button));
3591 ctk_container_remove (CTK_CONTAINER (tree_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_container_get_type ()))))))
, button);
3592 ctk_widget_set_parent_window (button, tree_view->priv->header_window);
3593 ctk_tree_view_update_button_position (tree_view, tree_view->priv->drag_column);
3594 ctk_widget_set_parent (button, CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
3595 g_object_unref (button);
3596 ctk_widget_queue_resize (widget);
3597 if (ctk_tree_view_column_get_resizable (tree_view->priv->drag_column))
3598 {
3599 cdk_window_raise (_ctk_tree_view_column_get_window (tree_view->priv->drag_column));
3600 cdk_window_show (_ctk_tree_view_column_get_window (tree_view->priv->drag_column));
3601 }
3602 else
3603 cdk_window_hide (_ctk_tree_view_column_get_window (tree_view->priv->drag_column));
3604
3605 ctk_widget_grab_focus (button);
3606
3607 if (rtl)
3608 {
3609 if (tree_view->priv->cur_reorder &&
3610 tree_view->priv->cur_reorder->right_column != tree_view->priv->drag_column)
3611 ctk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
3612 tree_view->priv->cur_reorder->right_column);
3613 }
3614 else
3615 {
3616 if (tree_view->priv->cur_reorder &&
3617 tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
3618 ctk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
3619 tree_view->priv->cur_reorder->left_column);
3620 }
3621 tree_view->priv->drag_column = NULL((void*)0);
3622 ctk_widget_unregister_window (widget, tree_view->priv->drag_window);
3623 cdk_window_destroy (tree_view->priv->drag_window);
3624 tree_view->priv->drag_window = NULL((void*)0);
3625
3626 for (l = tree_view->priv->column_drag_info; l != NULL((void*)0); l = l->next)
3627 g_slice_free (CtkTreeViewColumnReorder, l->data)do { if (1) g_slice_free1 (sizeof (CtkTreeViewColumnReorder),
(l->data)); else (void) ((CtkTreeViewColumnReorder*) 0 ==
(l->data)); } while (0)
;
3628 g_list_free (tree_view->priv->column_drag_info);
3629 tree_view->priv->column_drag_info = NULL((void*)0);
3630 tree_view->priv->cur_reorder = NULL((void*)0);
3631
3632 if (tree_view->priv->drag_highlight_window)
3633 cdk_window_hide (tree_view->priv->drag_highlight_window);
3634
3635 /* Reset our flags */
3636 tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_UNSET;
3637 tree_view->priv->in_column_drag = FALSE(0);
3638
3639 return TRUE(!(0));
3640}
3641
3642/* column drag gesture helper */
3643static gboolean
3644ctk_tree_view_button_release_column_resize (CtkTreeView *tree_view)
3645{
3646 gpointer drag_data;
3647
3648 tree_view->priv->drag_pos = -1;
3649
3650 /* unblock attached dnd signal handler */
3651 drag_data = g_object_get_data (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, "ctk-site-data");
3652 if (drag_data)
3653 g_signal_handlers_unblock_matched (tree_view,
3654 G_SIGNAL_MATCH_DATA,
3655 0, 0, NULL((void*)0), NULL((void*)0),
3656 drag_data);
3657
3658 tree_view->priv->in_column_resize = FALSE(0);
3659 return TRUE(!(0));
3660}
3661
3662static void
3663ctk_tree_view_column_drag_gesture_end (CtkGestureDrag *gesture,
3664 gdouble offset_x G_GNUC_UNUSED__attribute__ ((__unused__)),
3665 gdouble offset_y G_GNUC_UNUSED__attribute__ ((__unused__)),
3666 CtkTreeView *tree_view)
3667{
3668 CdkEventSequence *sequence;
3669
3670 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
3671
3672 /* Cancel reorder if the drag got cancelled */
3673 if (!ctk_gesture_handles_sequence (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence))
3674 tree_view->priv->cur_reorder = NULL((void*)0);
3675
3676 if (tree_view->priv->in_column_drag)
3677 {
3678 CdkDevice *device;
3679
3680 ctk_tree_view_button_release_drag_column (tree_view);
3681 device = ctk_gesture_get_device (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
);
3682 cdk_seat_ungrab (cdk_device_get_seat (device));
3683 }
3684 else if (tree_view->priv->in_column_resize)
3685 ctk_tree_view_button_release_column_resize (tree_view);
3686}
3687
3688static void
3689ctk_tree_view_drag_gesture_end (CtkGestureDrag *gesture G_GNUC_UNUSED__attribute__ ((__unused__)),
3690 gdouble offset_x G_GNUC_UNUSED__attribute__ ((__unused__)),
3691 gdouble offset_y G_GNUC_UNUSED__attribute__ ((__unused__)),
3692 CtkTreeView *tree_view)
3693{
3694 ctk_tree_view_stop_rubber_band (tree_view);
3695}
3696
3697static void
3698ctk_tree_view_multipress_gesture_released (CtkGestureMultiPress *gesture,
3699 gint n_press G_GNUC_UNUSED__attribute__ ((__unused__)),
3700 gdouble x G_GNUC_UNUSED__attribute__ ((__unused__)),
3701 gdouble y G_GNUC_UNUSED__attribute__ ((__unused__)),
3702 CtkTreeView *tree_view)
3703{
3704 gboolean modify, extend;
3705 guint button;
3706
3707 button = ctk_gesture_single_get_current_button (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
3708
3709 if (button != CDK_BUTTON_PRIMARY(1) ||
3710 tree_view->priv->button_pressed_node == NULL((void*)0) ||
3711 tree_view->priv->button_pressed_node != tree_view->priv->prelight_node)
3712 return;
3713
3714 get_current_selection_modifiers (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &modify, &extend);
3715
3716 if (tree_view->priv->arrow_prelit)
3717 {
3718 CtkTreePath *path = NULL((void*)0);
3719
3720 path = _ctk_tree_path_new_from_rbtree (tree_view->priv->button_pressed_tree,
3721 tree_view->priv->button_pressed_node);
3722 /* Actually activate the node */
3723 if (tree_view->priv->button_pressed_node->children == NULL((void*)0))
3724 ctk_tree_view_real_expand_row (tree_view, path,
3725 tree_view->priv->button_pressed_tree,
3726 tree_view->priv->button_pressed_node,
3727 FALSE(0), TRUE(!(0)));
3728 else
3729 ctk_tree_view_real_collapse_row (tree_view, path,
3730 tree_view->priv->button_pressed_tree,
3731 tree_view->priv->button_pressed_node, TRUE(!(0)));
3732 ctk_tree_path_free (path);
3733 }
3734 else if (tree_view->priv->activate_on_single_click && !modify && !extend)
3735 {
3736 CtkTreePath *path = NULL((void*)0);
3737
3738 path = _ctk_tree_path_new_from_rbtree (tree_view->priv->button_pressed_tree,
3739 tree_view->priv->button_pressed_node);
3740 ctk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
3741 ctk_tree_path_free (path);
3742 }
3743
3744 tree_view->priv->button_pressed_tree = NULL((void*)0);
3745 tree_view->priv->button_pressed_node = NULL((void*)0);
3746}
3747
3748/* CtkWidget::motion_event function set.
3749 */
3750
3751static gboolean
3752coords_are_over_arrow (CtkTreeView *tree_view,
3753 CtkRBTree *tree,
3754 CtkRBNode *node,
3755 /* these are in bin window coords */
3756 gint x,
3757 gint y)
3758{
3759 CdkRectangle arrow;
3760 gint x2;
3761
3762 if (!ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
3763 return FALSE(0);
3764
3765 if ((node->flags & CTK_RBNODE_IS_PARENT) == 0)
3766 return FALSE(0);
3767
3768 arrow.y = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
3769 arrow.height = ctk_tree_view_get_row_height (tree_view, node);
3770
3771 ctk_tree_view_get_arrow_xrange (tree_view, tree, &arrow.x, &x2);
3772
3773 arrow.width = x2 - arrow.x;
3774
3775 return (x >= arrow.x &&
3776 x < (arrow.x + arrow.width) &&
3777 y >= arrow.y &&
3778 y < (arrow.y + arrow.height));
3779}
3780
3781static gboolean
3782auto_expand_timeout (gpointer data)
3783{
3784 CtkTreeView *tree_view = CTK_TREE_VIEW (data)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_view_get_type ()))))))
;
3785 CtkTreePath *path;
3786
3787 if (tree_view->priv->prelight_node)
3788 {
3789 path = _ctk_tree_path_new_from_rbtree (tree_view->priv->prelight_tree,
3790 tree_view->priv->prelight_node);
3791
3792 if (tree_view->priv->prelight_node->children)
3793 ctk_tree_view_collapse_row (tree_view, path);
3794 else
3795 ctk_tree_view_expand_row (tree_view, path, FALSE(0));
3796
3797 ctk_tree_path_free (path);
3798 }
3799
3800 tree_view->priv->auto_expand_timeout = 0;
3801
3802 return FALSE(0);
3803}
3804
3805static void
3806remove_auto_expand_timeout (CtkTreeView *tree_view)
3807{
3808 if (tree_view->priv->auto_expand_timeout != 0)
3809 {
3810 g_source_remove (tree_view->priv->auto_expand_timeout);
3811 tree_view->priv->auto_expand_timeout = 0;
3812 }
3813}
3814
3815static void
3816do_prelight (CtkTreeView *tree_view,
3817 CtkRBTree *tree,
3818 CtkRBNode *node,
3819 /* these are in bin_window coords */
3820 gint x,
3821 gint y)
3822{
3823 if (tree_view->priv->prelight_tree == tree &&
3824 tree_view->priv->prelight_node == node)
3825 {
3826 /* We are still on the same node,
3827 but we might need to take care of the arrow */
3828
3829 if (tree && node && ctk_tree_view_draw_expanders (tree_view))
3830 {
3831 gboolean over_arrow;
3832
3833 over_arrow = coords_are_over_arrow (tree_view, tree, node, x, y);
3834
3835 if (over_arrow != tree_view->priv->arrow_prelit)
3836 {
3837 if (over_arrow)
3838 tree_view->priv->arrow_prelit = TRUE(!(0));
3839 else
3840 tree_view->priv->arrow_prelit = FALSE(0);
3841
3842 ctk_tree_view_queue_draw_arrow (tree_view, tree, node);
3843 }
3844 }
3845
3846 return;
3847 }
3848
3849 if (tree_view->priv->prelight_tree && tree_view->priv->prelight_node)
3850 {
3851 /* Unprelight the old node and arrow */
3852
3853 CTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node,do{ (tree_view->priv->prelight_node->flags&=~(CTK_RBNODE_IS_PRELIT
)); }while (0)
3854 CTK_RBNODE_IS_PRELIT)do{ (tree_view->priv->prelight_node->flags&=~(CTK_RBNODE_IS_PRELIT
)); }while (0)
;
3855
3856 if (tree_view->priv->arrow_prelit
3857 && ctk_tree_view_draw_expanders (tree_view))
3858 {
3859 tree_view->priv->arrow_prelit = FALSE(0);
3860
3861 ctk_tree_view_queue_draw_arrow (tree_view,
3862 tree_view->priv->prelight_tree,
3863 tree_view->priv->prelight_node);
3864 }
3865
3866 _ctk_tree_view_queue_draw_node (tree_view,
3867 tree_view->priv->prelight_tree,
3868 tree_view->priv->prelight_node,
3869 NULL((void*)0));
3870 }
3871
3872
3873 if (tree_view->priv->hover_expand)
3874 remove_auto_expand_timeout (tree_view);
3875
3876 /* Set the new prelight values */
3877 tree_view->priv->prelight_node = node;
3878 tree_view->priv->prelight_tree = tree;
3879
3880 if (!node || !tree)
3881 return;
3882
3883 /* Prelight the new node and arrow */
3884
3885 if (ctk_tree_view_draw_expanders (tree_view)
3886 && coords_are_over_arrow (tree_view, tree, node, x, y))
3887 {
3888 tree_view->priv->arrow_prelit = TRUE(!(0));
3889
3890 ctk_tree_view_queue_draw_arrow (tree_view, tree, node);
3891 }
3892
3893 CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_IS_PRELIT)do{ (node->flags|=CTK_RBNODE_IS_PRELIT); }while (0);
3894
3895 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
3896
3897 if (tree_view->priv->hover_expand)
3898 {
3899 tree_view->priv->auto_expand_timeout =
3900 cdk_threads_add_timeout (AUTO_EXPAND_TIMEOUT500, auto_expand_timeout, tree_view);
3901 g_source_set_name_by_id (tree_view->priv->auto_expand_timeout, "[ctk+] auto_expand_timeout");
3902 }
3903}
3904
3905static void
3906prelight_or_select (CtkTreeView *tree_view,
3907 CtkRBTree *tree,
3908 CtkRBNode *node,
3909 /* these are in bin_window coords */
3910 gint x,
3911 gint y)
3912{
3913 CtkSelectionMode mode = ctk_tree_selection_get_mode (tree_view->priv->selection);
3914
3915 if (tree_view->priv->hover_selection &&
3916 (mode == CTK_SELECTION_SINGLE || mode == CTK_SELECTION_BROWSE) &&
3917 !(tree_view->priv->edited_column &&
3918 ctk_cell_area_get_edit_widget
3919 (ctk_cell_layout_get_area (CTK_CELL_LAYOUT (tree_view->priv->edited_column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->edited_column)), ((ctk_cell_layout_get_type
()))))))
))))
3920 {
3921 if (node)
3922 {
3923 if (!CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
3924 {
3925 CtkTreePath *path;
3926
3927 path = _ctk_tree_path_new_from_rbtree (tree, node);
3928 ctk_tree_selection_select_path (tree_view->priv->selection, path);
3929 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
3930 {
3931 tree_view->priv->draw_keyfocus = FALSE(0);
3932 ctk_tree_view_real_set_cursor (tree_view, path, 0);
3933 }
3934 ctk_tree_path_free (path);
3935 }
3936 }
3937
3938 else if (mode == CTK_SELECTION_SINGLE)
3939 ctk_tree_selection_unselect_all (tree_view->priv->selection);
3940 }
3941
3942 do_prelight (tree_view, tree, node, x, y);
3943}
3944
3945static void
3946ensure_unprelighted (CtkTreeView *tree_view)
3947{
3948 do_prelight (tree_view,
3949 NULL((void*)0), NULL((void*)0),
3950 -1000, -1000); /* coords not possibly over an arrow */
3951
3952 g_assert (tree_view->priv->prelight_node == NULL)do { if (tree_view->priv->prelight_node == ((void*)0)) ;
else g_assertion_message_expr ("Ctk", "ctktreeview.c", 3952,
((const char*) (__func__)), "tree_view->priv->prelight_node == NULL"
); } while (0)
;
3953}
3954
3955static void
3956update_prelight (CtkTreeView *tree_view,
3957 gint x,
3958 gint y)
3959{
3960 int new_y;
3961 CtkRBTree *tree;
3962 CtkRBNode *node;
3963
3964 if (tree_view->priv->tree == NULL((void*)0))
3965 return;
3966
3967 if (x == -10000)
3968 {
3969 ensure_unprelighted (tree_view);
3970 return;
3971 }
3972
3973 new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y)((y) + tree_view->priv->dy);
3974 if (new_y < 0)
3975 new_y = 0;
3976
3977 _ctk_rbtree_find_offset (tree_view->priv->tree,
3978 new_y, &tree, &node);
3979
3980 if (node)
3981 prelight_or_select (tree_view, tree, node, x, y);
3982}
3983
3984
3985
3986
3987/* Our motion arrow is either a box (in the case of the original spot)
3988 * or an arrow. It is expander_size wide.
3989 */
3990/*
3991 * 11111111111111
3992 * 01111111111110
3993 * 00111111111100
3994 * 00011111111000
3995 * 00001111110000
3996 * 00000111100000
3997 * 00000111100000
3998 * 00000111100000
3999 * ~ ~ ~ ~ ~ ~ ~
4000 * 00000111100000
4001 * 00000111100000
4002 * 00000111100000
4003 * 00001111110000
4004 * 00011111111000
4005 * 00111111111100
4006 * 01111111111110
4007 * 11111111111111
4008 */
4009
4010static void
4011ctk_tree_view_motion_draw_column_motion_arrow (CtkTreeView *tree_view)
4012{
4013 CtkTreeViewColumnReorder *reorder = tree_view->priv->cur_reorder;
4014 CtkWidget *widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
4015 cairo_surface_t *mask_image;
4016 cairo_region_t *mask_region;
4017 gint x;
4018 gint y;
4019 gint width;
4020 gint height;
4021 gint arrow_type = DRAG_COLUMN_WINDOW_STATE_UNSET;
4022 CdkWindowAttr attributes;
4023 guint attributes_mask;
4024 cairo_t *cr;
4025
4026 if (!reorder ||
4027 reorder->left_column == tree_view->priv->drag_column ||
4028 reorder->right_column == tree_view->priv->drag_column)
4029 arrow_type = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
4030 else if (reorder->left_column || reorder->right_column)
4031 {
4032 CtkAllocation left_allocation, right_allocation;
4033 CdkRectangle visible_rect;
4034 CtkWidget *button;
4035
4036 ctk_tree_view_get_visible_rect (tree_view, &visible_rect);
4037 if (reorder->left_column)
4038 {
4039 button = ctk_tree_view_column_get_button (reorder->left_column);
4040 ctk_widget_get_allocation (button, &left_allocation);
4041 x = left_allocation.x + left_allocation.width;
4042 }
4043 else
4044 {
4045 button = ctk_tree_view_column_get_button (reorder->right_column);
4046 ctk_widget_get_allocation (button, &right_allocation);
4047 x = right_allocation.x;
4048 }
4049
4050 if (x < visible_rect.x)
4051 arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT;
4052 else if (x > visible_rect.x + visible_rect.width)
4053 arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT;
4054 else
4055 arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW;
4056 }
4057
4058 /* We want to draw the rectangle over the initial location. */
4059 if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
4060 {
4061 if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
4062 {
4063 CtkAllocation drag_allocation;
4064 CtkWidget *button;
4065
4066 if (tree_view->priv->drag_highlight_window)
4067 {
4068 ctk_widget_unregister_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_highlight_window);
4069 cdk_window_destroy (tree_view->priv->drag_highlight_window);
4070 }
4071
4072 button = ctk_tree_view_column_get_button (tree_view->priv->drag_column);
4073 attributes.window_type = CDK_WINDOW_CHILD;
4074 attributes.wclass = CDK_INPUT_OUTPUT;
4075 attributes.x = tree_view->priv->drag_column_x;
4076 attributes.y = 0;
4077 ctk_widget_get_allocation (button, &drag_allocation);
4078 width = attributes.width = drag_allocation.width;
4079 height = attributes.height = drag_allocation.height;
4080 attributes.visual = cdk_screen_get_rgba_visual (ctk_widget_get_screen (widget));
4081 attributes.event_mask = CDK_VISIBILITY_NOTIFY_MASK | CDK_POINTER_MOTION_MASK;
4082 attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL;
4083 tree_view->priv->drag_highlight_window = cdk_window_new (tree_view->priv->header_window, &attributes, attributes_mask);
4084 ctk_widget_register_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_highlight_window);
4085
4086 tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
4087 }
4088 }
4089 else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW)
4090 {
4091 CtkAllocation button_allocation;
4092 CtkWidget *button;
4093
4094 width = ctk_tree_view_get_expander_size (tree_view);
4095
4096 /* Get x, y, width, height of arrow */
4097 cdk_window_get_origin (tree_view->priv->header_window, &x, &y);
4098 if (reorder->left_column)
4099 {
4100 button = ctk_tree_view_column_get_button (reorder->left_column);
4101 ctk_widget_get_allocation (button, &button_allocation);
4102 x += button_allocation.x + button_allocation.width - width/2;
4103 height = button_allocation.height;
4104 }
4105 else
4106 {
4107 button = ctk_tree_view_column_get_button (reorder->right_column);
4108 ctk_widget_get_allocation (button, &button_allocation);
4109 x += button_allocation.x - width/2;
4110 height = button_allocation.height;
4111 }
4112 y -= width/2; /* The arrow takes up only half the space */
4113 height += width;
4114
4115 /* Create the new window */
4116 if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
4117 {
4118 if (tree_view->priv->drag_highlight_window)
4119 {
4120 ctk_widget_unregister_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_highlight_window);
4121 cdk_window_destroy (tree_view->priv->drag_highlight_window);
4122 }
4123
4124 attributes.window_type = CDK_WINDOW_TEMP;
4125 attributes.wclass = CDK_INPUT_OUTPUT;
4126 attributes.visual = ctk_widget_get_visual (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
4127 attributes.event_mask = CDK_VISIBILITY_NOTIFY_MASK | CDK_POINTER_MOTION_MASK;
4128 attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL;
4129 attributes.x = x;
4130 attributes.y = y;
4131 attributes.width = width;
4132 attributes.height = height;
4133 tree_view->priv->drag_highlight_window = cdk_window_new (cdk_screen_get_root_window (ctk_widget_get_screen (widget)),
4134 &attributes, attributes_mask);
4135 ctk_widget_register_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_highlight_window);
4136
4137 mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
4138
4139 cr = cairo_create (mask_image);
4140 cairo_move_to (cr, 0, 0);
4141 cairo_line_to (cr, width, 0);
4142 cairo_line_to (cr, width / 2., width / 2);
4143 cairo_move_to (cr, 0, height);
4144 cairo_line_to (cr, width, height);
4145 cairo_line_to (cr, width / 2., height - width / 2.);
4146 cairo_fill (cr);
4147 cairo_destroy (cr);
4148
4149 mask_region = cdk_cairo_region_create_from_surface (mask_image);
4150 cdk_window_shape_combine_region (tree_view->priv->drag_highlight_window,
4151 mask_region, 0, 0);
4152
4153 cairo_region_destroy (mask_region);
4154 cairo_surface_destroy (mask_image);
4155 }
4156
4157 tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
4158 cdk_window_move (tree_view->priv->drag_highlight_window, x, y);
4159 }
4160 else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT ||
4161 arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
4162 {
4163 CtkAllocation allocation;
4164 CtkWidget *button;
4165 gint expander_size;
4166
4167 expander_size = ctk_tree_view_get_expander_size (tree_view);
4168
4169 /* Get x, y, width, height of arrow */
4170 width = expander_size/2; /* remember, the arrow only takes half the available width */
4171 cdk_window_get_origin (ctk_widget_get_window (widget),
4172 &x, &y);
4173 if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
4174 {
4175 ctk_widget_get_allocation (widget, &allocation);
4176 x += allocation.width - width;
4177 }
4178
4179 if (reorder->left_column)
4180 {
4181 button = ctk_tree_view_column_get_button (reorder->left_column);
4182 ctk_widget_get_allocation (button, &allocation);
4183 height = allocation.height;
4184 }
4185 else
4186 {
4187 button = ctk_tree_view_column_get_button (reorder->right_column);
4188 ctk_widget_get_allocation (button, &allocation);
4189 height = allocation.height;
4190 }
4191
4192 y -= expander_size;
4193 height += 2 * expander_size;
4194
4195 /* Create the new window */
4196 if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT &&
4197 tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
4198 {
4199 if (tree_view->priv->drag_highlight_window)
4200 {
4201 ctk_widget_unregister_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_highlight_window);
4202 cdk_window_destroy (tree_view->priv->drag_highlight_window);
4203 }
4204
4205 attributes.window_type = CDK_WINDOW_TEMP;
4206 attributes.wclass = CDK_INPUT_OUTPUT;
4207 attributes.visual = ctk_widget_get_visual (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
4208 attributes.event_mask = CDK_VISIBILITY_NOTIFY_MASK | CDK_POINTER_MOTION_MASK;
4209 attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL;
4210 attributes.x = x;
4211 attributes.y = y;
4212 attributes.width = width;
4213 attributes.height = height;
4214 tree_view->priv->drag_highlight_window = cdk_window_new (cdk_screen_get_root_window (ctk_widget_get_screen (widget)), &attributes, attributes_mask);
4215 ctk_widget_register_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_highlight_window);
4216
4217 mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
4218
4219 cr = cairo_create (mask_image);
4220 /* mirror if we're on the left */
4221 if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT)
4222 {
4223 cairo_translate (cr, width, 0);
4224 cairo_scale (cr, -1, 1);
4225 }
4226 cairo_move_to (cr, 0, 0);
4227 cairo_line_to (cr, width, width);
4228 cairo_line_to (cr, 0, expander_size);
4229 cairo_move_to (cr, 0, height);
4230 cairo_line_to (cr, width, height - width);
4231 cairo_line_to (cr, 0, height - expander_size);
4232 cairo_fill (cr);
4233 cairo_destroy (cr);
4234
4235 mask_region = cdk_cairo_region_create_from_surface (mask_image);
4236 cdk_window_shape_combine_region (tree_view->priv->drag_highlight_window,
4237 mask_region, 0, 0);
4238
4239 cairo_region_destroy (mask_region);
4240 cairo_surface_destroy (mask_image);
4241 }
4242
4243 tree_view->priv->drag_column_window_state = arrow_type;
4244 cdk_window_move (tree_view->priv->drag_highlight_window, x, y);
4245 }
4246 else
4247 {
4248 g_warning (G_STRLOC"ctktreeview.c" ":" "4248""Invalid CtkTreeViewColumnReorder struct");
4249 cdk_window_hide (tree_view->priv->drag_highlight_window);
4250 return;
4251 }
4252
4253 cdk_window_show (tree_view->priv->drag_highlight_window);
4254 cdk_window_raise (tree_view->priv->drag_highlight_window);
4255}
4256
4257static gboolean
4258ctk_tree_view_motion_resize_column (CtkTreeView *tree_view,
4259 gdouble x,
4260 gdouble y G_GNUC_UNUSED__attribute__ ((__unused__)))
4261{
4262 gint new_width;
4263 CtkTreeViewColumn *column;
4264
4265 column = ctk_tree_view_get_column (tree_view, tree_view->priv->drag_pos);
4266
4267 if (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL)
4268 new_width = MAX (tree_view->priv->x_drag - x, 0)(((tree_view->priv->x_drag - x) > (0)) ? (tree_view->
priv->x_drag - x) : (0))
;
4269 else
4270 new_width = MAX (x - tree_view->priv->x_drag, 0)(((x - tree_view->priv->x_drag) > (0)) ? (x - tree_view
->priv->x_drag) : (0))
;
4271
4272 if (new_width != ctk_tree_view_column_get_fixed_width (column))
4273 ctk_tree_view_column_set_fixed_width (column, new_width);
4274
4275 return FALSE(0);
4276}
4277
4278static void
4279ctk_tree_view_update_current_reorder (CtkTreeView *tree_view)
4280{
4281 CtkTreeViewColumnReorder *reorder = NULL((void*)0);
4282 CdkEventSequence *sequence;
4283 GList *list;
4284 gdouble x;
4285
4286 sequence = ctk_gesture_single_get_current_sequence
4287 (CTK_GESTURE_SINGLE (tree_view->priv->column_drag_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((tree_view->priv->column_drag_gesture)
), ((ctk_gesture_single_get_type ()))))))
);
4288 ctk_gesture_get_point (tree_view->priv->column_drag_gesture,
4289 sequence, &x, NULL((void*)0));
4290 x += ctk_adjustment_get_value (tree_view->priv->hadjustment);
4291
4292 for (list = tree_view->priv->column_drag_info; list; list = list->next)
4293 {
4294 reorder = (CtkTreeViewColumnReorder *) list->data;
4295 if (x >= reorder->left_align && x < reorder->right_align)
4296 break;
4297 reorder = NULL((void*)0);
4298 }
4299
4300 tree_view->priv->cur_reorder = reorder;
4301 ctk_tree_view_motion_draw_column_motion_arrow (tree_view);
4302}
4303
4304static void
4305ctk_tree_view_vertical_autoscroll (CtkTreeView *tree_view)
4306{
4307 CdkRectangle visible_rect;
4308 gint y;
4309 gint offset;
4310
4311 if (ctk_gesture_is_recognized (tree_view->priv->drag_gesture))
4312 {
4313 CdkEventSequence *sequence;
4314 gdouble py;
4315
4316 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (tree_view->priv->drag_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_single_get_type
()))))))
);
4317 ctk_gesture_get_point (tree_view->priv->drag_gesture, sequence, NULL((void*)0), &py);
4318 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, 0, py,
4319 NULL((void*)0), &y);
4320 }
4321 else
4322 {
4323 y = tree_view->priv->event_last_y;
4324 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, 0, y, NULL((void*)0), &y);
4325 }
4326
4327 y += tree_view->priv->dy;
4328 ctk_tree_view_get_visible_rect (tree_view, &visible_rect);
4329
4330 /* see if we are near the edge. */
4331 offset = y - (visible_rect.y + 2 * SCROLL_EDGE_SIZE15);
4332 if (offset > 0)
4333 {
4334 offset = y - (visible_rect.y + visible_rect.height - 2 * SCROLL_EDGE_SIZE15);
4335 if (offset < 0)
4336 return;
4337 }
4338
4339 ctk_adjustment_set_value (tree_view->priv->vadjustment,
4340 MAX (ctk_adjustment_get_value (tree_view->priv->vadjustment) + offset, 0.0)(((ctk_adjustment_get_value (tree_view->priv->vadjustment
) + offset) > (0.0)) ? (ctk_adjustment_get_value (tree_view
->priv->vadjustment) + offset) : (0.0))
);
4341}
4342
4343static gboolean
4344ctk_tree_view_horizontal_autoscroll (CtkTreeView *tree_view)
4345{
4346 CdkEventSequence *sequence;
4347 CdkRectangle visible_rect;
4348 gdouble x;
4349 gint offset;
4350
4351 sequence = ctk_gesture_single_get_current_sequence
4352 (CTK_GESTURE_SINGLE (tree_view->priv->column_drag_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((tree_view->priv->column_drag_gesture)
), ((ctk_gesture_single_get_type ()))))))
);
4353 ctk_gesture_get_point (tree_view->priv->column_drag_gesture,
4354 sequence, &x, NULL((void*)0));
4355 ctk_tree_view_get_visible_rect (tree_view, &visible_rect);
4356
4357 x += ctk_adjustment_get_value (tree_view->priv->hadjustment);
4358
4359 /* See if we are near the edge. */
4360 offset = x - (visible_rect.x + SCROLL_EDGE_SIZE15);
4361 if (offset > 0)
4362 {
4363 offset = x - (visible_rect.x + visible_rect.width - SCROLL_EDGE_SIZE15);
4364 if (offset < 0)
4365 return TRUE(!(0));
4366 }
4367 offset = offset/3;
4368
4369 ctk_adjustment_set_value (tree_view->priv->hadjustment,
4370 MAX (ctk_adjustment_get_value (tree_view->priv->hadjustment) + offset, 0.0)(((ctk_adjustment_get_value (tree_view->priv->hadjustment
) + offset) > (0.0)) ? (ctk_adjustment_get_value (tree_view
->priv->hadjustment) + offset) : (0.0))
);
4371
4372 return TRUE(!(0));
4373
4374}
4375
4376static gboolean
4377ctk_tree_view_motion_drag_column (CtkTreeView *tree_view,
4378 gdouble x,
4379 gdouble y G_GNUC_UNUSED__attribute__ ((__unused__)))
4380{
4381 CtkAllocation allocation, button_allocation;
4382 CtkTreeViewColumn *column = tree_view->priv->drag_column;
4383 CtkWidget *button;
4384 gint win_x, win_y;
4385
4386 button = ctk_tree_view_column_get_button (column);
4387 x += ctk_adjustment_get_value (tree_view->priv->hadjustment);
4388
4389 /* Handle moving the header */
4390 cdk_window_get_position (tree_view->priv->drag_window, &win_x, &win_y);
4391 ctk_widget_get_allocation (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &allocation);
4392 ctk_widget_get_allocation (button, &button_allocation);
4393 win_x = CLAMP (x - _ctk_tree_view_column_get_drag_x (column), 0,(((x - _ctk_tree_view_column_get_drag_x (column)) > ((((tree_view
->priv->width) > (allocation.width)) ? (tree_view->
priv->width) : (allocation.width)) - button_allocation.width
)) ? ((((tree_view->priv->width) > (allocation.width
)) ? (tree_view->priv->width) : (allocation.width)) - button_allocation
.width) : (((x - _ctk_tree_view_column_get_drag_x (column)) <
(0)) ? (0) : (x - _ctk_tree_view_column_get_drag_x (column))
))
4394 MAX (tree_view->priv->width, allocation.width) - button_allocation.width)(((x - _ctk_tree_view_column_get_drag_x (column)) > ((((tree_view
->priv->width) > (allocation.width)) ? (tree_view->
priv->width) : (allocation.width)) - button_allocation.width
)) ? ((((tree_view->priv->width) > (allocation.width
)) ? (tree_view->priv->width) : (allocation.width)) - button_allocation
.width) : (((x - _ctk_tree_view_column_get_drag_x (column)) <
(0)) ? (0) : (x - _ctk_tree_view_column_get_drag_x (column))
))
;
4395 cdk_window_move (tree_view->priv->drag_window, win_x, win_y);
4396 cdk_window_raise (tree_view->priv->drag_window);
4397
4398 /* autoscroll, if needed */
4399 ctk_tree_view_horizontal_autoscroll (tree_view);
4400 /* Update the current reorder position and arrow; */
4401 ctk_tree_view_update_current_reorder (tree_view);
4402
4403 return TRUE(!(0));
4404}
4405
4406static void
4407ctk_tree_view_stop_rubber_band (CtkTreeView *tree_view)
4408{
4409 remove_scroll_timeout (tree_view);
4410
4411 if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
4412 {
4413 CtkTreePath *tmp_path;
4414
4415 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
4416
4417 /* The anchor path should be set to the start path */
4418 if (tree_view->priv->rubber_band_start_node)
4419 {
4420 tmp_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->rubber_band_start_tree,
4421 tree_view->priv->rubber_band_start_node);
4422
4423 if (tree_view->priv->anchor)
4424 ctk_tree_row_reference_free (tree_view->priv->anchor);
4425
4426 tree_view->priv->anchor =
4427 ctk_tree_row_reference_new_proxy (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
,
4428 tree_view->priv->model,
4429 tmp_path);
4430
4431 ctk_tree_path_free (tmp_path);
4432 }
4433
4434 /* ... and the cursor to the end path */
4435 if (tree_view->priv->rubber_band_end_node)
4436 {
4437 tmp_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->rubber_band_end_tree,
4438 tree_view->priv->rubber_band_end_node);
4439 ctk_tree_view_real_set_cursor (CTK_TREE_VIEW (tree_view)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_tree_view_get_type ()))))))
, tmp_path, 0);
4440 ctk_tree_path_free (tmp_path);
4441 }
4442
4443 _ctk_tree_selection_emit_changed (tree_view->priv->selection);
4444
4445 ctk_css_node_set_parent (tree_view->priv->rubber_band_cssnode, NULL((void*)0));
4446 tree_view->priv->rubber_band_cssnode = NULL((void*)0);
4447 }
4448
4449 /* Clear status variables */
4450 tree_view->priv->rubber_band_status = RUBBER_BAND_OFF;
4451 tree_view->priv->rubber_band_extend = FALSE(0);
4452 tree_view->priv->rubber_band_modify = FALSE(0);
4453
4454 tree_view->priv->rubber_band_start_node = NULL((void*)0);
4455 tree_view->priv->rubber_band_start_tree = NULL((void*)0);
4456 tree_view->priv->rubber_band_end_node = NULL((void*)0);
4457 tree_view->priv->rubber_band_end_tree = NULL((void*)0);
4458}
4459
4460static void
4461ctk_tree_view_update_rubber_band_selection_range (CtkTreeView *tree_view,
4462 CtkRBTree *start_tree,
4463 CtkRBNode *start_node,
4464 CtkRBTree *end_tree G_GNUC_UNUSED__attribute__ ((__unused__)),
4465 CtkRBNode *end_node,
4466 gboolean select,
4467 gboolean skip_start,
4468 gboolean skip_end)
4469{
4470 if (start_node
40.1
'start_node' is not equal to 'end_node'
== end_node)
41
Taking false branch
4471 return;
4472
4473 /* We skip the first node and jump inside the loop */
4474 if (skip_start
41.1
'skip_start' is 0
)
4475 goto skip_first;
4476
4477 do
4478 {
4479 /* Small optimization by assuming insensitive nodes are never
4480 * selected.
4481 */
4482 if (!CTK_RBNODE_FLAG_SET (start_node, CTK_RBNODE_IS_SELECTED)(start_node?(((start_node->flags&CTK_RBNODE_IS_SELECTED
)==CTK_RBNODE_IS_SELECTED)?(!(0)):(0)):(0))
)
42
Taking false branch
43
'?' condition is false
44
Taking true branch
4483 {
4484 CtkTreePath *path;
4485 gboolean selectable;
4486
4487 path = _ctk_tree_path_new_from_rbtree (start_tree, start_node);
4488 selectable = _ctk_tree_selection_row_is_selectable (tree_view->priv->selection, start_node, path);
4489 ctk_tree_path_free (path);
4490
4491 if (!selectable)
45
Assuming 'selectable' is 0
46
Taking true branch
4492 goto node_not_selectable;
47
Control jumps to line 4530
4493 }
4494
4495 if (select)
4496 {
4497 if (tree_view->priv->rubber_band_extend)
4498 CTK_RBNODE_SET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags|=CTK_RBNODE_IS_SELECTED); }while (0
)
;
4499 else if (tree_view->priv->rubber_band_modify)
4500 {
4501 /* Toggle the selection state */
4502 if (CTK_RBNODE_FLAG_SET (start_node, CTK_RBNODE_IS_SELECTED)(start_node?(((start_node->flags&CTK_RBNODE_IS_SELECTED
)==CTK_RBNODE_IS_SELECTED)?(!(0)):(0)):(0))
)
4503 CTK_RBNODE_UNSET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags&=~(CTK_RBNODE_IS_SELECTED)); }while
(0)
;
4504 else
4505 CTK_RBNODE_SET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags|=CTK_RBNODE_IS_SELECTED); }while (0
)
;
4506 }
4507 else
4508 CTK_RBNODE_SET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags|=CTK_RBNODE_IS_SELECTED); }while (0
)
;
4509 }
4510 else
4511 {
4512 /* Mirror the above */
4513 if (tree_view->priv->rubber_band_extend)
4514 CTK_RBNODE_UNSET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags&=~(CTK_RBNODE_IS_SELECTED)); }while
(0)
;
4515 else if (tree_view->priv->rubber_band_modify)
4516 {
4517 /* Toggle the selection state */
4518 if (CTK_RBNODE_FLAG_SET (start_node, CTK_RBNODE_IS_SELECTED)(start_node?(((start_node->flags&CTK_RBNODE_IS_SELECTED
)==CTK_RBNODE_IS_SELECTED)?(!(0)):(0)):(0))
)
4519 CTK_RBNODE_UNSET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags&=~(CTK_RBNODE_IS_SELECTED)); }while
(0)
;
4520 else
4521 CTK_RBNODE_SET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags|=CTK_RBNODE_IS_SELECTED); }while (0
)
;
4522 }
4523 else
4524 CTK_RBNODE_UNSET_FLAG (start_node, CTK_RBNODE_IS_SELECTED)do{ (start_node->flags&=~(CTK_RBNODE_IS_SELECTED)); }while
(0)
;
4525 }
4526
4527 _ctk_tree_view_queue_draw_node (tree_view, start_tree, start_node, NULL((void*)0));
4528
4529node_not_selectable:
4530 if (start_node
47.1
'start_node' is not equal to 'end_node'
== end_node)
48
Taking false branch
4531 break;
4532
4533skip_first:
4534
4535 if (start_node->children)
49
Access to field 'children' results in a dereference of a null pointer (loaded from variable 'start_node')
4536 {
4537 start_tree = start_node->children;
4538 start_node = _ctk_rbtree_first (start_tree);
4539 }
4540 else
4541 {
4542 _ctk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
4543
4544 if (!start_tree)
4545 /* Ran out of tree */
4546 break;
4547 }
4548
4549 if (skip_end && start_node == end_node)
4550 break;
4551 }
4552 while (TRUE(!(0)));
4553}
4554
4555static void
4556ctk_tree_view_update_rubber_band_selection (CtkTreeView *tree_view)
4557{
4558 CtkRBTree *start_tree, *end_tree;
4559 CtkRBNode *start_node, *end_node;
4560 gdouble start_y, offset_y;
4561 gint bin_y;
4562
4563 if (!ctk_gesture_is_active (tree_view->priv->drag_gesture))
27
Assuming the condition is false
28
Taking false branch
4564 return;
4565
4566 ctk_gesture_drag_get_offset (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
4567 NULL((void*)0), &offset_y);
4568 ctk_gesture_drag_get_start_point (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
4569 NULL((void*)0), &start_y);
4570 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, 0, start_y,
4571 NULL((void*)0), &bin_y);
4572 bin_y = MAX (0, bin_y + offset_y + tree_view->priv->dy)(((0) > (bin_y + offset_y + tree_view->priv->dy)) ? (
0) : (bin_y + offset_y + tree_view->priv->dy))
;
29
Assuming the condition is true
30
'?' condition is true
4573
4574 _ctk_rbtree_find_offset (tree_view->priv->tree, MIN (tree_view->priv->press_start_y, bin_y)(((tree_view->priv->press_start_y) < (bin_y)) ? (tree_view
->priv->press_start_y) : (bin_y))
, &start_tree, &start_node)
;
31
Assuming 'bin_y' is <= field 'press_start_y'
32
'?' condition is false
33
Value assigned to 'start_node'
4575 _ctk_rbtree_find_offset (tree_view->priv->tree, MAX (tree_view->priv->press_start_y, bin_y)(((tree_view->priv->press_start_y) > (bin_y)) ? (tree_view
->priv->press_start_y) : (bin_y))
, &end_tree, &end_node);
34
Assuming 'bin_y' is >= field 'press_start_y'
35
'?' condition is false
4576
4577 /* Handle the start area first */
4578 if (!start_node && !end_node)
36
Assuming 'start_node' is null
37
Assuming 'end_node' is non-null
4579 {
4580 if (tree_view->priv->rubber_band_start_node)
4581 {
4582 CtkRBNode *node = tree_view->priv->rubber_band_start_node;
4583 CtkRBTree *tree = tree_view->priv->rubber_band_start_tree;
4584
4585 if (tree_view->priv->rubber_band_modify)
4586 {
4587 /* Toggle the selection state */
4588 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
4589 CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_IS_SELECTED)do{ (node->flags&=~(CTK_RBNODE_IS_SELECTED)); }while (
0)
;
4590 else
4591 CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_IS_SELECTED)do{ (node->flags|=CTK_RBNODE_IS_SELECTED); }while (0);
4592 }
4593 else
4594 CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_IS_SELECTED)do{ (node->flags&=~(CTK_RBNODE_IS_SELECTED)); }while (
0)
;
4595
4596 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
4597 }
4598 }
4599 if (!tree_view->priv->rubber_band_start_node || !start_node)
38
Assuming field 'rubber_band_start_node' is null
4600 {
4601 ctk_tree_view_update_rubber_band_selection_range (tree_view,
40
Calling 'ctk_tree_view_update_rubber_band_selection_range'
4602 start_tree,
4603 start_node,
39
Passing null pointer value via 3rd parameter 'start_node'
4604 end_tree,
4605 end_node,
4606 TRUE(!(0)),
4607 FALSE(0),
4608 FALSE(0));
4609 }
4610 else if (_ctk_rbtree_node_find_offset (start_tree, start_node) <
4611 _ctk_rbtree_node_find_offset (tree_view->priv->rubber_band_start_tree, tree_view->priv->rubber_band_start_node))
4612 {
4613 /* New node is above the old one; selection became bigger */
4614 ctk_tree_view_update_rubber_band_selection_range (tree_view,
4615 start_tree,
4616 start_node,
4617 tree_view->priv->rubber_band_start_tree,
4618 tree_view->priv->rubber_band_start_node,
4619 TRUE(!(0)),
4620 FALSE(0),
4621 TRUE(!(0)));
4622 }
4623 else if (_ctk_rbtree_node_find_offset (start_tree, start_node) >
4624 _ctk_rbtree_node_find_offset (tree_view->priv->rubber_band_start_tree, tree_view->priv->rubber_band_start_node))
4625 {
4626 /* New node is below the old one; selection became smaller */
4627 ctk_tree_view_update_rubber_band_selection_range (tree_view,
4628 tree_view->priv->rubber_band_start_tree,
4629 tree_view->priv->rubber_band_start_node,
4630 start_tree,
4631 start_node,
4632 FALSE(0),
4633 FALSE(0),
4634 TRUE(!(0)));
4635 }
4636
4637 tree_view->priv->rubber_band_start_tree = start_tree;
4638 tree_view->priv->rubber_band_start_node = start_node;
4639
4640 /* Next, handle the end area */
4641 if (!tree_view->priv->rubber_band_end_node)
4642 {
4643 /* In the event this happens, start_node was also NULL; this case is
4644 * handled above.
4645 */
4646 }
4647 else if (!end_node)
4648 {
4649 /* Find the last node in the tree */
4650 _ctk_rbtree_find_offset (tree_view->priv->tree, ctk_tree_view_get_height (tree_view) - 1,
4651 &end_tree, &end_node);
4652
4653 /* Selection reached end of the tree */
4654 ctk_tree_view_update_rubber_band_selection_range (tree_view,
4655 tree_view->priv->rubber_band_end_tree,
4656 tree_view->priv->rubber_band_end_node,
4657 end_tree,
4658 end_node,
4659 TRUE(!(0)),
4660 TRUE(!(0)),
4661 FALSE(0));
4662 }
4663 else if (_ctk_rbtree_node_find_offset (end_tree, end_node) >
4664 _ctk_rbtree_node_find_offset (tree_view->priv->rubber_band_end_tree, tree_view->priv->rubber_band_end_node))
4665 {
4666 /* New node is below the old one; selection became bigger */
4667 ctk_tree_view_update_rubber_band_selection_range (tree_view,
4668 tree_view->priv->rubber_band_end_tree,
4669 tree_view->priv->rubber_band_end_node,
4670 end_tree,
4671 end_node,
4672 TRUE(!(0)),
4673 TRUE(!(0)),
4674 FALSE(0));
4675 }
4676 else if (_ctk_rbtree_node_find_offset (end_tree, end_node) <
4677 _ctk_rbtree_node_find_offset (tree_view->priv->rubber_band_end_tree, tree_view->priv->rubber_band_end_node))
4678 {
4679 /* New node is above the old one; selection became smaller */
4680 ctk_tree_view_update_rubber_band_selection_range (tree_view,
4681 end_tree,
4682 end_node,
4683 tree_view->priv->rubber_band_end_tree,
4684 tree_view->priv->rubber_band_end_node,
4685 FALSE(0),
4686 TRUE(!(0)),
4687 FALSE(0));
4688 }
4689
4690 tree_view->priv->rubber_band_end_tree = end_tree;
4691 tree_view->priv->rubber_band_end_node = end_node;
4692}
4693
4694static void
4695ctk_tree_view_update_rubber_band (CtkTreeView *tree_view)
4696{
4697 gdouble start_x, start_y, offset_x, offset_y, x, y;
4698 CdkRectangle old_area;
4699 CdkRectangle new_area;
4700 cairo_region_t *invalid_region;
4701 gint bin_x, bin_y;
4702
4703 if (!ctk_gesture_is_recognized (tree_view->priv->drag_gesture))
4
Assuming the condition is false
4704 return;
4705
4706 old_area.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x)(((tree_view->priv->press_start_x) < (tree_view->
priv->rubber_band_x)) ? (tree_view->priv->press_start_x
) : (tree_view->priv->rubber_band_x))
;
5
Taking false branch
6
Assuming field 'press_start_x' is >= field 'rubber_band_x'
7
'?' condition is false
4707 old_area.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y)(((tree_view->priv->press_start_y) < (tree_view->
priv->rubber_band_y)) ? (tree_view->priv->press_start_y
) : (tree_view->priv->rubber_band_y))
- tree_view->priv->dy;
8
Assuming field 'press_start_y' is >= field 'rubber_band_y'
9
'?' condition is false
4708 old_area.width = ABS (tree_view->priv->rubber_band_x - tree_view->priv->press_start_x)(((tree_view->priv->rubber_band_x - tree_view->priv->
press_start_x) < 0) ? -(tree_view->priv->rubber_band_x
- tree_view->priv->press_start_x) : (tree_view->priv
->rubber_band_x - tree_view->priv->press_start_x))
+ 1;
10
Assuming the condition is false
11
'?' condition is false
4709 old_area.height = ABS (tree_view->priv->rubber_band_y - tree_view->priv->press_start_y)(((tree_view->priv->rubber_band_y - tree_view->priv->
press_start_y) < 0) ? -(tree_view->priv->rubber_band_y
- tree_view->priv->press_start_y) : (tree_view->priv
->rubber_band_y - tree_view->priv->press_start_y))
+ 1;
12
Assuming the condition is false
13
'?' condition is false
4710
4711 ctk_gesture_drag_get_offset (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
4712 &offset_x, &offset_y);
4713 ctk_gesture_drag_get_start_point (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
4714 &start_x, &start_y);
4715 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, start_x, start_y,
4716 &bin_x, &bin_y);
4717 bin_y += tree_view->priv->dy;
4718
4719 x = MAX (bin_x + offset_x, 0)(((bin_x + offset_x) > (0)) ? (bin_x + offset_x) : (0));
14
Assuming the condition is false
15
'?' condition is false
4720 y = MAX (bin_y + offset_y, 0)(((bin_y + offset_y) > (0)) ? (bin_y + offset_y) : (0));
16
Assuming the condition is false
17
'?' condition is false
4721
4722 new_area.x = MIN (tree_view->priv->press_start_x, x)(((tree_view->priv->press_start_x) < (x)) ? (tree_view
->priv->press_start_x) : (x))
;
18
Assuming 'x' is <= field 'press_start_x'
19
'?' condition is false
4723 new_area.y = MIN (tree_view->priv->press_start_y, y)(((tree_view->priv->press_start_y) < (y)) ? (tree_view
->priv->press_start_y) : (y))
- tree_view->priv->dy;
20
Assuming 'y' is <= field 'press_start_y'
21
'?' condition is false
4724 new_area.width = ABS (x - tree_view->priv->press_start_x)(((x - tree_view->priv->press_start_x) < 0) ? -(x - tree_view
->priv->press_start_x) : (x - tree_view->priv->press_start_x
))
+ 1;
22
Assuming the condition is false
23
'?' condition is false
4725 new_area.height = ABS (y - tree_view->priv->press_start_y)(((y - tree_view->priv->press_start_y) < 0) ? -(y - tree_view
->priv->press_start_y) : (y - tree_view->priv->press_start_y
))
+ 1;
24
Assuming the condition is false
25
'?' condition is false
4726
4727 invalid_region = cairo_region_create_rectangle (&old_area);
4728 cairo_region_union_rectangle (invalid_region, &new_area);
4729
4730 cdk_window_invalidate_region (tree_view->priv->bin_window, invalid_region, TRUE(!(0)));
4731
4732 cairo_region_destroy (invalid_region);
4733
4734 tree_view->priv->rubber_band_x = x;
4735 tree_view->priv->rubber_band_y = y;
4736
4737 ctk_tree_view_update_rubber_band_selection (tree_view);
26
Calling 'ctk_tree_view_update_rubber_band_selection'
4738}
4739
4740static void
4741ctk_tree_view_paint_rubber_band (CtkTreeView *tree_view,
4742 cairo_t *cr)
4743{
4744 gdouble start_x, start_y, offset_x, offset_y;
4745 CdkRectangle rect;
4746 CtkStyleContext *context;
4747 gint bin_x, bin_y;
4748
4749 if (!ctk_gesture_is_recognized (tree_view->priv->drag_gesture))
4750 return;
4751
4752 ctk_gesture_drag_get_offset (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
4753 &offset_x, &offset_y);
4754 ctk_gesture_drag_get_start_point (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
4755 &start_x, &start_y);
4756 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, start_x, start_y,
4757 &bin_x, &bin_y);
4758 bin_x = MAX (0, bin_x + offset_x)(((0) > (bin_x + offset_x)) ? (0) : (bin_x + offset_x));
4759 bin_y = MAX (0, bin_y + offset_y + tree_view->priv->dy)(((0) > (bin_y + offset_y + tree_view->priv->dy)) ? (
0) : (bin_y + offset_y + tree_view->priv->dy))
;
4760
4761 cairo_save (cr);
4762
4763 context = ctk_widget_get_style_context (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
4764
4765 ctk_style_context_save_to_node (context, tree_view->priv->rubber_band_cssnode);
4766
4767 rect.x = MIN (tree_view->priv->press_start_x, bin_x)(((tree_view->priv->press_start_x) < (bin_x)) ? (tree_view
->priv->press_start_x) : (bin_x))
;
4768 rect.y = MIN (tree_view->priv->press_start_y, bin_y)(((tree_view->priv->press_start_y) < (bin_y)) ? (tree_view
->priv->press_start_y) : (bin_y))
- tree_view->priv->dy;
4769 rect.width = ABS (tree_view->priv->press_start_x - bin_x)(((tree_view->priv->press_start_x - bin_x) < 0) ? -(
tree_view->priv->press_start_x - bin_x) : (tree_view->
priv->press_start_x - bin_x))
+ 1;
4770 rect.height = ABS (tree_view->priv->press_start_y - bin_y)(((tree_view->priv->press_start_y - bin_y) < 0) ? -(
tree_view->priv->press_start_y - bin_y) : (tree_view->
priv->press_start_y - bin_y))
+ 1;
4771
4772 cdk_cairo_rectangle (cr, &rect);
4773 cairo_clip (cr);
4774
4775 ctk_render_background (context, cr,
4776 rect.x, rect.y,
4777 rect.width, rect.height);
4778 ctk_render_frame (context, cr,
4779 rect.x, rect.y,
4780 rect.width, rect.height);
4781
4782 ctk_style_context_restore (context);
4783 cairo_restore (cr);
4784}
4785
4786static void
4787ctk_tree_view_column_drag_gesture_update (CtkGestureDrag *gesture,
4788 gdouble offset_x,
4789 gdouble offset_y,
4790 CtkTreeView *tree_view)
4791{
4792 gdouble start_x, start_y, x, y;
4793 CdkEventSequence *sequence;
4794
4795 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
4796
4797 if (ctk_gesture_get_sequence_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence) != CTK_EVENT_SEQUENCE_CLAIMED)
4798 return;
4799
4800 ctk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
4801 x = start_x + offset_x;
4802 y = start_y + offset_y;
4803
4804 if (tree_view->priv->in_column_resize)
4805 ctk_tree_view_motion_resize_column (tree_view, x, y);
4806 else if (tree_view->priv->in_column_drag)
4807 ctk_tree_view_motion_drag_column (tree_view, x, y);
4808}
4809
4810static void
4811ctk_tree_view_drag_gesture_update (CtkGestureDrag *gesture,
4812 gdouble offset_x G_GNUC_UNUSED__attribute__ ((__unused__)),
4813 gdouble offset_y G_GNUC_UNUSED__attribute__ ((__unused__)),
4814 CtkTreeView *tree_view)
4815{
4816 if (tree_view->priv->tree == NULL((void*)0))
4817 {
4818 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
4819 return;
4820 }
4821
4822 if (tree_view->priv->rubber_band_status == RUBBER_BAND_MAYBE_START)
4823 {
4824 CtkCssNode *widget_node;
4825
4826 widget_node = ctk_widget_get_css_node (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
4827 tree_view->priv->rubber_band_cssnode = ctk_css_node_new ();
4828 ctk_css_node_set_name (tree_view->priv->rubber_band_cssnode, I_("rubberband")g_intern_static_string ("rubberband"));
4829 ctk_css_node_set_parent (tree_view->priv->rubber_band_cssnode, widget_node);
4830 ctk_css_node_set_state (tree_view->priv->rubber_band_cssnode, ctk_css_node_get_state (widget_node));
4831 g_object_unref (tree_view->priv->rubber_band_cssnode);
4832
4833 ctk_tree_view_update_rubber_band (tree_view);
4834
4835 tree_view->priv->rubber_band_status = RUBBER_BAND_ACTIVE;
4836 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_CLAIMED);
4837 }
4838 else if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
4839 {
4840 ctk_tree_view_update_rubber_band (tree_view);
4841
4842 add_scroll_timeout (tree_view);
4843 }
4844 else if (!tree_view->priv->rubber_band_status)
4845 {
4846 if (ctk_tree_view_maybe_begin_dragging_row (tree_view))
4847 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
4848 }
4849}
4850
4851static gboolean
4852ctk_tree_view_motion (CtkWidget *widget,
4853 CdkEventMotion *event)
4854{
4855 CtkTreeView *tree_view;
4856 CtkRBTree *tree;
4857 CtkRBNode *node;
4858 gint new_y;
4859
4860 tree_view = (CtkTreeView *) widget;
4861
4862 if (tree_view->priv->tree)
4863 {
4864 /* If we are currently pressing down a button, we don't want to prelight anything else. */
4865 if (ctk_gesture_is_active (tree_view->priv->drag_gesture) ||
4866 ctk_gesture_is_active (tree_view->priv->multipress_gesture))
4867 node = NULL((void*)0);
4868
4869 new_y = MAX (0, TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->y))(((0) > (((event->y) + tree_view->priv->dy))) ? (
0) : (((event->y) + tree_view->priv->dy)))
;
4870
4871 _ctk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
4872
4873 tree_view->priv->event_last_x = event->x;
4874 tree_view->priv->event_last_y = event->y;
4875 prelight_or_select (tree_view, tree, node, event->x, event->y);
4876 }
4877
4878 return CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->motion_notify_event (widget, event);
4879}
4880
4881/* Invalidate the focus rectangle near the edge of the bin_window; used when
4882 * the tree is empty.
4883 */
4884static void
4885invalidate_empty_focus (CtkTreeView *tree_view)
4886{
4887 CdkRectangle area;
4888
4889 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
4890 return;
4891
4892 area.x = 0;
4893 area.y = 0;
4894 area.width = cdk_window_get_width (tree_view->priv->bin_window);
4895 area.height = cdk_window_get_height (tree_view->priv->bin_window);
4896 cdk_window_invalidate_rect (tree_view->priv->bin_window, &area, FALSE(0));
4897}
4898
4899/* Draws background and a focus rectangle near the edge of the bin_window;
4900 * used when the tree is empty.
4901 */
4902static void
4903draw_empty (CtkTreeView *tree_view,
4904 cairo_t *cr)
4905{
4906 CtkWidget *widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
4907 CtkStyleContext *context;
4908 gint width, height;
4909
4910 context = ctk_widget_get_style_context (widget);
4911
4912 width = cdk_window_get_width (tree_view->priv->bin_window);
4913 height = cdk_window_get_height (tree_view->priv->bin_window);
4914
4915 ctk_render_background (context, cr, 0, 0, width, height);
4916
4917 if (ctk_widget_has_visible_focus (widget))
4918 ctk_render_focus (context, cr, 0, 0, width, height);
4919}
4920
4921typedef enum {
4922 CTK_TREE_VIEW_GRID_LINE,
4923 CTK_TREE_VIEW_TREE_LINE,
4924 CTK_TREE_VIEW_FOREGROUND_LINE
4925} CtkTreeViewLineType;
4926
4927static void
4928ctk_tree_view_draw_line (CtkTreeView *tree_view,
4929 cairo_t *cr,
4930 CtkTreeViewLineType type,
4931 int x1,
4932 int y1,
4933 int x2,
4934 int y2)
4935{
4936 CtkStyleContext *context;
4937
4938 cairo_save (cr);
4939
4940 context = ctk_widget_get_style_context (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
4941
4942 switch (type)
4943 {
4944 case CTK_TREE_VIEW_TREE_LINE:
4945 {
4946 const CdkRGBA *color;
4947
4948 color = _ctk_css_rgba_value_get_rgba (_ctk_style_context_peek_property (context, CTK_CSS_PROPERTY_BORDER_LEFT_COLOR));
4949
4950 cdk_cairo_set_source_rgba (cr, color);
4951 cairo_set_line_width (cr, tree_view->priv->tree_line_width);
4952 if (tree_view->priv->tree_line_dashes[0])
4953 cairo_set_dash (cr, tree_view->priv->tree_line_dashes, 2, 0.5);
4954 }
4955 break;
4956
4957 case CTK_TREE_VIEW_GRID_LINE:
4958 {
4959 const CdkRGBA *color;
4960
4961 color = _ctk_css_rgba_value_get_rgba (_ctk_style_context_peek_property (context, CTK_CSS_PROPERTY_BORDER_TOP_COLOR));
4962
4963 cdk_cairo_set_source_rgba (cr, color);
4964 cairo_set_line_width (cr, tree_view->priv->grid_line_width);
4965 if (tree_view->priv->grid_line_dashes[0])
4966 cairo_set_dash (cr, tree_view->priv->grid_line_dashes, 2, 0.5);
4967 }
4968 break;
4969
4970 case CTK_TREE_VIEW_FOREGROUND_LINE:
4971 {
4972 CdkRGBA color;
4973
4974 cairo_set_line_width (cr, 1.0);
4975 ctk_style_context_get_color (context, ctk_style_context_get_state (context), &color);
4976 cdk_cairo_set_source_rgba (cr, &color);
4977 }
4978 break;
4979
4980 default:
4981 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktreeview.c", 4981, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
4982 break;
4983 }
4984
4985 cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
4986 cairo_line_to (cr, x2 + 0.5, y2 + 0.5);
4987 cairo_stroke (cr);
4988
4989 cairo_restore (cr);
4990}
4991
4992static void
4993ctk_tree_view_draw_grid_lines (CtkTreeView *tree_view,
4994 cairo_t *cr)
4995{
4996 GList *list, *first, *last;
4997 gboolean rtl;
4998 gint current_x = 0;
4999
5000 if (tree_view->priv->grid_lines != CTK_TREE_VIEW_GRID_LINES_VERTICAL
5001 && tree_view->priv->grid_lines != CTK_TREE_VIEW_GRID_LINES_BOTH)
5002 return;
5003
5004 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
5005
5006 first = g_list_first (tree_view->priv->columns);
5007 last = g_list_last (tree_view->priv->columns);
5008
5009 for (list = (rtl ? last : first);
5010 list;
5011 list = (rtl ? list->prev : list->next))
5012 {
5013 CtkTreeViewColumn *column = list->data;
5014
5015 /* We don't want a line for the last column */
5016 if (column == (rtl ? first->data : last->data))
5017 break;
5018
5019 if (!ctk_tree_view_column_get_visible (column))
5020 continue;
5021
5022 current_x += ctk_tree_view_column_get_width (column);
5023
5024 ctk_tree_view_draw_line (tree_view, cr,
5025 CTK_TREE_VIEW_GRID_LINE,
5026 current_x - 1, 0,
5027 current_x - 1, ctk_tree_view_get_height (tree_view));
5028 }
5029}
5030
5031/* Warning: Very scary function.
5032 * Modify at your own risk
5033 *
5034 * KEEP IN SYNC WITH ctk_tree_view_create_row_drag_icon()!
5035 * FIXME: It’s not...
5036 */
5037static gboolean
5038ctk_tree_view_bin_draw (CtkWidget *widget,
5039 cairo_t *cr)
5040{
5041 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
5042 CtkTreePath *path;
5043 CtkRBTree *tree;
5044 GList *list;
5045 CtkRBNode *node;
5046 CtkRBNode *drag_highlight = NULL((void*)0);
5047 CtkRBTree *drag_highlight_tree = NULL((void*)0);
5048 CtkTreeIter iter;
5049 gint new_y;
5050 gint y_offset, cell_offset;
5051 gint max_height;
5052 gint depth;
5053 CdkRectangle background_area;
5054 CdkRectangle cell_area;
5055 CdkRectangle clip;
5056 guint flags;
5057 gint bin_window_width;
5058 gint bin_window_height;
5059 CtkTreePath *drag_dest_path = NULL((void*)0);
5060 GList *first_column, *last_column;
5061 gint vertical_separator;
5062 gint horizontal_separator;
5063 gboolean allow_rules;
5064 gboolean has_can_focus_cell;
5065 gboolean rtl;
5066 gint n_visible_columns;
5067 gint grid_line_width;
5068 gint expander_size;
5069 gboolean draw_vgrid_lines, draw_hgrid_lines;
5070 CtkStyleContext *context;
5071 gboolean parity;
5072
5073 rtl = (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
5074 context = ctk_widget_get_style_context (widget);
5075
5076 ctk_widget_style_get (widget,
5077 "horizontal-separator", &horizontal_separator,
5078 "vertical-separator", &vertical_separator,
5079 "allow-rules", &allow_rules,
5080 NULL((void*)0));
5081
5082 if (tree_view->priv->tree == NULL((void*)0))
5083 {
5084 draw_empty (tree_view, cr);
5085 return TRUE(!(0));
5086 }
5087
5088 bin_window_width = cdk_window_get_width (tree_view->priv->bin_window);
5089 bin_window_height = cdk_window_get_height (tree_view->priv->bin_window);
5090 if (!cdk_cairo_get_clip_rectangle (cr, &clip))
5091 return TRUE(!(0));
5092
5093 new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, clip.y)((clip.y) + tree_view->priv->dy);
5094
5095 if (new_y < 0)
5096 new_y = 0;
5097 y_offset = -_ctk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
5098
5099 if (ctk_tree_view_get_height (tree_view) < bin_window_height)
5100 {
5101 ctk_style_context_save (context);
5102 ctk_style_context_add_class (context, CTK_STYLE_CLASS_CELL"cell");
5103
5104 ctk_render_background (context, cr,
5105 0, ctk_tree_view_get_height (tree_view),
5106 bin_window_width,
5107 bin_window_height - ctk_tree_view_get_height (tree_view));
5108
5109 ctk_style_context_restore (context);
5110 }
5111
5112 if (node == NULL((void*)0))
5113 goto done;
5114
5115 /* find the path for the node */
5116 path = _ctk_tree_path_new_from_rbtree (tree, node);
5117 ctk_tree_model_get_iter (tree_view->priv->model,
5118 &iter,
5119 path);
5120 depth = ctk_tree_path_get_depth (path);
5121 ctk_tree_path_free (path);
5122
5123 if (tree_view->priv->drag_dest_row)
5124 drag_dest_path = ctk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
5125
5126 if (drag_dest_path)
5127 _ctk_tree_view_find_node (tree_view, drag_dest_path,
5128 &drag_highlight_tree, &drag_highlight);
5129
5130 draw_vgrid_lines =
5131 tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_VERTICAL
5132 || tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_BOTH;
5133 draw_hgrid_lines =
5134 tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_HORIZONTAL
5135 || tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_BOTH;
5136 expander_size = ctk_tree_view_get_expander_size (tree_view);
5137
5138 if (draw_vgrid_lines || draw_hgrid_lines)
5139 ctk_widget_style_get (widget, "grid-line-width", &grid_line_width, NULL((void*)0));
5140
5141 n_visible_columns = 0;
5142 for (list = tree_view->priv->columns; list; list = list->next)
5143 {
5144 if (!ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
))
5145 continue;
5146 n_visible_columns ++;
5147 }
5148
5149 /* Find the last column */
5150 for (last_column = g_list_last (tree_view->priv->columns);
5151 last_column &&
5152 !(ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (last_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((last_column->data)), ((ctk_tree_view_column_get_type
()))))))
));
5153 last_column = last_column->prev)
5154 ;
5155
5156 /* and the first */
5157 for (first_column = g_list_first (tree_view->priv->columns);
5158 first_column &&
5159 !(ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (first_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((first_column->data)), ((ctk_tree_view_column_get_type
()))))))
));
5160 first_column = first_column->next)
5161 ;
5162
5163 /* Actually process the expose event. To do this, we want to
5164 * start at the first node of the event, and walk the tree in
5165 * order, drawing each successive node.
5166 */
5167
5168 parity = !(_ctk_rbtree_node_get_index (tree, node) % 2);
5169
5170 do
5171 {
5172 gboolean is_separator = FALSE(0);
5173 gint n_col = 0;
5174
5175 parity = !parity;
5176 is_separator = row_is_separator (tree_view, &iter, NULL((void*)0));
5177
5178 max_height = ctk_tree_view_get_row_height (tree_view, node);
5179
5180 cell_offset = 0;
5181
5182 background_area.y = y_offset + clip.y;
5183 background_area.height = max_height;
5184
5185 flags = 0;
5186
5187 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PRELIT)(node?(((node->flags&CTK_RBNODE_IS_PRELIT)==CTK_RBNODE_IS_PRELIT
)?(!(0)):(0)):(0))
)
5188 flags |= CTK_CELL_RENDERER_PRELIT;
5189
5190 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
5191 flags |= CTK_CELL_RENDERER_SELECTED;
5192
5193 /* we *need* to set cell data on all cells before the call
5194 * to _has_can_focus_cell, else _has_can_focus_cell() does not
5195 * return a correct value.
5196 */
5197 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
5198 list;
5199 list = (rtl ? list->prev : list->next))
5200 {
5201 CtkTreeViewColumn *column = list->data;
5202 ctk_tree_view_column_cell_set_cell_data (column,
5203 tree_view->priv->model,
5204 &iter,
5205 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
5206 node->children?TRUE(!(0)):FALSE(0));
5207 }
5208
5209 has_can_focus_cell = ctk_tree_view_has_can_focus_cell (tree_view);
5210
5211 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
5212 list;
5213 list = (rtl ? list->prev : list->next))
5214 {
5215 CtkTreeViewColumn *column = list->data;
5216 CtkStateFlags state = 0;
5217 gint width;
5218 gboolean draw_focus;
5219
5220 if (!ctk_tree_view_column_get_visible (column))
5221 continue;
5222
5223 n_col++;
5224 width = ctk_tree_view_column_get_width (column);
5225
5226 if (cell_offset > clip.x + clip.width ||
5227 cell_offset + width < clip.x)
5228 {
5229 cell_offset += width;
5230 continue;
5231 }
5232
5233 if (ctk_tree_view_column_get_sort_indicator (column))
5234 flags |= CTK_CELL_RENDERER_SORTED;
5235 else
5236 flags &= ~CTK_CELL_RENDERER_SORTED;
5237
5238 if (tree_view->priv->cursor_node == node)
5239 flags |= CTK_CELL_RENDERER_FOCUSED;
5240 else
5241 flags &= ~CTK_CELL_RENDERER_FOCUSED;
5242
5243 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
)
5244 flags |= CTK_CELL_RENDERER_EXPANDABLE;
5245 else
5246 flags &= ~CTK_CELL_RENDERER_EXPANDABLE;
5247
5248 if (node->children)
5249 flags |= CTK_CELL_RENDERER_EXPANDED;
5250 else
5251 flags &= ~CTK_CELL_RENDERER_EXPANDED;
5252
5253 background_area.x = cell_offset;
5254 background_area.width = width;
5255
5256 cell_area = background_area;
5257 cell_area.y += vertical_separator / 2;
5258 cell_area.x += horizontal_separator / 2;
5259 cell_area.height -= vertical_separator;
5260 cell_area.width -= horizontal_separator;
5261
5262 if (draw_vgrid_lines)
5263 {
5264 if (list == first_column)
5265 {
5266 cell_area.width -= grid_line_width / 2;
5267 }
5268 else if (list == last_column)
5269 {
5270 cell_area.x += grid_line_width / 2;
5271 cell_area.width -= grid_line_width / 2;
5272 }
5273 else
5274 {
5275 cell_area.x += grid_line_width / 2;
5276 cell_area.width -= grid_line_width;
5277 }
5278 }
5279
5280 if (draw_hgrid_lines)
5281 {
5282 cell_area.y += grid_line_width / 2;
5283 cell_area.height -= grid_line_width;
5284 }
5285
5286 if (!cdk_rectangle_intersect (&clip, &background_area, NULL((void*)0)))
5287 {
5288 cell_offset += ctk_tree_view_column_get_width (column);
5289 continue;
5290 }
5291
5292 ctk_tree_view_column_cell_set_cell_data (column,
5293 tree_view->priv->model,
5294 &iter,
5295 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
5296 node->children?TRUE(!(0)):FALSE(0));
5297
5298 ctk_style_context_save (context);
5299
5300 state = ctk_cell_renderer_get_state (NULL((void*)0), widget, flags);
5301 ctk_style_context_set_state (context, state);
5302
5303 ctk_style_context_add_class (context, CTK_STYLE_CLASS_CELL"cell");
5304
5305 if (node == tree_view->priv->cursor_node && has_can_focus_cell
5306 && ((column == tree_view->priv->focus_column
5307 && tree_view->priv->draw_keyfocus &&
5308 ctk_widget_has_visible_focus (widget))
5309 || (column == tree_view->priv->edited_column)))
5310 draw_focus = TRUE(!(0));
5311 else
5312 draw_focus = FALSE(0);
5313
5314 /* Draw background */
5315 ctk_render_background (context, cr,
5316 background_area.x,
5317 background_area.y,
5318 background_area.width,
5319 background_area.height);
5320
5321 /* Draw frame */
5322 ctk_render_frame (context, cr,
5323 background_area.x,
5324 background_area.y,
5325 background_area.width,
5326 background_area.height);
5327
5328 if (ctk_tree_view_is_expander_column (tree_view, column))
5329 {
5330 if (!rtl)
5331 cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
5332 cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
5333
5334 if (ctk_tree_view_draw_expanders (tree_view))
5335 {
5336 if (!rtl)
5337 cell_area.x += depth * expander_size;
5338 cell_area.width -= depth * expander_size;
5339 }
5340
5341 if (is_separator)
5342 {
5343 ctk_style_context_save (context);
5344 ctk_style_context_add_class (context, CTK_STYLE_CLASS_SEPARATOR"separator");
5345
5346 ctk_render_line (context, cr,
5347 cell_area.x,
5348 cell_area.y + cell_area.height / 2,
5349 cell_area.x + cell_area.width,
5350 cell_area.y + cell_area.height / 2);
5351
5352 ctk_style_context_restore (context);
5353 }
5354 else
5355 {
5356 _ctk_tree_view_column_cell_render (column,
5357 cr,
5358 &background_area,
5359 &cell_area,
5360 flags,
5361 draw_focus);
5362 }
5363
5364 if (ctk_tree_view_draw_expanders (tree_view)
5365 && (node->flags & CTK_RBNODE_IS_PARENT) == CTK_RBNODE_IS_PARENT)
5366 {
5367 ctk_tree_view_draw_arrow (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
,
5368 cr,
5369 tree,
5370 node);
5371 }
5372 }
5373 else
5374 {
5375 if (is_separator)
5376 {
5377 ctk_style_context_save (context);
5378 ctk_style_context_add_class (context, CTK_STYLE_CLASS_SEPARATOR"separator");
5379
5380 ctk_render_line (context, cr,
5381 cell_area.x,
5382 cell_area.y + cell_area.height / 2,
5383 cell_area.x + cell_area.width,
5384 cell_area.y + cell_area.height / 2);
5385
5386 ctk_style_context_restore (context);
5387 }
5388 else
5389 _ctk_tree_view_column_cell_render (column,
5390 cr,
5391 &background_area,
5392 &cell_area,
5393 flags,
5394 draw_focus);
5395 }
5396
5397 if (draw_hgrid_lines)
5398 {
5399 if (background_area.y >= clip.y)
5400 ctk_tree_view_draw_line (tree_view, cr,
5401 CTK_TREE_VIEW_GRID_LINE,
5402 background_area.x, background_area.y,
5403 background_area.x + background_area.width,
5404 background_area.y);
5405
5406 if (background_area.y + max_height < clip.y + clip.height)
5407 ctk_tree_view_draw_line (tree_view, cr,
5408 CTK_TREE_VIEW_GRID_LINE,
5409 background_area.x, background_area.y + max_height,
5410 background_area.x + background_area.width,
5411 background_area.y + max_height);
5412 }
5413
5414 if (ctk_tree_view_is_expander_column (tree_view, column) &&
5415 tree_view->priv->tree_lines_enabled)
5416 {
5417 gint x = background_area.x;
5418 gint mult = rtl ? -1 : 1;
5419 gint y0 = background_area.y;
5420 gint y1 = background_area.y + background_area.height/2;
5421 gint y2 = background_area.y + background_area.height;
5422
5423 if (rtl)
5424 x += background_area.width - 1;
5425
5426 if ((node->flags & CTK_RBNODE_IS_PARENT) == CTK_RBNODE_IS_PARENT
5427 && depth > 1)
5428 {
5429 ctk_tree_view_draw_line (tree_view, cr,
5430 CTK_TREE_VIEW_TREE_LINE,
5431 x + expander_size * (depth - 1.5) * mult,
5432 y1,
5433 x + expander_size * (depth - 1.1) * mult,
5434 y1);
5435 }
5436 else if (depth > 1)
5437 {
5438 ctk_tree_view_draw_line (tree_view, cr,
5439 CTK_TREE_VIEW_TREE_LINE,
5440 x + expander_size * (depth - 1.5) * mult,
5441 y1,
5442 x + expander_size * (depth - 0.5) * mult,
5443 y1);
5444 }
5445
5446 if (depth > 1)
5447 {
5448 gint i;
5449 CtkRBNode *tmp_node;
5450 CtkRBTree *tmp_tree;
5451
5452 if (!_ctk_rbtree_next (tree, node))
5453 ctk_tree_view_draw_line (tree_view, cr,
5454 CTK_TREE_VIEW_TREE_LINE,
5455 x + expander_size * (depth - 1.5) * mult,
5456 y0,
5457 x + expander_size * (depth - 1.5) * mult,
5458 y1);
5459 else
5460 ctk_tree_view_draw_line (tree_view, cr,
5461 CTK_TREE_VIEW_TREE_LINE,
5462 x + expander_size * (depth - 1.5) * mult,
5463 y0,
5464 x + expander_size * (depth - 1.5) * mult,
5465 y2);
5466
5467 tmp_node = tree->parent_node;
5468 tmp_tree = tree->parent_tree;
5469
5470 for (i = depth - 2; i > 0; i--)
5471 {
5472 if (_ctk_rbtree_next (tmp_tree, tmp_node))
5473 ctk_tree_view_draw_line (tree_view, cr,
5474 CTK_TREE_VIEW_TREE_LINE,
5475 x + expander_size * (i - 0.5) * mult,
5476 y0,
5477 x + expander_size * (i - 0.5) * mult,
5478 y2);
5479
5480 tmp_node = tmp_tree->parent_node;
5481 tmp_tree = tmp_tree->parent_tree;
5482 }
5483 }
5484 }
5485
5486 ctk_style_context_restore (context);
5487 cell_offset += ctk_tree_view_column_get_width (column);
5488 }
5489
5490 if (node == drag_highlight)
5491 {
5492 /* Draw indicator for the drop
5493 */
5494 CtkRBTree *drag_tree = NULL((void*)0);
5495 CtkRBNode *drag_node = NULL((void*)0);
5496
5497 ctk_style_context_save (context);
5498 ctk_style_context_set_state (context, ctk_style_context_get_state (context) | CTK_STATE_FLAG_DROP_ACTIVE);
5499
5500 switch (tree_view->priv->drag_dest_pos)
5501 {
5502 case CTK_TREE_VIEW_DROP_BEFORE:
5503 ctk_style_context_add_class (context, "before");
5504 break;
5505
5506 case CTK_TREE_VIEW_DROP_AFTER:
5507 ctk_style_context_add_class (context, "after");
5508 break;
5509
5510 case CTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
5511 case CTK_TREE_VIEW_DROP_INTO_OR_AFTER:
5512 ctk_style_context_add_class (context, "into");
5513 break;
5514 }
5515
5516 _ctk_tree_view_find_node (tree_view, drag_dest_path, &drag_tree, &drag_node);
5517 if (drag_tree != NULL((void*)0))
5518 ctk_render_frame (context, cr,
5519 0, ctk_tree_view_get_row_y_offset (tree_view, drag_tree, drag_node),
5520 cdk_window_get_width (tree_view->priv->bin_window),
5521 ctk_tree_view_get_row_height (tree_view, drag_node));
5522
5523 ctk_style_context_restore (context);
5524 }
5525
5526 /* draw the big row-spanning focus rectangle, if needed */
5527 if (!has_can_focus_cell && node == tree_view->priv->cursor_node &&
5528 tree_view->priv->draw_keyfocus &&
5529 ctk_widget_has_visible_focus (widget))
5530 {
5531 gint tmp_y, tmp_height;
5532 CtkStateFlags focus_rect_state = 0;
5533
5534 ctk_style_context_save (context);
5535
5536 focus_rect_state = ctk_cell_renderer_get_state (NULL((void*)0), widget, flags);
5537 ctk_style_context_set_state (context, focus_rect_state);
5538
5539 if (draw_hgrid_lines)
5540 {
5541 tmp_y = ctk_tree_view_get_row_y_offset (tree_view, tree, node) + grid_line_width / 2;
5542 tmp_height = ctk_tree_view_get_row_height (tree_view, node) - grid_line_width;
5543 }
5544 else
5545 {
5546 tmp_y = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
5547 tmp_height = ctk_tree_view_get_row_height (tree_view, node);
5548 }
5549
5550 ctk_render_focus (context, cr,
5551 0, tmp_y,
5552 cdk_window_get_width (tree_view->priv->bin_window),
5553 tmp_height);
5554
5555 ctk_style_context_restore (context);
5556 }
5557
5558 y_offset += max_height;
5559 if (node->children)
5560 {
5561 CtkTreeIter parent = iter;
5562 gboolean has_child;
5563
5564 tree = node->children;
5565 node = _ctk_rbtree_first (tree);
5566
5567 has_child = ctk_tree_model_iter_children (tree_view->priv->model,
5568 &iter,
5569 &parent);
5570 depth++;
5571
5572 /* Sanity Check! */
5573 TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE)do{ if (!(has_child)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "5573", ((const char*
) (__func__)), "has_child"); return (0); }; }while (0)
;
5574 }
5575 else
5576 {
5577 gboolean done = FALSE(0);
5578
5579 do
5580 {
5581 node = _ctk_rbtree_next (tree, node);
5582 if (node != NULL((void*)0))
5583 {
5584 gboolean has_next = ctk_tree_model_iter_next (tree_view->priv->model, &iter);
5585 done = TRUE(!(0));
5586
5587 /* Sanity Check! */
5588 TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE)do{ if (!(has_next)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "5588", ((const char*
) (__func__)), "has_next"); return (0); }; }while (0)
;
5589 }
5590 else
5591 {
5592 CtkTreeIter parent_iter = iter;
5593 gboolean has_parent;
5594
5595 node = tree->parent_node;
5596 tree = tree->parent_tree;
5597 if (tree == NULL((void*)0))
5598 /* we should go to done to free some memory */
5599 goto done;
5600 has_parent = ctk_tree_model_iter_parent (tree_view->priv->model,
5601 &iter,
5602 &parent_iter);
5603 depth--;
5604
5605 /* Sanity check */
5606 TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE)do{ if (!(has_parent)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "5606", ((const char*
) (__func__)), "has_parent"); return (0); }; }while (0)
;
5607 }
5608 }
5609 while (!done);
5610 }
5611 }
5612 while (y_offset < clip.height);
5613
5614done:
5615 ctk_tree_view_draw_grid_lines (tree_view, cr);
5616
5617 if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
5618 ctk_tree_view_paint_rubber_band (tree_view, cr);
5619
5620 if (drag_dest_path)
5621 ctk_tree_path_free (drag_dest_path);
5622
5623 return FALSE(0);
5624}
5625
5626static void
5627draw_bin (cairo_t *cr,
5628 gpointer user_data)
5629{
5630 CtkWidget *widget = CTK_WIDGET (user_data)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((ctk_widget_get_type ()))))))
;
5631 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
5632 GList *tmp_list;
5633
5634 cairo_save (cr);
5635
5636 ctk_cairo_transform_to_window (cr, widget, tree_view->priv->bin_window);
5637 ctk_tree_view_bin_draw (widget, cr);
5638
5639 cairo_restore (cr);
5640
5641 /* We can't just chain up to Container::draw as it will try to send the
5642 * event to the headers, so we handle propagating it to our children
5643 * (eg. widgets being edited) ourselves.
5644 */
5645 tmp_list = tree_view->priv->children;
5646 while (tmp_list)
5647 {
5648 CtkTreeViewChild *child = tmp_list->data;
5649 tmp_list = tmp_list->next;
5650
5651 ctk_container_propagate_draw (CTK_CONTAINER (tree_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_container_get_type ()))))))
, child->widget, cr);
5652 }
5653}
5654
5655static gboolean
5656ctk_tree_view_draw (CtkWidget *widget,
5657 cairo_t *cr)
5658{
5659 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
5660 CtkWidget *button;
5661 CtkStyleContext *context;
5662
5663 context = ctk_widget_get_style_context (widget);
5664
5665 if (ctk_cairo_should_draw_window (cr, tree_view->priv->bin_window))
5666 {
5667 cairo_rectangle_int_t view_rect;
5668 cairo_rectangle_int_t canvas_rect;
5669
5670 view_rect.x = 0;
5671 view_rect.y = ctk_tree_view_get_effective_header_height (tree_view);
5672 view_rect.width = ctk_widget_get_allocated_width (widget);
5673 view_rect.height = ctk_widget_get_allocated_height (widget) - view_rect.y;
5674
5675 cdk_window_get_position (tree_view->priv->bin_window, &canvas_rect.x, &canvas_rect.y);
5676 canvas_rect.y = -ctk_adjustment_get_value (tree_view->priv->vadjustment);
5677 canvas_rect.width = cdk_window_get_width (tree_view->priv->bin_window);
5678 canvas_rect.height = ctk_tree_view_get_height (tree_view);
5679
5680 _ctk_pixel_cache_draw (tree_view->priv->pixel_cache, cr, tree_view->priv->bin_window,
5681 &view_rect, &canvas_rect,
5682 draw_bin, widget);
5683 }
5684 else if (tree_view->priv->drag_highlight_window &&
5685 ctk_cairo_should_draw_window (cr, tree_view->priv->drag_highlight_window))
5686 {
5687 CdkRGBA color;
5688
5689 ctk_style_context_get_color (context, ctk_style_context_get_state (context), &color);
5690 cairo_save (cr);
5691 ctk_cairo_transform_to_window (cr, CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_highlight_window);
5692 if (tree_view->priv->drag_column_window_state == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
5693 {
5694 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
5695 cairo_paint (cr);
5696 cdk_cairo_set_source_rgba (cr, &color);
5697 cairo_rectangle (cr,
5698 1, 1,
5699 cdk_window_get_width (tree_view->priv->drag_highlight_window) - 2,
5700 cdk_window_get_height (tree_view->priv->drag_highlight_window) - 2);
5701 cairo_stroke (cr);
5702 }
5703 else
5704 {
5705 cdk_cairo_set_source_rgba (cr, &color);
5706 cairo_paint (cr);
5707 }
5708 cairo_restore (cr);
5709 }
5710 else
5711 {
5712 ctk_render_background (context, cr,
5713 0, 0,
5714 ctk_widget_get_allocated_width (widget),
5715 ctk_widget_get_allocated_height (widget));
5716 }
5717
5718 ctk_style_context_save (context);
5719 ctk_style_context_remove_class (context, CTK_STYLE_CLASS_VIEW"view");
5720
5721 if (ctk_cairo_should_draw_window (cr, tree_view->priv->header_window))
5722 {
5723 GList *list;
5724
5725 for (list = tree_view->priv->columns; list != NULL((void*)0); list = list->next)
5726 {
5727 CtkTreeViewColumn *column = list->data;
5728
5729 if (column == tree_view->priv->drag_column)
5730 continue;
5731
5732 if (ctk_tree_view_column_get_visible (column))
5733 {
5734 button = ctk_tree_view_column_get_button (column);
5735 ctk_container_propagate_draw (CTK_CONTAINER (tree_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_container_get_type ()))))))
,
5736 button, cr);
5737 }
5738 }
5739 }
5740
5741 if (tree_view->priv->drag_window &&
5742 ctk_cairo_should_draw_window (cr, tree_view->priv->drag_window))
5743 {
5744 button = ctk_tree_view_column_get_button (tree_view->priv->drag_column);
5745 ctk_container_propagate_draw (CTK_CONTAINER (tree_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_container_get_type ()))))))
,
5746 button, cr);
5747 }
5748
5749 ctk_style_context_restore (context);
5750
5751 return FALSE(0);
5752}
5753
5754enum
5755{
5756 DROP_HOME,
5757 DROP_RIGHT,
5758 DROP_LEFT,
5759 DROP_END
5760};
5761
5762/* returns 0x1 when no column has been found -- yes it's hackish */
5763static CtkTreeViewColumn *
5764ctk_tree_view_get_drop_column (CtkTreeView *tree_view,
5765 CtkTreeViewColumn *column,
5766 gint drop_position)
5767{
5768 CtkTreeViewColumn *left_column = NULL((void*)0);
5769 CtkTreeViewColumn *cur_column = NULL((void*)0);
5770 GList *tmp_list;
5771
5772 if (!ctk_tree_view_column_get_reorderable (column))
5773 return (CtkTreeViewColumn *)0x1;
5774
5775 switch (drop_position)
5776 {
5777 case DROP_HOME:
5778 /* find first column where we can drop */
5779 tmp_list = tree_view->priv->columns;
5780 if (column == CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
)
5781 return (CtkTreeViewColumn *)0x1;
5782
5783 while (tmp_list)
5784 {
5785 g_assert (tmp_list)do { if (tmp_list) ; else g_assertion_message_expr ("Ctk", "ctktreeview.c"
, 5785, ((const char*) (__func__)), "tmp_list"); } while (0)
;
5786
5787 cur_column = CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
;
5788 tmp_list = tmp_list->next;
5789
5790 if (left_column &&
5791 ctk_tree_view_column_get_visible (left_column) == FALSE(0))
5792 continue;
5793
5794 if (!tree_view->priv->column_drop_func)
5795 return left_column;
5796
5797 if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5798 {
5799 left_column = cur_column;
5800 continue;
5801 }
5802
5803 return left_column;
5804 }
5805
5806 if (!tree_view->priv->column_drop_func)
5807 return left_column;
5808
5809 if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL((void*)0), tree_view->priv->column_drop_func_data))
5810 return left_column;
5811 else
5812 return (CtkTreeViewColumn *)0x1;
5813 break;
5814
5815 case DROP_RIGHT:
5816 /* find first column after column where we can drop */
5817 tmp_list = tree_view->priv->columns;
5818
5819 for (; tmp_list; tmp_list = tmp_list->next)
5820 if (CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
== column)
5821 break;
5822
5823 if (!tmp_list || !tmp_list->next)
5824 return (CtkTreeViewColumn *)0x1;
5825
5826 tmp_list = tmp_list->next;
5827 left_column = CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
;
5828 tmp_list = tmp_list->next;
5829
5830 while (tmp_list)
5831 {
5832 g_assert (tmp_list)do { if (tmp_list) ; else g_assertion_message_expr ("Ctk", "ctktreeview.c"
, 5832, ((const char*) (__func__)), "tmp_list"); } while (0)
;
5833
5834 cur_column = CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
;
5835 tmp_list = tmp_list->next;
5836
5837 if (left_column &&
5838 ctk_tree_view_column_get_visible (left_column) == FALSE(0))
5839 {
5840 left_column = cur_column;
5841 if (tmp_list)
5842 tmp_list = tmp_list->next;
5843 continue;
5844 }
5845
5846 if (!tree_view->priv->column_drop_func)
5847 return left_column;
5848
5849 if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5850 {
5851 left_column = cur_column;
5852 continue;
5853 }
5854
5855 return left_column;
5856 }
5857
5858 if (!tree_view->priv->column_drop_func)
5859 return left_column;
5860
5861 if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL((void*)0), tree_view->priv->column_drop_func_data))
5862 return left_column;
5863 else
5864 return (CtkTreeViewColumn *)0x1;
5865 break;
5866
5867 case DROP_LEFT:
5868 /* find first column before column where we can drop */
5869 tmp_list = tree_view->priv->columns;
5870
5871 for (; tmp_list; tmp_list = tmp_list->next)
5872 if (CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
== column)
5873 break;
5874
5875 if (!tmp_list || !tmp_list->prev)
5876 return (CtkTreeViewColumn *)0x1;
5877
5878 tmp_list = tmp_list->prev;
5879 cur_column = CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
;
5880 tmp_list = tmp_list->prev;
5881
5882 while (tmp_list)
5883 {
5884 g_assert (tmp_list)do { if (tmp_list) ; else g_assertion_message_expr ("Ctk", "ctktreeview.c"
, 5884, ((const char*) (__func__)), "tmp_list"); } while (0)
;
5885
5886 left_column = CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
;
5887
5888 if (left_column &&
5889 ctk_tree_view_column_get_visible (left_column) == FALSE(0))
5890 {
5891 /*if (!tmp_list->prev)
5892 return (CtkTreeViewColumn *)0x1;
5893 */
5894/*
5895 cur_column = CTK_TREE_VIEW_COLUMN (tmp_list->prev->data);
5896 tmp_list = tmp_list->prev->prev;
5897 continue;*/
5898
5899 cur_column = left_column;
5900 if (tmp_list)
5901 tmp_list = tmp_list->prev;
5902 continue;
5903 }
5904
5905 if (!tree_view->priv->column_drop_func)
5906 return left_column;
5907
5908 if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5909 return left_column;
5910
5911 cur_column = left_column;
5912 tmp_list = tmp_list->prev;
5913 }
5914
5915 if (!tree_view->priv->column_drop_func)
5916 return NULL((void*)0);
5917
5918 if (tree_view->priv->column_drop_func (tree_view, column, NULL((void*)0), cur_column, tree_view->priv->column_drop_func_data))
5919 return NULL((void*)0);
5920 else
5921 return (CtkTreeViewColumn *)0x1;
5922 break;
5923
5924 case DROP_END:
5925 /* same as DROP_HOME case, but doing it backwards */
5926 tmp_list = g_list_last (tree_view->priv->columns);
5927 cur_column = NULL((void*)0);
5928
5929 if (column == CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
)
5930 return (CtkTreeViewColumn *)0x1;
5931
5932 while (tmp_list)
5933 {
5934 g_assert (tmp_list)do { if (tmp_list) ; else g_assertion_message_expr ("Ctk", "ctktreeview.c"
, 5934, ((const char*) (__func__)), "tmp_list"); } while (0)
;
5935
5936 left_column = CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
;
5937
5938 if (left_column &&
5939 ctk_tree_view_column_get_visible (left_column) == FALSE(0))
5940 {
5941 cur_column = left_column;
5942 tmp_list = tmp_list->prev;
5943 }
5944
5945 if (!tree_view->priv->column_drop_func)
5946 return left_column;
5947
5948 if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5949 return left_column;
5950
5951 cur_column = left_column;
5952 tmp_list = tmp_list->prev;
5953 }
5954
5955 if (!tree_view->priv->column_drop_func)
5956 return NULL((void*)0);
5957
5958 if (tree_view->priv->column_drop_func (tree_view, column, NULL((void*)0), cur_column, tree_view->priv->column_drop_func_data))
5959 return NULL((void*)0);
5960 else
5961 return (CtkTreeViewColumn *)0x1;
5962 break;
5963 }
5964
5965 return (CtkTreeViewColumn *)0x1;
5966}
5967
5968static gboolean
5969ctk_tree_view_search_key_cancels_search (guint keyval)
5970{
5971 return keyval == CDK_KEY_Escape0xff1b
5972 || keyval == CDK_KEY_Tab0xff09
5973 || keyval == CDK_KEY_KP_Tab0xff89
5974 || keyval == CDK_KEY_ISO_Left_Tab0xfe20;
5975}
5976
5977static gboolean
5978ctk_tree_view_key_press (CtkWidget *widget,
5979 CdkEventKey *event)
5980{
5981 CtkTreeView *tree_view = (CtkTreeView *) widget;
5982 CtkWidget *button;
5983
5984 if (tree_view->priv->rubber_band_status)
5985 {
5986 if (event->keyval == CDK_KEY_Escape0xff1b)
5987 ctk_tree_view_stop_rubber_band (tree_view);
5988
5989 return TRUE(!(0));
5990 }
5991
5992 if (tree_view->priv->in_column_drag)
5993 {
5994 if (event->keyval == CDK_KEY_Escape0xff1b)
5995 ctk_gesture_set_state (CTK_GESTURE (tree_view->priv->column_drag_gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->column_drag_gesture)), ((ctk_gesture_get_type
()))))))
,
5996 CTK_EVENT_SEQUENCE_DENIED);
5997 return TRUE(!(0));
5998 }
5999
6000 if (tree_view->priv->headers_visible)
6001 {
6002 GList *focus_column;
6003 gboolean rtl;
6004
6005 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
6006
6007 for (focus_column = tree_view->priv->columns;
6008 focus_column;
6009 focus_column = focus_column->next)
6010 {
6011 CtkTreeViewColumn *column = CTK_TREE_VIEW_COLUMN (focus_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((focus_column->data)), ((ctk_tree_view_column_get_type
()))))))
;
6012
6013 button = ctk_tree_view_column_get_button (column);
6014 if (ctk_widget_has_focus (button))
6015 break;
6016 }
6017
6018 if (focus_column &&
6019 (event->state & CDK_SHIFT_MASK) && (event->state & CDK_MOD1_MASK) &&
6020 (event->keyval == CDK_KEY_Left0xff51 || event->keyval == CDK_KEY_KP_Left0xff96
6021 || event->keyval == CDK_KEY_Right0xff53 || event->keyval == CDK_KEY_KP_Right0xff98))
6022 {
6023 CtkTreeViewColumn *column = CTK_TREE_VIEW_COLUMN (focus_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((focus_column->data)), ((ctk_tree_view_column_get_type
()))))))
;
6024 gint column_width;
6025
6026 if (!ctk_tree_view_column_get_resizable (column))
6027 {
6028 ctk_widget_error_bell (widget);
6029 return TRUE(!(0));
6030 }
6031
6032 column_width = ctk_tree_view_column_get_width (column);
6033
6034 if (event->keyval == (rtl ? CDK_KEY_Right0xff53 : CDK_KEY_Left0xff51)
6035 || event->keyval == (rtl ? CDK_KEY_KP_Right0xff98 : CDK_KEY_KP_Left0xff96))
6036 {
6037 column_width = MAX (column_width - 2, 0)(((column_width - 2) > (0)) ? (column_width - 2) : (0));
6038 }
6039 else if (event->keyval == (rtl ? CDK_KEY_Left0xff51 : CDK_KEY_Right0xff53)
6040 || event->keyval == (rtl ? CDK_KEY_KP_Left0xff96 : CDK_KEY_KP_Right0xff98))
6041 {
6042 column_width = column_width + 2;
6043 }
6044
6045 ctk_tree_view_column_set_fixed_width (column, column_width);
6046 ctk_tree_view_column_set_expand (column, FALSE(0));
6047 return TRUE(!(0));
6048 }
6049
6050 if (focus_column &&
6051 (event->state & CDK_MOD1_MASK) &&
6052 (event->keyval == CDK_KEY_Left0xff51 || event->keyval == CDK_KEY_KP_Left0xff96
6053 || event->keyval == CDK_KEY_Right0xff53 || event->keyval == CDK_KEY_KP_Right0xff98
6054 || event->keyval == CDK_KEY_Home0xff50 || event->keyval == CDK_KEY_KP_Home0xff95
6055 || event->keyval == CDK_KEY_End0xff57 || event->keyval == CDK_KEY_KP_End0xff9c))
6056 {
6057 CtkTreeViewColumn *column = CTK_TREE_VIEW_COLUMN (focus_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((focus_column->data)), ((ctk_tree_view_column_get_type
()))))))
;
6058
6059 if (event->keyval == (rtl ? CDK_KEY_Right0xff53 : CDK_KEY_Left0xff51)
6060 || event->keyval == (rtl ? CDK_KEY_KP_Right0xff98 : CDK_KEY_KP_Left0xff96))
6061 {
6062 CtkTreeViewColumn *col;
6063 col = ctk_tree_view_get_drop_column (tree_view, column, DROP_LEFT);
6064 if (col != (CtkTreeViewColumn *)0x1)
6065 ctk_tree_view_move_column_after (tree_view, column, col);
6066 else
6067 ctk_widget_error_bell (widget);
6068 }
6069 else if (event->keyval == (rtl ? CDK_KEY_Left0xff51 : CDK_KEY_Right0xff53)
6070 || event->keyval == (rtl ? CDK_KEY_KP_Left0xff96 : CDK_KEY_KP_Right0xff98))
6071 {
6072 CtkTreeViewColumn *col;
6073 col = ctk_tree_view_get_drop_column (tree_view, column, DROP_RIGHT);
6074 if (col != (CtkTreeViewColumn *)0x1)
6075 ctk_tree_view_move_column_after (tree_view, column, col);
6076 else
6077 ctk_widget_error_bell (widget);
6078 }
6079 else if (event->keyval == CDK_KEY_Home0xff50 || event->keyval == CDK_KEY_KP_Home0xff95)
6080 {
6081 CtkTreeViewColumn *col;
6082 col = ctk_tree_view_get_drop_column (tree_view, column, DROP_HOME);
6083 if (col != (CtkTreeViewColumn *)0x1)
6084 ctk_tree_view_move_column_after (tree_view, column, col);
6085 else
6086 ctk_widget_error_bell (widget);
6087 }
6088 else if (event->keyval == CDK_KEY_End0xff57 || event->keyval == CDK_KEY_KP_End0xff9c)
6089 {
6090 CtkTreeViewColumn *col;
6091 col = ctk_tree_view_get_drop_column (tree_view, column, DROP_END);
6092 if (col != (CtkTreeViewColumn *)0x1)
6093 ctk_tree_view_move_column_after (tree_view, column, col);
6094 else
6095 ctk_widget_error_bell (widget);
6096 }
6097
6098 return TRUE(!(0));
6099 }
6100 }
6101
6102 /* Chain up to the parent class. It handles the keybindings. */
6103 if (CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->key_press_event (widget, event))
6104 return TRUE(!(0));
6105
6106 if (tree_view->priv->search_entry_avoid_unhandled_binding)
6107 {
6108 tree_view->priv->search_entry_avoid_unhandled_binding = FALSE(0);
6109 return FALSE(0);
6110 }
6111
6112 /* Initially, before the search window is visible, we pass the event to the
6113 * IM context of the search entry box. If it triggers a commit or a preedit,
6114 * we then show the search window without loosing tree view focus.
6115 * If the seach window is already visible, we forward the events to it,
6116 * keeping the focus on the tree view.
6117 */
6118 if (ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
)
6119 && tree_view->priv->enable_search
6120 && !tree_view->priv->search_custom_entry_set
6121 && !ctk_tree_view_search_key_cancels_search (event->keyval))
6122 {
6123 CtkWidget *search_window;
6124
6125 ctk_tree_view_ensure_interactive_directory (tree_view);
6126
6127 search_window = tree_view->priv->search_window;
6128 if (!ctk_widget_is_visible (search_window))
6129 {
6130 CtkIMContext *im_context =
6131 _ctk_entry_get_im_context (CTK_ENTRY (tree_view->priv->search_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_entry_get_type
()))))))
);
6132
6133 tree_view->priv->imcontext_changed = FALSE(0);
6134 ctk_im_context_filter_keypress (im_context, event);
6135
6136 if (tree_view->priv->imcontext_changed)
6137 {
6138 CdkDevice *device;
6139
6140 device = cdk_event_get_device ((CdkEvent *) event);
6141 if (ctk_tree_view_real_start_interactive_search (tree_view,
6142 device,
6143 FALSE(0)))
6144 {
6145 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
6146 return TRUE(!(0));
6147 }
6148 else
6149 {
6150 ctk_entry_set_text (CTK_ENTRY (tree_view->priv->search_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_entry_get_type
()))))))
, "");
6151 return FALSE(0);
6152 }
6153 }
6154 }
6155 else
6156 {
6157 CdkEvent *new_event;
6158 gulong popup_menu_id;
6159
6160 new_event = cdk_event_copy ((CdkEvent *) event);
6161 g_object_unref (((CdkEventKey *) new_event)->window);
6162 ((CdkEventKey *) new_event)->window =
6163 g_object_ref (ctk_widget_get_window (search_window))((__typeof__ (ctk_widget_get_window (search_window))) (g_object_ref
) (ctk_widget_get_window (search_window)))
;
6164 ctk_widget_realize (search_window);
6165
6166 popup_menu_id = g_signal_connect (tree_view->priv->search_entry,g_signal_connect_data ((tree_view->priv->search_entry),
("popup-menu"), (((GCallback) (ctk_true))), (((void*)0)), ((
void*)0), (GConnectFlags) 0)
6167 "popup-menu", G_CALLBACK (ctk_true),g_signal_connect_data ((tree_view->priv->search_entry),
("popup-menu"), (((GCallback) (ctk_true))), (((void*)0)), ((
void*)0), (GConnectFlags) 0)
6168 NULL)g_signal_connect_data ((tree_view->priv->search_entry),
("popup-menu"), (((GCallback) (ctk_true))), (((void*)0)), ((
void*)0), (GConnectFlags) 0)
;
6169
6170 /* Because we keep the focus on the treeview, we need to forward the
6171 * key events to the entry, when it is visible. */
6172 ctk_widget_event (search_window, new_event);
6173 cdk_event_free (new_event);
6174
6175 g_signal_handler_disconnect (tree_view->priv->search_entry,
6176 popup_menu_id);
6177
6178 }
6179 }
6180
6181 return FALSE(0);
6182}
6183
6184static gboolean
6185ctk_tree_view_key_release (CtkWidget *widget,
6186 CdkEventKey *event)
6187{
6188 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
6189
6190 if (tree_view->priv->rubber_band_status)
6191 return TRUE(!(0));
6192
6193 return CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->key_release_event (widget, event);
6194}
6195
6196/* FIXME Is this function necessary? Can I get an enter_notify event
6197 * w/o either an expose event or a mouse motion event?
6198 */
6199static gboolean
6200ctk_tree_view_enter_notify (CtkWidget *widget,
6201 CdkEventCrossing *event)
6202{
6203 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
6204 CtkRBTree *tree;
6205 CtkRBNode *node;
6206 gint new_y;
6207
6208 /* Sanity check it */
6209 if (event->window != tree_view->priv->bin_window)
6210 return FALSE(0);
6211
6212 if (tree_view->priv->tree == NULL((void*)0))
6213 return FALSE(0);
6214
6215 /* find the node internally */
6216 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y)((event->y) + tree_view->priv->dy);
6217 if (new_y < 0)
6218 new_y = 0;
6219 _ctk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
6220
6221 tree_view->priv->event_last_x = event->x;
6222 tree_view->priv->event_last_y = event->y;
6223
6224 if ((tree_view->priv->button_pressed_node == NULL((void*)0)) ||
6225 (tree_view->priv->button_pressed_node == node))
6226 prelight_or_select (tree_view, tree, node, event->x, event->y);
6227
6228 return TRUE(!(0));
6229}
6230
6231static gboolean
6232ctk_tree_view_leave_notify (CtkWidget *widget,
6233 CdkEventCrossing *event G_GNUC_UNUSED__attribute__ ((__unused__)))
6234{
6235 CtkTreeView *tree_view;
6236
6237 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
6238
6239 if (tree_view->priv->prelight_node)
6240 _ctk_tree_view_queue_draw_node (tree_view,
6241 tree_view->priv->prelight_tree,
6242 tree_view->priv->prelight_node,
6243 NULL((void*)0));
6244
6245 tree_view->priv->event_last_x = -10000;
6246 tree_view->priv->event_last_y = -10000;
6247
6248 prelight_or_select (tree_view,
6249 NULL((void*)0), NULL((void*)0),
6250 -1000, -1000); /* coords not possibly over an arrow */
6251
6252 return TRUE(!(0));
6253}
6254
6255
6256static gint
6257ctk_tree_view_focus_out (CtkWidget *widget,
6258 CdkEventFocus *event)
6259{
6260 CtkTreeView *tree_view;
6261
6262 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
6263
6264 ctk_widget_queue_draw (widget);
6265
6266 /* destroy interactive search dialog */
6267 if (tree_view->priv->search_window)
6268 ctk_tree_view_search_window_hide (tree_view->priv->search_window, tree_view,
6269 cdk_event_get_device ((CdkEvent *) event));
6270 return FALSE(0);
6271}
6272
6273
6274/* Incremental Reflow
6275 */
6276
6277static void
6278ctk_tree_view_node_queue_redraw (CtkTreeView *tree_view,
6279 CtkRBTree *tree,
6280 CtkRBNode *node)
6281{
6282 CdkRectangle rect;
6283
6284 rect.x = 0;
6285 rect.y =
6286 _ctk_rbtree_node_find_offset (tree, node)
6287 - ctk_adjustment_get_value (tree_view->priv->vadjustment);
6288 rect.width = ctk_widget_get_allocated_width (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
6289 rect.height = CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right->
offset+(node->children?node->children->root->offset
:0)))
;
6290
6291 cdk_window_invalidate_rect (tree_view->priv->bin_window,
6292 &rect, TRUE(!(0)));
6293}
6294
6295static gboolean
6296node_is_visible (CtkTreeView *tree_view,
6297 CtkRBTree *tree,
6298 CtkRBNode *node)
6299{
6300 int y;
6301 int height;
6302
6303 y = _ctk_rbtree_node_find_offset (tree, node);
6304 height = ctk_tree_view_get_row_height (tree_view, node);
6305
6306 if (y >= ctk_adjustment_get_value (tree_view->priv->vadjustment) &&
6307 y + height <= (ctk_adjustment_get_value (tree_view->priv->vadjustment)
6308 + ctk_adjustment_get_page_size (tree_view->priv->vadjustment)))
6309 return TRUE(!(0));
6310
6311 return FALSE(0);
6312}
6313
6314static gint
6315get_separator_height (CtkTreeView *tree_view)
6316{
6317 CtkStyleContext *context;
6318 CtkCssStyle *style;
6319 gdouble d;
6320 gint min_size;
6321
6322 context = ctk_widget_get_style_context (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
6323 ctk_style_context_save (context);
6324 ctk_style_context_add_class (context, CTK_STYLE_CLASS_SEPARATOR"separator");
6325
6326 style = ctk_style_context_lookup_style (context);
6327 d = _ctk_css_number_value_get
6328 (ctk_css_style_get_value (style, CTK_CSS_PROPERTY_MIN_HEIGHT), 100);
6329
6330 if (d < 1)
6331 min_size = ceil (d);
6332 else
6333 min_size = floor (d);
6334
6335 ctk_style_context_restore (context);
6336
6337 return min_size;
6338}
6339
6340/* Returns TRUE if it updated the size
6341 */
6342static gboolean
6343validate_row (CtkTreeView *tree_view,
6344 CtkRBTree *tree,
6345 CtkRBNode *node,
6346 CtkTreeIter *iter,
6347 CtkTreePath *path)
6348{
6349 CtkTreeViewColumn *column;
6350 CtkStyleContext *context;
6351 GList *list, *first_column, *last_column;
6352 gint height = 0;
6353 gint horizontal_separator;
6354 gint vertical_separator;
6355 gint depth = ctk_tree_path_get_depth (path);
6356 gboolean retval = FALSE(0);
6357 gboolean is_separator = FALSE(0);
6358 gboolean draw_vgrid_lines, draw_hgrid_lines;
6359 gint grid_line_width;
6360 gint expander_size;
6361
6362 /* double check the row needs validating */
6363 if (! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
&&
6364 ! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID
)?(!(0)):(0)):(0))
)
6365 return FALSE(0);
6366
6367 is_separator = row_is_separator (tree_view, iter, NULL((void*)0));
6368
6369 ctk_widget_style_get (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
6370 "horizontal-separator", &horizontal_separator,
6371 "vertical-separator", &vertical_separator,
6372 "grid-line-width", &grid_line_width,
6373 NULL((void*)0));
6374
6375 draw_vgrid_lines =
6376 tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_VERTICAL
6377 || tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_BOTH;
6378 draw_hgrid_lines =
6379 tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_HORIZONTAL
6380 || tree_view->priv->grid_lines == CTK_TREE_VIEW_GRID_LINES_BOTH;
6381 expander_size = ctk_tree_view_get_expander_size (tree_view);
6382
6383 for (last_column = g_list_last (tree_view->priv->columns);
6384 last_column &&
6385 !(ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (last_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((last_column->data)), ((ctk_tree_view_column_get_type
()))))))
));
6386 last_column = last_column->prev)
6387 ;
6388
6389 for (first_column = g_list_first (tree_view->priv->columns);
6390 first_column &&
6391 !(ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (first_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((first_column->data)), ((ctk_tree_view_column_get_type
()))))))
));
6392 first_column = first_column->next)
6393 ;
6394
6395 context = ctk_widget_get_style_context (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
6396 ctk_style_context_save (context);
6397 ctk_style_context_add_class (context, CTK_STYLE_CLASS_CELL"cell");
6398
6399 for (list = tree_view->priv->columns; list; list = list->next)
6400 {
6401 gint padding = 0;
6402 gint original_width;
6403 gint new_width;
6404 gint row_height;
6405
6406 column = list->data;
6407
6408 if (!ctk_tree_view_column_get_visible (column))
6409 continue;
6410
6411 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID
)?(!(0)):(0)):(0))
&&
6412 !_ctk_tree_view_column_cell_get_dirty (column))
6413 continue;
6414
6415 original_width = _ctk_tree_view_column_get_requested_width (column);
6416
6417 ctk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter,
6418 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
6419 node->children?TRUE(!(0)):FALSE(0));
6420 ctk_tree_view_column_cell_get_size (column,
6421 NULL((void*)0), NULL((void*)0), NULL((void*)0),
6422 NULL((void*)0), &row_height);
6423
6424 if (is_separator)
6425 {
6426 height = get_separator_height (tree_view);
6427 /* ctk_tree_view_get_row_height() assumes separator nodes are > 0 */
6428 height = MAX (height, 1)(((height) > (1)) ? (height) : (1));
6429 }
6430 else
6431 {
6432 row_height += vertical_separator;
6433 height = MAX (height, row_height)(((height) > (row_height)) ? (height) : (row_height));
6434 height = MAX (height, expander_size)(((height) > (expander_size)) ? (height) : (expander_size)
)
;
6435 }
6436
6437 if (ctk_tree_view_is_expander_column (tree_view, column))
6438 {
6439 padding += horizontal_separator + (depth - 1) * tree_view->priv->level_indentation;
6440
6441 if (ctk_tree_view_draw_expanders (tree_view))
6442 padding += depth * expander_size;
6443 }
6444 else
6445 padding += horizontal_separator;
6446
6447 if (draw_vgrid_lines)
6448 {
6449 if (list->data == first_column || list->data == last_column)
6450 padding += grid_line_width / 2.0;
6451 else
6452 padding += grid_line_width;
6453 }
6454
6455 /* Update the padding for the column */
6456 _ctk_tree_view_column_push_padding (column, padding);
6457 new_width = _ctk_tree_view_column_get_requested_width (column);
6458
6459 if (new_width > original_width)
6460 retval = TRUE(!(0));
6461 }
6462
6463 ctk_style_context_restore (context);
6464
6465 if (draw_hgrid_lines)
6466 height += grid_line_width;
6467
6468 if (height != CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right->
offset+(node->children?node->children->root->offset
:0)))
)
6469 {
6470 retval = TRUE(!(0));
6471 _ctk_rbtree_node_set_height (tree, node, height);
6472 }
6473 _ctk_rbtree_node_mark_valid (tree, node);
6474 tree_view->priv->post_validation_flag = TRUE(!(0));
6475
6476 return retval;
6477}
6478
6479
6480static void
6481validate_visible_area (CtkTreeView *tree_view)
6482{
6483 CtkAllocation allocation;
6484 CtkTreePath *path = NULL((void*)0);
6485 CtkTreePath *above_path = NULL((void*)0);
6486 CtkTreeIter iter;
6487 CtkRBTree *tree = NULL((void*)0);
6488 CtkRBNode *node = NULL((void*)0);
6489 gboolean need_redraw = FALSE(0);
6490 gboolean size_changed = FALSE(0);
6491 gint total_height;
6492 gint area_above = 0;
6493 gint area_below = 0;
6494
6495 if (tree_view->priv->tree == NULL((void*)0))
6496 return;
6497
6498 if (! CTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, CTK_RBNODE_DESCENDANTS_INVALID)(tree_view->priv->tree->root?(((tree_view->priv->
tree->root->flags&CTK_RBNODE_DESCENDANTS_INVALID)==
CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))
&&
6499 tree_view->priv->scroll_to_path == NULL((void*)0))
6500 return;
6501
6502 ctk_widget_get_allocation (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &allocation);
6503 total_height = allocation.height - ctk_tree_view_get_effective_header_height (tree_view);
6504
6505 if (total_height == 0)
6506 return;
6507
6508 /* First, we check to see if we need to scroll anywhere
6509 */
6510 if (tree_view->priv->scroll_to_path)
6511 {
6512 path = ctk_tree_row_reference_get_path (tree_view->priv->scroll_to_path);
6513 if (path && !_ctk_tree_view_find_node (tree_view, path, &tree, &node))
6514 {
6515 /* we are going to scroll, and will update dy */
6516 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6517 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
||
6518 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID
)?(!(0)):(0)):(0))
)
6519 {
6520 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
6521 if (validate_row (tree_view, tree, node, &iter, path))
6522 size_changed = TRUE(!(0));
6523 }
6524
6525 if (tree_view->priv->scroll_to_use_align)
6526 {
6527 gint height = ctk_tree_view_get_row_height (tree_view, node);
6528 area_above = (total_height - height) *
6529 tree_view->priv->scroll_to_row_align;
6530 area_below = total_height - area_above - height;
6531 area_above = MAX (area_above, 0)(((area_above) > (0)) ? (area_above) : (0));
6532 area_below = MAX (area_below, 0)(((area_below) > (0)) ? (area_below) : (0));
6533 }
6534 else
6535 {
6536 /* two cases:
6537 * 1) row not visible
6538 * 2) row visible
6539 */
6540 gint dy;
6541 gint height = ctk_tree_view_get_row_height (tree_view, node);
6542
6543 dy = _ctk_rbtree_node_find_offset (tree, node);
6544
6545 if (dy >= ctk_adjustment_get_value (tree_view->priv->vadjustment) &&
6546 dy + height <= (ctk_adjustment_get_value (tree_view->priv->vadjustment)
6547 + ctk_adjustment_get_page_size (tree_view->priv->vadjustment)))
6548 {
6549 /* row visible: keep the row at the same position */
6550 area_above = dy - ctk_adjustment_get_value (tree_view->priv->vadjustment);
6551 area_below = (ctk_adjustment_get_value (tree_view->priv->vadjustment) +
6552 ctk_adjustment_get_page_size (tree_view->priv->vadjustment))
6553 - dy - height;
6554 }
6555 else
6556 {
6557 /* row not visible */
6558 if (dy >= 0
6559 && dy + height <= ctk_adjustment_get_page_size (tree_view->priv->vadjustment))
6560 {
6561 /* row at the beginning -- fixed */
6562 area_above = dy;
6563 area_below = ctk_adjustment_get_page_size (tree_view->priv->vadjustment)
6564 - area_above - height;
6565 }
6566 else if (dy >= (ctk_adjustment_get_upper (tree_view->priv->vadjustment) -
6567 ctk_adjustment_get_page_size (tree_view->priv->vadjustment)))
6568 {
6569 /* row at the end -- fixed */
6570 area_above = dy - (ctk_adjustment_get_upper (tree_view->priv->vadjustment) -
6571 ctk_adjustment_get_page_size (tree_view->priv->vadjustment));
6572 area_below = ctk_adjustment_get_page_size (tree_view->priv->vadjustment) -
6573 area_above - height;
6574
6575 if (area_below < 0)
6576 {
6577 area_above = ctk_adjustment_get_page_size (tree_view->priv->vadjustment) - height;
6578 area_below = 0;
6579 }
6580 }
6581 else
6582 {
6583 /* row somewhere in the middle, bring it to the top
6584 * of the view
6585 */
6586 area_above = 0;
6587 area_below = total_height - height;
6588 }
6589 }
6590 }
6591 }
6592 else
6593 /* the scroll to isn't valid; ignore it.
6594 */
6595 {
6596 if (tree_view->priv->scroll_to_path && !path)
6597 {
6598 ctk_tree_row_reference_free (tree_view->priv->scroll_to_path);
6599 tree_view->priv->scroll_to_path = NULL((void*)0);
6600 }
6601 if (path)
6602 ctk_tree_path_free (path);
6603 path = NULL((void*)0);
6604 }
6605 }
6606
6607 /* We didn't have a scroll_to set, so we just handle things normally
6608 */
6609 if (path == NULL((void*)0))
6610 {
6611 gint offset;
6612
6613 offset = _ctk_rbtree_find_offset (tree_view->priv->tree,
6614 TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0)((0) + tree_view->priv->dy),
6615 &tree, &node);
6616 if (node == NULL((void*)0))
6617 {
6618 /* In this case, nothing has been validated */
6619 path = ctk_tree_path_new_first ();
6620 _ctk_tree_view_find_node (tree_view, path, &tree, &node);
6621 }
6622 else
6623 {
6624 path = _ctk_tree_path_new_from_rbtree (tree, node);
6625 total_height += offset;
6626 }
6627
6628 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6629
6630 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
||
6631 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID
)?(!(0)):(0)):(0))
)
6632 {
6633 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
6634 if (validate_row (tree_view, tree, node, &iter, path))
6635 size_changed = TRUE(!(0));
6636 }
6637 area_above = 0;
6638 area_below = total_height - ctk_tree_view_get_row_height (tree_view, node);
6639 }
6640
6641 above_path = ctk_tree_path_copy (path);
6642
6643 /* if we do not validate any row above the new top_row, we will make sure
6644 * that the row immediately above top_row has been validated. (if we do not
6645 * do this, _ctk_rbtree_find_offset will find the row above top_row, because
6646 * when invalidated that row's height will be zero. and this will mess up
6647 * scrolling).
6648 */
6649 if (area_above == 0)
6650 {
6651 CtkRBTree *tmptree;
6652 CtkRBNode *tmpnode;
6653
6654 _ctk_tree_view_find_node (tree_view, above_path, &tmptree, &tmpnode);
6655 _ctk_rbtree_prev_full (tmptree, tmpnode, &tmptree, &tmpnode);
6656
6657 if (tmpnode)
6658 {
6659 CtkTreePath *tmppath;
6660 CtkTreeIter tmpiter;
6661
6662 tmppath = _ctk_tree_path_new_from_rbtree (tmptree, tmpnode);
6663 ctk_tree_model_get_iter (tree_view->priv->model, &tmpiter, tmppath);
6664
6665 if (CTK_RBNODE_FLAG_SET (tmpnode, CTK_RBNODE_INVALID)(tmpnode?(((tmpnode->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
||
6666 CTK_RBNODE_FLAG_SET (tmpnode, CTK_RBNODE_COLUMN_INVALID)(tmpnode?(((tmpnode->flags&CTK_RBNODE_COLUMN_INVALID)==
CTK_RBNODE_COLUMN_INVALID)?(!(0)):(0)):(0))
)
6667 {
6668 _ctk_tree_view_queue_draw_node (tree_view, tmptree, tmpnode, NULL((void*)0));
6669 if (validate_row (tree_view, tmptree, tmpnode, &tmpiter, tmppath))
6670 size_changed = TRUE(!(0));
6671 }
6672
6673 ctk_tree_path_free (tmppath);
6674 }
6675 }
6676
6677 /* Now, we walk forwards and backwards, measuring rows. Unfortunately,
6678 * backwards is much slower then forward, as there is no iter_prev function.
6679 * We go forwards first in case we run out of tree. Then we go backwards to
6680 * fill out the top.
6681 */
6682 while (node && area_below > 0)
6683 {
6684 if (node->children)
6685 {
6686 CtkTreeIter parent = iter;
6687 gboolean has_child;
6688
6689 tree = node->children;
6690 node = _ctk_rbtree_first (tree);
6691
6692 has_child = ctk_tree_model_iter_children (tree_view->priv->model,
6693 &iter,
6694 &parent);
6695 TREE_VIEW_INTERNAL_ASSERT_VOID (has_child)do{ if (!(has_child)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "6695", ((const char*
) (__func__)), "has_child"); return; }; }while (0)
;
6696 ctk_tree_path_down (path);
6697 }
6698 else
6699 {
6700 gboolean done = FALSE(0);
6701 do
6702 {
6703 node = _ctk_rbtree_next (tree, node);
6704 if (node != NULL((void*)0))
6705 {
6706 gboolean has_next = ctk_tree_model_iter_next (tree_view->priv->model, &iter);
6707 done = TRUE(!(0));
6708 ctk_tree_path_next (path);
6709
6710 /* Sanity Check! */
6711 TREE_VIEW_INTERNAL_ASSERT_VOID (has_next)do{ if (!(has_next)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "6711", ((const char*
) (__func__)), "has_next"); return; }; }while (0)
;
6712 }
6713 else
6714 {
6715 CtkTreeIter parent_iter = iter;
6716 gboolean has_parent;
6717
6718 node = tree->parent_node;
6719 tree = tree->parent_tree;
6720 if (tree == NULL((void*)0))
6721 break;
6722 has_parent = ctk_tree_model_iter_parent (tree_view->priv->model,
6723 &iter,
6724 &parent_iter);
6725 ctk_tree_path_up (path);
6726
6727 /* Sanity check */
6728 TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent)do{ if (!(has_parent)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "6728", ((const char*
) (__func__)), "has_parent"); return; }; }while (0)
;
6729 }
6730 }
6731 while (!done);
6732 }
6733
6734 if (!node)
6735 break;
6736
6737 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
||
6738 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID
)?(!(0)):(0)):(0))
)
6739 {
6740 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
6741 if (validate_row (tree_view, tree, node, &iter, path))
6742 size_changed = TRUE(!(0));
6743 }
6744
6745 area_below -= ctk_tree_view_get_row_height (tree_view, node);
6746 }
6747 ctk_tree_path_free (path);
6748
6749 /* If we ran out of tree, and have extra area_below left, we need to add it
6750 * to area_above */
6751 if (area_below > 0)
6752 area_above += area_below;
6753
6754 _ctk_tree_view_find_node (tree_view, above_path, &tree, &node);
6755
6756 /* We walk backwards */
6757 while (area_above > 0)
6758 {
6759 _ctk_rbtree_prev_full (tree, node, &tree, &node);
6760
6761 /* Always find the new path in the tree. We cannot just assume
6762 * a ctk_tree_path_prev() is enough here, as there might be children
6763 * in between this node and the previous sibling node. If this
6764 * appears to be a performance hotspot in profiles, we can look into
6765 * intrigate logic for keeping path, node and iter in sync like
6766 * we do for forward walks. (Which will be hard because of the lacking
6767 * iter_prev).
6768 */
6769
6770 if (node == NULL((void*)0))
6771 break;
6772
6773 ctk_tree_path_free (above_path);
6774 above_path = _ctk_tree_path_new_from_rbtree (tree, node);
6775
6776 ctk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
6777
6778 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
||
6779 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID
)?(!(0)):(0)):(0))
)
6780 {
6781 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
6782 if (validate_row (tree_view, tree, node, &iter, above_path))
6783 size_changed = TRUE(!(0));
6784 }
6785 area_above -= ctk_tree_view_get_row_height (tree_view, node);
6786 }
6787
6788 /* if we scrolled to a path, we need to set the dy here,
6789 * and sync the top row accordingly
6790 */
6791 if (tree_view->priv->scroll_to_path)
6792 {
6793 ctk_tree_view_set_top_row (tree_view, above_path, -area_above);
6794 ctk_tree_view_top_row_to_dy (tree_view);
6795
6796 need_redraw = TRUE(!(0));
6797 }
6798 else if (ctk_tree_view_get_height (tree_view) <= ctk_adjustment_get_page_size (tree_view->priv->vadjustment))
6799 {
6800 /* when we are not scrolling, we should never set dy to something
6801 * else than zero. we update top_row to be in sync with dy = 0.
6802 */
6803 ctk_adjustment_set_value (CTK_ADJUSTMENT (tree_view->priv->vadjustment)((((CtkAdjustment*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->vadjustment)), ((ctk_adjustment_get_type
()))))))
, 0);
6804 ctk_tree_view_dy_to_top_row (tree_view);
6805 }
6806 else if (ctk_adjustment_get_value (tree_view->priv->vadjustment) + ctk_adjustment_get_page_size (tree_view->priv->vadjustment) > ctk_tree_view_get_height (tree_view))
6807 {
6808 ctk_adjustment_set_value (CTK_ADJUSTMENT (tree_view->priv->vadjustment)((((CtkAdjustment*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->vadjustment)), ((ctk_adjustment_get_type
()))))))
, ctk_tree_view_get_height (tree_view) - ctk_adjustment_get_page_size (tree_view->priv->vadjustment));
6809 ctk_tree_view_dy_to_top_row (tree_view);
6810 }
6811 else
6812 ctk_tree_view_top_row_to_dy (tree_view);
6813
6814 /* update width/height and queue a resize */
6815 if (size_changed)
6816 {
6817 CtkRequisition requisition;
6818
6819 /* We temporarily guess a size, under the assumption that it will be the
6820 * same when we get our next size_allocate. If we don't do this, we'll be
6821 * in an inconsistent state if we call top_row_to_dy. */
6822
6823 ctk_widget_get_preferred_size (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
6824 &requisition, NULL((void*)0));
6825 ctk_adjustment_set_upper (tree_view->priv->hadjustment,
6826 MAX (ctk_adjustment_get_upper (tree_view->priv->hadjustment), requisition.width)(((ctk_adjustment_get_upper (tree_view->priv->hadjustment
)) > (requisition.width)) ? (ctk_adjustment_get_upper (tree_view
->priv->hadjustment)) : (requisition.width))
);
6827 ctk_adjustment_set_upper (tree_view->priv->vadjustment,
6828 MAX (ctk_adjustment_get_upper (tree_view->priv->vadjustment), requisition.height)(((ctk_adjustment_get_upper (tree_view->priv->vadjustment
)) > (requisition.height)) ? (ctk_adjustment_get_upper (tree_view
->priv->vadjustment)) : (requisition.height))
);
6829 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
6830 }
6831
6832 if (tree_view->priv->scroll_to_path)
6833 {
6834 ctk_tree_row_reference_free (tree_view->priv->scroll_to_path);
6835 tree_view->priv->scroll_to_path = NULL((void*)0);
6836 }
6837
6838 if (above_path)
6839 ctk_tree_path_free (above_path);
6840
6841 if (tree_view->priv->scroll_to_column)
6842 {
6843 tree_view->priv->scroll_to_column = NULL((void*)0);
6844 }
6845 if (need_redraw)
6846 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
6847}
6848
6849static void
6850initialize_fixed_height_mode (CtkTreeView *tree_view)
6851{
6852 if (!tree_view->priv->tree)
6853 return;
6854
6855 if (tree_view->priv->fixed_height < 0)
6856 {
6857 CtkTreeIter iter;
6858 CtkTreePath *path;
6859
6860 CtkRBTree *tree = NULL((void*)0);
6861 CtkRBNode *node = NULL((void*)0);
6862
6863 tree = tree_view->priv->tree;
6864 node = tree->root;
6865
6866 path = _ctk_tree_path_new_from_rbtree (tree, node);
6867 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6868
6869 validate_row (tree_view, tree, node, &iter, path);
6870
6871 ctk_tree_path_free (path);
6872
6873 tree_view->priv->fixed_height = ctk_tree_view_get_row_height (tree_view, node);
6874 }
6875
6876 _ctk_rbtree_set_fixed_height (tree_view->priv->tree,
6877 tree_view->priv->fixed_height, TRUE(!(0)));
6878}
6879
6880/* Our strategy for finding nodes to validate is a little convoluted. We find
6881 * the left-most uninvalidated node. We then try walking right, validating
6882 * nodes. Once we find a valid node, we repeat the previous process of finding
6883 * the first invalid node.
6884 */
6885
6886static gboolean
6887do_validate_rows (CtkTreeView *tree_view, gboolean queue_resize)
6888{
6889 static gboolean prevent_recursion_hack = FALSE(0);
6890
6891 CtkRBTree *tree = NULL((void*)0);
6892 CtkRBNode *node = NULL((void*)0);
6893 gboolean validated_area = FALSE(0);
6894 gint retval = TRUE(!(0));
6895 CtkTreePath *path = NULL((void*)0);
6896 CtkTreeIter iter;
6897 GTimer *timer;
6898 gint i = 0;
6899
6900 gint y = -1;
6901 gint prev_height = -1;
6902 gboolean fixed_height = TRUE(!(0));
6903
6904 g_assert (tree_view)do { if (tree_view) ; else g_assertion_message_expr ("Ctk", "ctktreeview.c"
, 6904, ((const char*) (__func__)), "tree_view"); } while (0)
;
6905
6906 /* prevent infinite recursion via get_preferred_width() */
6907 if (prevent_recursion_hack)
6908 return FALSE(0);
6909
6910 if (tree_view->priv->tree == NULL((void*)0))
6911 return FALSE(0);
6912
6913 if (tree_view->priv->fixed_height_mode)
6914 {
6915 if (tree_view->priv->fixed_height < 0)
6916 initialize_fixed_height_mode (tree_view);
6917
6918 return FALSE(0);
6919 }
6920
6921 timer = g_timer_new ();
6922 g_timer_start (timer);
6923
6924 do
6925 {
6926 gboolean changed = FALSE(0);
6927
6928 if (! CTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, CTK_RBNODE_DESCENDANTS_INVALID)(tree_view->priv->tree->root?(((tree_view->priv->
tree->root->flags&CTK_RBNODE_DESCENDANTS_INVALID)==
CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))
)
6929 {
6930 retval = FALSE(0);
6931 goto done;
6932 }
6933
6934 if (path != NULL((void*)0))
6935 {
6936 node = _ctk_rbtree_next (tree, node);
6937 if (node != NULL((void*)0))
6938 {
6939 TREE_VIEW_INTERNAL_ASSERT (ctk_tree_model_iter_next (tree_view->priv->model, &iter), FALSE)do{ if (!(ctk_tree_model_iter_next (tree_view->priv->model
, &iter))) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "6939", ((const char*
) (__func__)), "ctk_tree_model_iter_next (tree_view->priv->model, &iter)"
); return (0); }; }while (0)
;
6940 ctk_tree_path_next (path);
6941 }
6942 else
6943 {
6944 ctk_tree_path_free (path);
6945 path = NULL((void*)0);
6946 }
6947 }
6948
6949 if (path == NULL((void*)0))
6950 {
6951 tree = tree_view->priv->tree;
6952 node = tree_view->priv->tree->root;
6953
6954 g_assert (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_DESCENDANTS_INVALID))do { if ((node?(((node->flags&CTK_RBNODE_DESCENDANTS_INVALID
)==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))) ; else g_assertion_message_expr
("Ctk", "ctktreeview.c", 6954, ((const char*) (__func__)), "CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_DESCENDANTS_INVALID)"
); } while (0)
;
6955
6956 do
6957 {
6958 if (!_ctk_rbtree_is_nil (node->left) &&
6959 CTK_RBNODE_FLAG_SET (node->left, CTK_RBNODE_DESCENDANTS_INVALID)(node->left?(((node->left->flags&CTK_RBNODE_DESCENDANTS_INVALID
)==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))
)
6960 {
6961 node = node->left;
6962 }
6963 else if (!_ctk_rbtree_is_nil (node->right) &&
6964 CTK_RBNODE_FLAG_SET (node->right, CTK_RBNODE_DESCENDANTS_INVALID)(node->right?(((node->right->flags&CTK_RBNODE_DESCENDANTS_INVALID
)==CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))
)
6965 {
6966 node = node->right;
6967 }
6968 else if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
||
6969 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_COLUMN_INVALID)(node?(((node->flags&CTK_RBNODE_COLUMN_INVALID)==CTK_RBNODE_COLUMN_INVALID
)?(!(0)):(0)):(0))
)
6970 {
6971 break;
6972 }
6973 else if (node->children != NULL((void*)0))
6974 {
6975 tree = node->children;
6976 node = tree->root;
6977 }
6978 else
6979 /* RBTree corruption! All bad */
6980 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktreeview.c", 6980, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
6981 }
6982 while (TRUE(!(0)));
6983 path = _ctk_tree_path_new_from_rbtree (tree, node);
6984 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6985 }
6986
6987 changed = validate_row (tree_view, tree, node, &iter, path);
6988 validated_area = changed || validated_area;
6989
6990 if (changed)
6991 {
6992 gint offset = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
6993
6994 if (y == -1 || y > offset)
6995 y = offset;
6996 }
6997
6998 if (!tree_view->priv->fixed_height_check)
6999 {
7000 gint height;
7001
7002 height = ctk_tree_view_get_row_height (tree_view, node);
7003 if (prev_height < 0)
7004 prev_height = height;
7005 else if (prev_height != height)
7006 fixed_height = FALSE(0);
7007 }
7008
7009 i++;
7010 }
7011 while (g_timer_elapsed (timer, NULL((void*)0)) < CTK_TREE_VIEW_TIME_MS_PER_IDLE10 / 1000.);
7012
7013 if (!tree_view->priv->fixed_height_check)
7014 {
7015 if (fixed_height)
7016 _ctk_rbtree_set_fixed_height (tree_view->priv->tree, prev_height, FALSE(0));
7017
7018 tree_view->priv->fixed_height_check = 1;
7019 }
7020
7021 done:
7022 if (validated_area)
7023 {
7024 CtkRequisition requisition;
7025 gint dummy;
7026
7027 /* We temporarily guess a size, under the assumption that it will be the
7028 * same when we get our next size_allocate. If we don't do this, we'll be
7029 * in an inconsistent state when we call top_row_to_dy. */
7030
7031 /* FIXME: This is called from size_request, for some reason it is not infinitely
7032 * recursing, we cannot call ctk_widget_get_preferred_size() here because that's
7033 * not allowed (from inside ->get_preferred_width/height() implementations, one
7034 * should call the vfuncs directly). However what is desired here is the full
7035 * size including any margins and limited by any alignment (i.e. after
7036 * CtkWidget:adjust_size_request() is called).
7037 *
7038 * Currently bypassing this but the real solution is to not update the scroll adjustments
7039 * untill we've recieved an allocation (never update scroll adjustments from size-requests).
7040 */
7041 prevent_recursion_hack = TRUE(!(0));
7042 ctk_tree_view_get_preferred_width (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &requisition.width, &dummy);
7043 ctk_tree_view_get_preferred_height (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &requisition.height, &dummy);
7044 prevent_recursion_hack = FALSE(0);
7045
7046 /* If rows above the current position have changed height, this has
7047 * affected the current view and thus needs a redraw.
7048 */
7049 if (y != -1 && y < ctk_adjustment_get_value (tree_view->priv->vadjustment))
7050 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
7051
7052 ctk_adjustment_set_upper (tree_view->priv->hadjustment,
7053 MAX (ctk_adjustment_get_upper (tree_view->priv->hadjustment), requisition.width)(((ctk_adjustment_get_upper (tree_view->priv->hadjustment
)) > (requisition.width)) ? (ctk_adjustment_get_upper (tree_view
->priv->hadjustment)) : (requisition.width))
);
7054 ctk_adjustment_set_upper (tree_view->priv->vadjustment,
7055 MAX (ctk_adjustment_get_upper (tree_view->priv->vadjustment), requisition.height)(((ctk_adjustment_get_upper (tree_view->priv->vadjustment
)) > (requisition.height)) ? (ctk_adjustment_get_upper (tree_view
->priv->vadjustment)) : (requisition.height))
);
7056
7057 if (queue_resize)
7058 ctk_widget_queue_resize_no_redraw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
7059 }
7060
7061 if (path) ctk_tree_path_free (path);
7062 g_timer_destroy (timer);
7063
7064 if (!retval && ctk_widget_get_mapped (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
7065 update_prelight (tree_view,
7066 tree_view->priv->event_last_x,
7067 tree_view->priv->event_last_y);
7068
7069 return retval;
7070}
7071
7072static void
7073disable_adjustment_animation (CtkTreeView *tree_view)
7074{
7075 ctk_adjustment_enable_animation (tree_view->priv->vadjustment,
7076 NULL((void*)0),
7077 ctk_adjustment_get_animation_duration (tree_view->priv->vadjustment));
7078}
7079
7080static void
7081maybe_reenable_adjustment_animation (CtkTreeView *tree_view)
7082{
7083 if (tree_view->priv->presize_handler_tick_cb != 0 ||
7084 tree_view->priv->validate_rows_timer != 0)
7085 return;
7086
7087 ctk_adjustment_enable_animation (tree_view->priv->vadjustment,
7088 ctk_widget_get_frame_clock (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
),
7089 ctk_adjustment_get_animation_duration (tree_view->priv->vadjustment));
7090}
7091
7092static gboolean
7093do_presize_handler (CtkTreeView *tree_view)
7094{
7095 if (tree_view->priv->mark_rows_col_dirty)
7096 {
7097 if (tree_view->priv->tree)
7098 _ctk_rbtree_column_invalid (tree_view->priv->tree);
7099 tree_view->priv->mark_rows_col_dirty = FALSE(0);
7100 }
7101 validate_visible_area (tree_view);
7102 if (tree_view->priv->presize_handler_tick_cb != 0)
7103 {
7104 ctk_widget_remove_tick_callback (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->presize_handler_tick_cb);
7105 tree_view->priv->presize_handler_tick_cb = 0;
7106 }
7107
7108 if (tree_view->priv->fixed_height_mode)
7109 {
7110 CtkRequisition requisition;
7111
7112 ctk_widget_get_preferred_size (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
7113 &requisition, NULL((void*)0));
7114
7115 ctk_adjustment_set_upper (tree_view->priv->hadjustment,
7116 MAX (ctk_adjustment_get_upper (tree_view->priv->hadjustment), requisition.width)(((ctk_adjustment_get_upper (tree_view->priv->hadjustment
)) > (requisition.width)) ? (ctk_adjustment_get_upper (tree_view
->priv->hadjustment)) : (requisition.width))
);
7117 ctk_adjustment_set_upper (tree_view->priv->vadjustment,
7118 MAX (ctk_adjustment_get_upper (tree_view->priv->vadjustment), requisition.height)(((ctk_adjustment_get_upper (tree_view->priv->vadjustment
)) > (requisition.height)) ? (ctk_adjustment_get_upper (tree_view
->priv->vadjustment)) : (requisition.height))
);
7119 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
7120 }
7121
7122 maybe_reenable_adjustment_animation (tree_view);
7123
7124 return FALSE(0);
7125}
7126
7127static gboolean
7128presize_handler_callback (CtkWidget *widget,
7129 CdkFrameClock *clock G_GNUC_UNUSED__attribute__ ((__unused__)),
7130 gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__)))
7131{
7132 do_presize_handler (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
7133
7134 return G_SOURCE_REMOVE(0);
7135}
7136
7137static gboolean
7138validate_rows (CtkTreeView *tree_view)
7139{
7140 gboolean retval;
7141
7142 if (tree_view->priv->presize_handler_tick_cb)
7143 {
7144 do_presize_handler (tree_view);
7145 return G_SOURCE_CONTINUE(!(0));
7146 }
7147
7148 retval = do_validate_rows (tree_view, TRUE(!(0)));
7149
7150 if (! retval && tree_view->priv->validate_rows_timer)
7151 {
7152 g_source_remove (tree_view->priv->validate_rows_timer);
7153 tree_view->priv->validate_rows_timer = 0;
7154 maybe_reenable_adjustment_animation (tree_view);
7155 }
7156
7157 return retval;
7158}
7159
7160static void
7161install_presize_handler (CtkTreeView *tree_view)
7162{
7163 if (! ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
7164 return;
7165
7166 disable_adjustment_animation (tree_view);
7167
7168 if (! tree_view->priv->presize_handler_tick_cb)
7169 {
7170 tree_view->priv->presize_handler_tick_cb =
7171 ctk_widget_add_tick_callback (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, presize_handler_callback, NULL((void*)0), NULL((void*)0));
7172 }
7173 if (! tree_view->priv->validate_rows_timer)
7174 {
7175 tree_view->priv->validate_rows_timer =
7176 cdk_threads_add_idle_full (CTK_TREE_VIEW_PRIORITY_VALIDATE((100 + 20) + 5), (GSourceFunc) validate_rows, tree_view, NULL((void*)0));
7177 g_source_set_name_by_id (tree_view->priv->validate_rows_timer, "[ctk+] validate_rows");
7178 }
7179}
7180
7181static gboolean
7182scroll_sync_handler (CtkTreeView *tree_view)
7183{
7184 if (ctk_tree_view_get_height (tree_view) <= ctk_adjustment_get_page_size (tree_view->priv->vadjustment))
7185 ctk_adjustment_set_value (CTK_ADJUSTMENT (tree_view->priv->vadjustment)((((CtkAdjustment*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->vadjustment)), ((ctk_adjustment_get_type
()))))))
, 0);
7186 else if (ctk_tree_row_reference_valid (tree_view->priv->top_row))
7187 ctk_tree_view_top_row_to_dy (tree_view);
7188 else
7189 ctk_tree_view_dy_to_top_row (tree_view);
7190
7191 tree_view->priv->scroll_sync_timer = 0;
7192
7193 return FALSE(0);
7194}
7195
7196static void
7197install_scroll_sync_handler (CtkTreeView *tree_view)
7198{
7199 if (!ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
7200 return;
7201
7202 if (!tree_view->priv->scroll_sync_timer)
7203 {
7204 tree_view->priv->scroll_sync_timer =
7205 cdk_threads_add_idle_full (CTK_TREE_VIEW_PRIORITY_SCROLL_SYNC(((100 + 20) + 5) + 2), (GSourceFunc) scroll_sync_handler, tree_view, NULL((void*)0));
7206 g_source_set_name_by_id (tree_view->priv->scroll_sync_timer, "[ctk+] scroll_sync_handler");
7207 }
7208}
7209
7210static void
7211ctk_tree_view_set_top_row (CtkTreeView *tree_view,
7212 CtkTreePath *path,
7213 gint offset)
7214{
7215 ctk_tree_row_reference_free (tree_view->priv->top_row);
7216
7217 if (!path)
7218 {
7219 tree_view->priv->top_row = NULL((void*)0);
7220 tree_view->priv->top_row_dy = 0;
7221 }
7222 else
7223 {
7224 tree_view->priv->top_row = ctk_tree_row_reference_new_proxy (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view->priv->model, path);
7225 tree_view->priv->top_row_dy = offset;
7226 }
7227}
7228
7229/* Always call this iff dy is in the visible range. If the tree is empty, then
7230 * it’s set to be NULL, and top_row_dy is 0;
7231 */
7232static void
7233ctk_tree_view_dy_to_top_row (CtkTreeView *tree_view)
7234{
7235 gint offset;
7236 CtkTreePath *path;
7237 CtkRBTree *tree;
7238 CtkRBNode *node;
7239
7240 if (tree_view->priv->tree == NULL((void*)0))
7241 {
7242 ctk_tree_view_set_top_row (tree_view, NULL((void*)0), 0);
7243 }
7244 else
7245 {
7246 offset = _ctk_rbtree_find_offset (tree_view->priv->tree,
7247 tree_view->priv->dy,
7248 &tree, &node);
7249
7250 if (tree == NULL((void*)0))
7251 {
7252 ctk_tree_view_set_top_row (tree_view, NULL((void*)0), 0);
7253 }
7254 else
7255 {
7256 path = _ctk_tree_path_new_from_rbtree (tree, node);
7257 ctk_tree_view_set_top_row (tree_view, path, offset);
7258 ctk_tree_path_free (path);
7259 }
7260 }
7261}
7262
7263static void
7264ctk_tree_view_top_row_to_dy (CtkTreeView *tree_view)
7265{
7266 CtkTreePath *path;
7267 CtkRBTree *tree;
7268 CtkRBNode *node;
7269 int new_dy;
7270
7271 /* Avoid recursive calls */
7272 if (tree_view->priv->in_top_row_to_dy)
7273 return;
7274
7275 if (tree_view->priv->top_row)
7276 path = ctk_tree_row_reference_get_path (tree_view->priv->top_row);
7277 else
7278 path = NULL((void*)0);
7279
7280 if (!path)
7281 tree = NULL((void*)0);
7282 else
7283 _ctk_tree_view_find_node (tree_view, path, &tree, &node);
7284
7285 if (path)
7286 ctk_tree_path_free (path);
7287
7288 if (tree == NULL((void*)0))
7289 {
7290 /* keep dy and set new toprow */
7291 ctk_tree_row_reference_free (tree_view->priv->top_row);
7292 tree_view->priv->top_row = NULL((void*)0);
7293 tree_view->priv->top_row_dy = 0;
7294 /* DO NOT install the idle handler */
7295 ctk_tree_view_dy_to_top_row (tree_view);
7296 return;
7297 }
7298
7299 if (ctk_tree_view_get_row_height (tree_view, node)
7300 < tree_view->priv->top_row_dy)
7301 {
7302 /* new top row -- do NOT install the idle handler */
7303 ctk_tree_view_dy_to_top_row (tree_view);
7304 return;
7305 }
7306
7307 new_dy = _ctk_rbtree_node_find_offset (tree, node);
7308 new_dy += tree_view->priv->top_row_dy;
7309
7310 if (new_dy + ctk_adjustment_get_page_size (tree_view->priv->vadjustment) > ctk_tree_view_get_height (tree_view))
7311 new_dy = ctk_tree_view_get_height (tree_view) - ctk_adjustment_get_page_size (tree_view->priv->vadjustment);
7312
7313 new_dy = MAX (0, new_dy)(((0) > (new_dy)) ? (0) : (new_dy));
7314
7315 tree_view->priv->in_top_row_to_dy = TRUE(!(0));
7316 ctk_adjustment_set_value (tree_view->priv->vadjustment, (gdouble)new_dy);
7317 tree_view->priv->in_top_row_to_dy = FALSE(0);
7318}
7319
7320
7321void
7322_ctk_tree_view_install_mark_rows_col_dirty (CtkTreeView *tree_view,
7323 gboolean install_handler)
7324{
7325 tree_view->priv->mark_rows_col_dirty = TRUE(!(0));
7326
7327 if (install_handler)
7328 install_presize_handler (tree_view);
7329}
7330
7331/*
7332 * This function works synchronously (due to the while (validate_rows...)
7333 * loop).
7334 *
7335 * There was a check for column_type != CTK_TREE_VIEW_COLUMN_AUTOSIZE
7336 * here. You now need to check that yourself.
7337 */
7338void
7339_ctk_tree_view_column_autosize (CtkTreeView *tree_view,
7340 CtkTreeViewColumn *column)
7341{
7342 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
7343 g_return_if_fail (CTK_IS_TREE_VIEW_COLUMN (column))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((column)); GType __t = ((ctk_tree_view_column_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_VIEW_COLUMN (column)"); return
; } } while (0)
;
7344
7345 _ctk_tree_view_column_cell_set_dirty (column, FALSE(0));
7346
7347 do_presize_handler (tree_view);
7348 while (validate_rows (tree_view));
7349
7350 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
7351}
7352
7353/* Drag-and-drop */
7354
7355static void
7356set_source_row (CdkDragContext *context,
7357 CtkTreeModel *model,
7358 CtkTreePath *source_row)
7359{
7360 g_object_set_data_full (G_OBJECT (context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context)), (((GType) ((20) << (2))))))))
,
7361 I_("ctk-tree-view-source-row")g_intern_static_string ("ctk-tree-view-source-row"),
7362 source_row ? ctk_tree_row_reference_new (model, source_row) : NULL((void*)0),
7363 (GDestroyNotify) (source_row ? ctk_tree_row_reference_free : NULL((void*)0)));
7364}
7365
7366static CtkTreePath*
7367get_source_row (CdkDragContext *context)
7368{
7369 CtkTreeRowReference *ref =
7370 g_object_get_data (G_OBJECT (context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context)), (((GType) ((20) << (2))))))))
, "ctk-tree-view-source-row");
7371
7372 if (ref)
7373 return ctk_tree_row_reference_get_path (ref);
7374 else
7375 return NULL((void*)0);
7376}
7377
7378typedef struct
7379{
7380 CtkTreeRowReference *dest_row;
7381 guint path_down_mode : 1;
7382 guint empty_view_drop : 1;
7383 guint drop_append_mode : 1;
7384}
7385DestRow;
7386
7387static void
7388dest_row_free (gpointer data)
7389{
7390 DestRow *dr = (DestRow *)data;
7391
7392 ctk_tree_row_reference_free (dr->dest_row);
7393 g_slice_free (DestRow, dr)do { if (1) g_slice_free1 (sizeof (DestRow), (dr)); else (void
) ((DestRow*) 0 == (dr)); } while (0)
;
7394}
7395
7396static void
7397set_dest_row (CdkDragContext *context,
7398 CtkTreeModel *model,
7399 CtkTreePath *dest_row,
7400 gboolean path_down_mode,
7401 gboolean empty_view_drop,
7402 gboolean drop_append_mode)
7403{
7404 DestRow *dr;
7405
7406 if (!dest_row)
7407 {
7408 g_object_set_data_full (G_OBJECT (context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context)), (((GType) ((20) << (2))))))))
, I_("ctk-tree-view-dest-row")g_intern_static_string ("ctk-tree-view-dest-row"),
7409 NULL((void*)0), NULL((void*)0));
7410 return;
7411 }
7412
7413 dr = g_slice_new (DestRow)((DestRow*) g_slice_alloc (sizeof (DestRow)));
7414
7415 dr->dest_row = ctk_tree_row_reference_new (model, dest_row);
7416 dr->path_down_mode = path_down_mode != FALSE(0);
7417 dr->empty_view_drop = empty_view_drop != FALSE(0);
7418 dr->drop_append_mode = drop_append_mode != FALSE(0);
7419
7420 g_object_set_data_full (G_OBJECT (context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context)), (((GType) ((20) << (2))))))))
, I_("ctk-tree-view-dest-row")g_intern_static_string ("ctk-tree-view-dest-row"),
7421 dr, (GDestroyNotify) dest_row_free);
7422}
7423
7424static CtkTreePath*
7425get_dest_row (CdkDragContext *context,
7426 gboolean *path_down_mode)
7427{
7428 DestRow *dr =
7429 g_object_get_data (G_OBJECT (context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context)), (((GType) ((20) << (2))))))))
, "ctk-tree-view-dest-row");
7430
7431 if (dr)
7432 {
7433 CtkTreePath *path = NULL((void*)0);
7434
7435 if (path_down_mode)
7436 *path_down_mode = dr->path_down_mode;
7437
7438 if (dr->dest_row)
7439 path = ctk_tree_row_reference_get_path (dr->dest_row);
7440 else if (dr->empty_view_drop)
7441 path = ctk_tree_path_new_from_indices (0, -1);
7442 else
7443 path = NULL((void*)0);
7444
7445 if (path && dr->drop_append_mode)
7446 ctk_tree_path_next (path);
7447
7448 return path;
7449 }
7450 else
7451 return NULL((void*)0);
7452}
7453
7454/* Get/set whether drag_motion requested the drag data and
7455 * drag_data_received should thus not actually insert the data,
7456 * since the data doesn’t result from a drop.
7457 */
7458static void
7459set_status_pending (CdkDragContext *context,
7460 CdkDragAction suggested_action)
7461{
7462 g_object_set_data (G_OBJECT (context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context)), (((GType) ((20) << (2))))))))
,
7463 I_("ctk-tree-view-status-pending")g_intern_static_string ("ctk-tree-view-status-pending"),
7464 GINT_TO_POINTER (suggested_action)((gpointer) (glong) (suggested_action)));
7465}
7466
7467static CdkDragAction
7468get_status_pending (CdkDragContext *context)
7469{
7470 return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), (((GType) ((20) << (2))
)))))), "ctk-tree-view-status-pending")))
7471 "ctk-tree-view-status-pending"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), (((GType) ((20) << (2))
)))))), "ctk-tree-view-status-pending")))
;
7472}
7473
7474static TreeViewDragInfo*
7475get_info (CtkTreeView *tree_view)
7476{
7477 return g_object_get_data (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, "ctk-tree-view-drag-info");
7478}
7479
7480static void
7481destroy_info (TreeViewDragInfo *di)
7482{
7483 g_slice_free (TreeViewDragInfo, di)do { if (1) g_slice_free1 (sizeof (TreeViewDragInfo), (di)); else
(void) ((TreeViewDragInfo*) 0 == (di)); } while (0)
;
7484}
7485
7486static TreeViewDragInfo*
7487ensure_info (CtkTreeView *tree_view)
7488{
7489 TreeViewDragInfo *di;
7490
7491 di = get_info (tree_view);
7492
7493 if (di == NULL((void*)0))
7494 {
7495 di = g_slice_new0 (TreeViewDragInfo)((TreeViewDragInfo*) g_slice_alloc0 (sizeof (TreeViewDragInfo
)))
;
7496
7497 g_object_set_data_full (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
,
7498 I_("ctk-tree-view-drag-info")g_intern_static_string ("ctk-tree-view-drag-info"),
7499 di,
7500 (GDestroyNotify) destroy_info);
7501 }
7502
7503 return di;
7504}
7505
7506static void
7507remove_info (CtkTreeView *tree_view)
7508{
7509 g_object_set_data (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, I_("ctk-tree-view-drag-info")g_intern_static_string ("ctk-tree-view-drag-info"), NULL((void*)0));
7510}
7511
7512#if 0
7513static gint
7514drag_scan_timeout (gpointer data)
7515{
7516 CtkTreeView *tree_view;
7517 gint x, y;
7518 CdkModifierType state;
7519 CtkTreePath *path = NULL((void*)0);
7520 CtkTreeViewColumn *column = NULL((void*)0);
7521 CdkRectangle visible_rect;
7522 CdkSeat *seat;
7523
7524 cdk_threads_enter ();
7525
7526 tree_view = CTK_TREE_VIEW (data)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_view_get_type ()))))))
;
7527
7528 seat = cdk_display_get_default_seat (ctk_widget_get_display (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
));
7529 cdk_window_get_device_position (tree_view->priv->bin_window,
7530 cdk_seat_get_pointer (seat),
7531 &x, &y, &state);
7532
7533 ctk_tree_view_get_visible_rect (tree_view, &visible_rect);
7534
7535 /* See if we are near the edge. */
7536 if ((x - visible_rect.x) < SCROLL_EDGE_SIZE15 ||
7537 (visible_rect.x + visible_rect.width - x) < SCROLL_EDGE_SIZE15 ||
7538 (y - visible_rect.y) < SCROLL_EDGE_SIZE15 ||
7539 (visible_rect.y + visible_rect.height - y) < SCROLL_EDGE_SIZE15)
7540 {
7541 ctk_tree_view_get_path_at_pos (tree_view,
7542 tree_view->priv->bin_window,
7543 x, y,
7544 &path,
7545 &column,
7546 NULL((void*)0),
7547 NULL((void*)0));
7548
7549 if (path != NULL((void*)0))
7550 {
7551 ctk_tree_view_scroll_to_cell (tree_view,
7552 path,
7553 column,
7554 TRUE(!(0)),
7555 0.5, 0.5);
7556
7557 ctk_tree_path_free (path);
7558 }
7559 }
7560
7561 cdk_threads_leave ();
7562
7563 return TRUE(!(0));
7564}
7565#endif /* 0 */
7566
7567static void
7568add_scroll_timeout (CtkTreeView *tree_view)
7569{
7570 if (tree_view->priv->scroll_timeout == 0)
7571 {
7572 tree_view->priv->scroll_timeout =
7573 cdk_threads_add_timeout (150, scroll_row_timeout, tree_view);
7574 g_source_set_name_by_id (tree_view->priv->scroll_timeout, "[ctk+] scroll_row_timeout");
7575 }
7576}
7577
7578static void
7579remove_scroll_timeout (CtkTreeView *tree_view)
7580{
7581 if (tree_view->priv->scroll_timeout != 0)
7582 {
7583 g_source_remove (tree_view->priv->scroll_timeout);
7584 tree_view->priv->scroll_timeout = 0;
7585 }
7586}
7587
7588static gboolean
7589check_model_dnd (CtkTreeModel *model,
7590 GType required_iface,
7591 const gchar *signal)
7592{
7593 if (model == NULL((void*)0) || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(model)); GType __t = (required_iface); gboolean __r; if (!__inst
) __r = (0); else if (__inst->g_class && __inst->
g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a
(__inst, __t); __r; })))
)
7594 {
7595 g_warning ("You must override the default '%s' handler "
7596 "on CtkTreeView when using models that don't support "
7597 "the %s interface and enabling drag-and-drop. The simplest way to do this "
7598 "is to connect to '%s' and call "
7599 "g_signal_stop_emission_by_name() in your signal handler to prevent "
7600 "the default handler from running. Look at the source code "
7601 "for the default handler in ctktreeview.c to get an idea what "
7602 "your handler should do. (ctktreeview.c is in the CTK source "
7603 "code.) If you're using CTK from a language other than C, "
7604 "there may be a more natural way to override default handlers, e.g. via derivation.",
7605 signal, g_type_name (required_iface), signal);
7606 return FALSE(0);
7607 }
7608 else
7609 return TRUE(!(0));
7610}
7611
7612static void
7613remove_open_timeout (CtkTreeView *tree_view)
7614{
7615 if (tree_view->priv->open_dest_timeout != 0)
7616 {
7617 g_source_remove (tree_view->priv->open_dest_timeout);
7618 tree_view->priv->open_dest_timeout = 0;
7619 }
7620}
7621
7622
7623static gint
7624open_row_timeout (gpointer data)
7625{
7626 CtkTreeView *tree_view = data;
7627 CtkTreePath *dest_path = NULL((void*)0);
7628 CtkTreeViewDropPosition pos;
7629 gboolean result = FALSE(0);
7630
7631 ctk_tree_view_get_drag_dest_row (tree_view,
7632 &dest_path,
7633 &pos);
7634
7635 if (dest_path &&
7636 (pos == CTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
7637 pos == CTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
7638 {
7639 ctk_tree_view_expand_row (tree_view, dest_path, FALSE(0));
7640 tree_view->priv->open_dest_timeout = 0;
7641
7642 ctk_tree_path_free (dest_path);
7643 }
7644 else
7645 {
7646 if (dest_path)
7647 ctk_tree_path_free (dest_path);
7648
7649 result = TRUE(!(0));
7650 }
7651
7652 return result;
7653}
7654
7655static gboolean
7656scroll_row_timeout (gpointer data)
7657{
7658 CtkTreeView *tree_view = data;
7659
7660 ctk_tree_view_vertical_autoscroll (tree_view);
7661
7662 if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
1
Assuming field 'rubber_band_status' is equal to RUBBER_BAND_ACTIVE
2
Taking true branch
7663 ctk_tree_view_update_rubber_band (tree_view);
3
Calling 'ctk_tree_view_update_rubber_band'
7664
7665 return TRUE(!(0));
7666}
7667
7668/* Returns TRUE if event should not be propagated to parent widgets */
7669static gboolean
7670set_destination_row (CtkTreeView *tree_view,
7671 CdkDragContext *context,
7672 /* coordinates relative to the widget */
7673 gint x,
7674 gint y,
7675 CdkDragAction *suggested_action,
7676 CdkAtom *target)
7677{
7678 CtkTreePath *path = NULL((void*)0);
7679 CtkTreeViewDropPosition pos;
7680 CtkTreeViewDropPosition old_pos;
7681 TreeViewDragInfo *di;
7682 CtkWidget *widget;
7683 CtkTreePath *old_dest_path = NULL((void*)0);
7684 gboolean can_drop = FALSE(0);
7685
7686 *suggested_action = 0;
7687 *target = CDK_NONE((CdkAtom)((gpointer) (gulong) (0)));
7688
7689 widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
7690
7691 di = get_info (tree_view);
7692
7693 if (di == NULL((void*)0) || y - ctk_tree_view_get_effective_header_height (tree_view) < 0)
7694 {
7695 /* someone unset us as a drag dest, note that if
7696 * we return FALSE drag_leave isn't called
7697 */
7698
7699 ctk_tree_view_set_drag_dest_row (tree_view,
7700 NULL((void*)0),
7701 CTK_TREE_VIEW_DROP_BEFORE);
7702
7703 remove_scroll_timeout (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
7704 remove_open_timeout (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
7705
7706 return FALSE(0); /* no longer a drop site */
7707 }
7708
7709 *target = ctk_drag_dest_find_target (widget, context,
7710 ctk_drag_dest_get_target_list (widget));
7711 if (*target == CDK_NONE((CdkAtom)((gpointer) (gulong) (0))))
7712 {
7713 return FALSE(0);
7714 }
7715
7716 if (!ctk_tree_view_get_dest_row_at_pos (tree_view,
7717 x, y,
7718 &path,
7719 &pos))
7720 {
7721 gint n_children;
7722 CtkTreeModel *model;
7723
7724 remove_open_timeout (tree_view);
7725
7726 /* the row got dropped on empty space, let's setup a special case
7727 */
7728
7729 if (path)
7730 ctk_tree_path_free (path);
7731
7732 model = ctk_tree_view_get_model (tree_view);
7733
7734 n_children = ctk_tree_model_iter_n_children (model, NULL((void*)0));
7735 if (n_children)
7736 {
7737 pos = CTK_TREE_VIEW_DROP_AFTER;
7738 path = ctk_tree_path_new_from_indices (n_children - 1, -1);
7739 }
7740 else
7741 {
7742 pos = CTK_TREE_VIEW_DROP_BEFORE;
7743 path = ctk_tree_path_new_from_indices (0, -1);
7744 }
7745
7746 can_drop = TRUE(!(0));
7747
7748 goto out;
7749 }
7750
7751 g_assert (path)do { if (path) ; else g_assertion_message_expr ("Ctk", "ctktreeview.c"
, 7751, ((const char*) (__func__)), "path"); } while (0)
;
7752
7753 /* If we left the current row's "open" zone, unset the timeout for
7754 * opening the row
7755 */
7756 ctk_tree_view_get_drag_dest_row (tree_view,
7757 &old_dest_path,
7758 &old_pos);
7759
7760 if (old_dest_path &&
7761 (ctk_tree_path_compare (path, old_dest_path) != 0 ||
7762 !(pos == CTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
7763 pos == CTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
7764 remove_open_timeout (tree_view);
7765
7766 if (old_dest_path)
7767 ctk_tree_path_free (old_dest_path);
7768
7769 if (TRUE(!(0)) /* FIXME if the location droppable predicate */)
7770 {
7771 can_drop = TRUE(!(0));
7772 }
7773
7774out:
7775 if (can_drop)
7776 {
7777 CtkWidget *source_widget;
7778
7779 *suggested_action = cdk_drag_context_get_suggested_action (context);
7780 source_widget = ctk_drag_get_source_widget (context);
7781
7782 if (source_widget == widget)
7783 {
7784 /* Default to MOVE, unless the user has
7785 * pressed ctrl or shift to affect available actions
7786 */
7787 if ((cdk_drag_context_get_actions (context) & CDK_ACTION_MOVE) != 0)
7788 *suggested_action = CDK_ACTION_MOVE;
7789 }
7790
7791 ctk_tree_view_set_drag_dest_row (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
,
7792 path, pos);
7793 }
7794 else
7795 {
7796 /* can't drop here */
7797 remove_open_timeout (tree_view);
7798
7799 ctk_tree_view_set_drag_dest_row (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
,
7800 NULL((void*)0),
7801 CTK_TREE_VIEW_DROP_BEFORE);
7802 }
7803
7804 if (path)
7805 ctk_tree_path_free (path);
7806
7807 return TRUE(!(0));
7808}
7809
7810static CtkTreePath*
7811get_logical_dest_row (CtkTreeView *tree_view,
7812 gboolean *path_down_mode,
7813 gboolean *drop_append_mode)
7814{
7815 /* adjust path to point to the row the drop goes in front of */
7816 CtkTreePath *path = NULL((void*)0);
7817 CtkTreeViewDropPosition pos;
7818
7819 g_return_val_if_fail (path_down_mode != NULL, NULL)do { if ((path_down_mode != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path_down_mode != NULL"
); return (((void*)0)); } } while (0)
;
7820 g_return_val_if_fail (drop_append_mode != NULL, NULL)do { if ((drop_append_mode != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "drop_append_mode != NULL"
); return (((void*)0)); } } while (0)
;
7821
7822 *path_down_mode = FALSE(0);
7823 *drop_append_mode = 0;
7824
7825 ctk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
7826
7827 if (path == NULL((void*)0))
7828 return NULL((void*)0);
7829
7830 if (pos == CTK_TREE_VIEW_DROP_BEFORE)
7831 ; /* do nothing */
7832 else if (pos == CTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
7833 pos == CTK_TREE_VIEW_DROP_INTO_OR_AFTER)
7834 *path_down_mode = TRUE(!(0));
7835 else
7836 {
7837 CtkTreeIter iter;
7838 CtkTreeModel *model = ctk_tree_view_get_model (tree_view);
7839
7840 g_assert (pos == CTK_TREE_VIEW_DROP_AFTER)do { if (pos == CTK_TREE_VIEW_DROP_AFTER) ; else g_assertion_message_expr
("Ctk", "ctktreeview.c", 7840, ((const char*) (__func__)), "pos == CTK_TREE_VIEW_DROP_AFTER"
); } while (0)
;
7841
7842 if (!ctk_tree_model_get_iter (model, &iter, path) ||
7843 !ctk_tree_model_iter_next (model, &iter))
7844 *drop_append_mode = 1;
7845 else
7846 {
7847 *drop_append_mode = 0;
7848 ctk_tree_path_next (path);
7849 }
7850 }
7851
7852 return path;
7853}
7854
7855static gboolean
7856ctk_tree_view_maybe_begin_dragging_row (CtkTreeView *tree_view)
7857{
7858 CtkWidget *widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
7859 gdouble start_x, start_y, offset_x, offset_y;
7860 CdkEventSequence *sequence;
7861 const CdkEvent *event;
7862 CdkDragContext *context;
7863 TreeViewDragInfo *di;
7864 CtkTreePath *path = NULL((void*)0);
7865 gint button;
7866 CtkTreeModel *model;
7867 gboolean retval = FALSE(0);
7868 gint bin_x, bin_y;
7869
7870 di = get_info (tree_view);
7871
7872 if (di == NULL((void*)0) || !di->source_set)
7873 goto out;
7874
7875 if (!ctk_gesture_is_recognized (tree_view->priv->drag_gesture))
7876 goto out;
7877
7878 ctk_gesture_drag_get_start_point (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
7879 &start_x, &start_y);
7880 ctk_gesture_drag_get_offset (CTK_GESTURE_DRAG (tree_view->priv->drag_gesture)((((CtkGestureDrag*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_drag_get_type
()))))))
,
7881 &offset_x, &offset_y);
7882
7883 if (!ctk_drag_check_threshold (widget, 0, 0, offset_x, offset_y))
7884 goto out;
7885
7886 model = ctk_tree_view_get_model (tree_view);
7887
7888 if (model == NULL((void*)0))
7889 goto out;
7890
7891 button = ctk_gesture_single_get_current_button (CTK_GESTURE_SINGLE (tree_view->priv->drag_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_single_get_type
()))))))
);
7892
7893 /* Deny the multipress gesture */
7894 ctk_gesture_set_state (CTK_GESTURE (tree_view->priv->multipress_gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->multipress_gesture)), ((ctk_gesture_get_type
()))))))
,
7895 CTK_EVENT_SEQUENCE_DENIED);
7896
7897 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, start_x, start_y,
7898 &bin_x, &bin_y);
7899 ctk_tree_view_get_path_at_pos (tree_view, bin_x, bin_y, &path,
7900 NULL((void*)0), NULL((void*)0), NULL((void*)0));
7901
7902 if (path == NULL((void*)0))
7903 goto out;
7904
7905 if (!CTK_IS_TREE_DRAG_SOURCE (model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(model)); GType __t = ((ctk_tree_drag_source_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
||
7906 !ctk_tree_drag_source_row_draggable (CTK_TREE_DRAG_SOURCE (model)((((CtkTreeDragSource*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_drag_source_get_type (
)))))))
,
7907 path))
7908 goto out;
7909
7910 if (!(CDK_BUTTON1_MASK << (button - 1) & di->start_button_mask))
7911 goto out;
7912
7913 retval = TRUE(!(0));
7914
7915 /* Now we can begin the drag */
7916 ctk_gesture_set_state (CTK_GESTURE (tree_view->priv->drag_gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_get_type
()))))))
,
7917 CTK_EVENT_SEQUENCE_CLAIMED);
7918 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (tree_view->priv->drag_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_single_get_type
()))))))
);
7919 event = ctk_gesture_get_last_event (CTK_GESTURE (tree_view->priv->drag_gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->drag_gesture)), ((ctk_gesture_get_type
()))))))
, sequence);
7920
7921 context = ctk_drag_begin_with_coordinates (widget,
7922 ctk_drag_source_get_target_list (widget),
7923 di->source_actions,
7924 button,
7925 (CdkEvent*)event,
7926 start_x, start_y);
7927
7928 set_source_row (context, model, path);
7929
7930 out:
7931 if (path)
7932 ctk_tree_path_free (path);
7933
7934 return retval;
7935}
7936
7937
7938static void
7939ctk_tree_view_drag_begin (CtkWidget *widget,
7940 CdkDragContext *context)
7941{
7942 CtkTreeView *tree_view;
7943 CtkTreePath *path = NULL((void*)0);
7944 gint cell_x, cell_y;
7945 cairo_surface_t *row_pix;
7946 TreeViewDragInfo *di;
7947 double sx, sy;
7948
7949 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
7950
7951 /* if the user uses a custom DND source impl, we don't set the icon here */
7952 di = get_info (tree_view);
7953
7954 if (di == NULL((void*)0) || !di->source_set)
7955 return;
7956
7957 ctk_tree_view_get_path_at_pos (tree_view,
7958 tree_view->priv->press_start_x,
7959 tree_view->priv->press_start_y,
7960 &path,
7961 NULL((void*)0),
7962 &cell_x,
7963 &cell_y);
7964
7965 /* If path is NULL, there's nothing we can drag. For now, we silently
7966 * bail out. Actually, dragging should not be possible from an empty
7967 * tree view, but there's no way we can cancel that from here.
7968 * Automatically unsetting the tree view as drag source for empty models
7969 * is something that would likely break other people's code ...
7970 */
7971 if (!path)
7972 return;
7973
7974 row_pix = ctk_tree_view_create_row_drag_icon (tree_view,
7975 path);
7976 cairo_surface_get_device_scale (row_pix, &sx, &sy);
7977 cairo_surface_set_device_offset (row_pix,
7978 /* the + 1 is for the black border in the icon */
7979 - (tree_view->priv->press_start_x + 1) * sx,
7980 - (cell_y + 1) * sy);
7981
7982 ctk_drag_set_icon_surface (context, row_pix);
7983
7984 cairo_surface_destroy (row_pix);
7985 ctk_tree_path_free (path);
7986}
7987
7988static void
7989ctk_tree_view_drag_end (CtkWidget *widget,
7990 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)))
7991{
7992 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
7993
7994 tree_view->priv->event_last_x = -10000;
7995 tree_view->priv->event_last_y = -10000;
7996}
7997
7998/* Default signal implementations for the drag signals */
7999static void
8000ctk_tree_view_drag_data_get (CtkWidget *widget,
8001 CdkDragContext *context,
8002 CtkSelectionData *selection_data,
8003 guint info G_GNUC_UNUSED__attribute__ ((__unused__)),
8004 guint time G_GNUC_UNUSED__attribute__ ((__unused__)))
8005{
8006 CtkTreeView *tree_view;
8007 CtkTreeModel *model;
8008 TreeViewDragInfo *di;
8009 CtkTreePath *source_row;
8010
8011 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8012
8013 model = ctk_tree_view_get_model (tree_view);
8014
8015 if (model == NULL((void*)0))
8016 return;
8017
8018 di = get_info (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
8019
8020 if (di == NULL((void*)0))
8021 return;
8022
8023 source_row = get_source_row (context);
8024
8025 if (source_row == NULL((void*)0))
8026 return;
8027
8028 /* We can implement the CTK_TREE_MODEL_ROW target generically for
8029 * any model; for DragSource models there are some other targets
8030 * we also support.
8031 */
8032
8033 if (CTK_IS_TREE_DRAG_SOURCE (model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(model)); GType __t = ((ctk_tree_drag_source_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
&&
8034 ctk_tree_drag_source_drag_data_get (CTK_TREE_DRAG_SOURCE (model)((((CtkTreeDragSource*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_drag_source_get_type (
)))))))
,
8035 source_row,
8036 selection_data))
8037 goto done;
8038
8039 /* If drag_data_get does nothing, try providing row data. */
8040 if (ctk_selection_data_get_target (selection_data) == cdk_atom_intern_static_string ("CTK_TREE_MODEL_ROW"))
8041 {
8042 ctk_tree_set_row_drag_data (selection_data,
8043 model,
8044 source_row);
8045 }
8046
8047 done:
8048 ctk_tree_path_free (source_row);
8049}
8050
8051
8052static void
8053ctk_tree_view_drag_data_delete (CtkWidget *widget,
8054 CdkDragContext *context)
8055{
8056 TreeViewDragInfo *di;
8057 CtkTreeModel *model;
8058 CtkTreeView *tree_view;
8059 CtkTreePath *source_row;
8060
8061 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8062 model = ctk_tree_view_get_model (tree_view);
8063
8064 if (!check_model_dnd (model, CTK_TYPE_TREE_DRAG_SOURCE(ctk_tree_drag_source_get_type ()), "drag_data_delete"))
8065 return;
8066
8067 di = get_info (tree_view);
8068
8069 if (di == NULL((void*)0))
8070 return;
8071
8072 source_row = get_source_row (context);
8073
8074 if (source_row == NULL((void*)0))
8075 return;
8076
8077 ctk_tree_drag_source_drag_data_delete (CTK_TREE_DRAG_SOURCE (model)((((CtkTreeDragSource*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_drag_source_get_type (
)))))))
,
8078 source_row);
8079
8080 ctk_tree_path_free (source_row);
8081
8082 set_source_row (context, NULL((void*)0), NULL((void*)0));
8083}
8084
8085static void
8086ctk_tree_view_drag_leave (CtkWidget *widget,
8087 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
8088 guint time G_GNUC_UNUSED__attribute__ ((__unused__)))
8089{
8090 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8091
8092 /* unset any highlight row */
8093 ctk_tree_view_set_drag_dest_row (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
,
8094 NULL((void*)0),
8095 CTK_TREE_VIEW_DROP_BEFORE);
8096
8097 remove_scroll_timeout (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
8098 remove_open_timeout (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
8099
8100 tree_view->priv->event_last_x = -10000;
8101 tree_view->priv->event_last_y = -10000;
8102}
8103
8104
8105static gboolean
8106ctk_tree_view_drag_motion (CtkWidget *widget,
8107 CdkDragContext *context,
8108 /* coordinates relative to the widget */
8109 gint x,
8110 gint y,
8111 guint time)
8112{
8113 gboolean empty;
8114 CtkTreePath *path = NULL((void*)0);
8115 CtkTreeViewDropPosition pos;
8116 CtkTreeView *tree_view;
8117 CdkDragAction suggested_action = 0;
8118 CdkAtom target;
8119
8120 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8121
8122 if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
8123 return FALSE(0);
8124
8125 tree_view->priv->event_last_x = x;
8126 tree_view->priv->event_last_y = y;
8127
8128 ctk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
8129
8130 /* we only know this *after* set_desination_row */
8131 empty = tree_view->priv->empty_view_drop;
8132
8133 if (path == NULL((void*)0) && !empty)
8134 {
8135 /* Can't drop here. */
8136 cdk_drag_status (context, 0, time);
8137 }
8138 else
8139 {
8140 if (tree_view->priv->open_dest_timeout == 0 &&
8141 (pos == CTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
8142 pos == CTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
8143 {
8144 tree_view->priv->open_dest_timeout =
8145 cdk_threads_add_timeout (AUTO_EXPAND_TIMEOUT500, open_row_timeout, tree_view);
8146 g_source_set_name_by_id (tree_view->priv->open_dest_timeout, "[ctk+] open_row_timeout");
8147 }
8148 else
8149 {
8150 add_scroll_timeout (tree_view);
8151 }
8152
8153 if (target == cdk_atom_intern_static_string ("CTK_TREE_MODEL_ROW"))
8154 {
8155 /* Request data so we can use the source row when
8156 * determining whether to accept the drop
8157 */
8158 set_status_pending (context, suggested_action);
8159 ctk_drag_get_data (widget, context, target, time);
8160 }
8161 else
8162 {
8163 set_status_pending (context, 0);
8164 cdk_drag_status (context, suggested_action, time);
8165 }
8166 }
8167
8168 if (path)
8169 ctk_tree_path_free (path);
8170
8171 return TRUE(!(0));
8172}
8173
8174
8175static gboolean
8176ctk_tree_view_drag_drop (CtkWidget *widget,
8177 CdkDragContext *context,
8178 /* coordinates relative to the widget */
8179 gint x,
8180 gint y,
8181 guint time)
8182{
8183 CtkTreeView *tree_view;
8184 CtkTreePath *path;
8185 CdkDragAction suggested_action = 0;
8186 CdkAtom target = CDK_NONE((CdkAtom)((gpointer) (gulong) (0)));
8187 TreeViewDragInfo *di;
8188 CtkTreeModel *model;
8189 gboolean path_down_mode;
8190 gboolean drop_append_mode;
8191
8192 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8193
8194 model = ctk_tree_view_get_model (tree_view);
8195
8196 remove_scroll_timeout (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
8197 remove_open_timeout (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
8198
8199 di = get_info (tree_view);
8200
8201 if (di == NULL((void*)0))
8202 return FALSE(0);
8203
8204 if (!check_model_dnd (model, CTK_TYPE_TREE_DRAG_DEST(ctk_tree_drag_dest_get_type ()), "drag_drop"))
8205 return FALSE(0);
8206
8207 if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
8208 return FALSE(0);
8209
8210 path = get_logical_dest_row (tree_view, &path_down_mode, &drop_append_mode);
8211
8212 if (target != CDK_NONE((CdkAtom)((gpointer) (gulong) (0))) && path != NULL((void*)0))
8213 {
8214 /* in case a motion had requested drag data, change things so we
8215 * treat drag data receives as a drop.
8216 */
8217 set_status_pending (context, 0);
8218 set_dest_row (context, model, path,
8219 path_down_mode, tree_view->priv->empty_view_drop,
8220 drop_append_mode);
8221 }
8222
8223 if (path)
8224 ctk_tree_path_free (path);
8225
8226 /* Unset this thing */
8227 ctk_tree_view_set_drag_dest_row (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
,
8228 NULL((void*)0),
8229 CTK_TREE_VIEW_DROP_BEFORE);
8230
8231 if (target != CDK_NONE((CdkAtom)((gpointer) (gulong) (0))))
8232 {
8233 ctk_drag_get_data (widget, context, target, time);
8234 return TRUE(!(0));
8235 }
8236 else
8237 return FALSE(0);
8238}
8239
8240static void
8241ctk_tree_view_drag_data_received (CtkWidget *widget,
8242 CdkDragContext *context,
8243 /* coordinates relative to the widget */
8244 gint x G_GNUC_UNUSED__attribute__ ((__unused__)),
8245 gint y G_GNUC_UNUSED__attribute__ ((__unused__)),
8246 CtkSelectionData *selection_data,
8247 guint info G_GNUC_UNUSED__attribute__ ((__unused__)),
8248 guint time)
8249{
8250 CtkTreePath *path;
8251 TreeViewDragInfo *di;
8252 gboolean accepted = FALSE(0);
8253 CtkTreeModel *model;
8254 CtkTreeView *tree_view;
8255 CtkTreePath *dest_row;
8256 CdkDragAction suggested_action;
8257 gboolean path_down_mode;
8258 gboolean drop_append_mode;
8259
8260 tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8261
8262 model = ctk_tree_view_get_model (tree_view);
8263
8264 if (!check_model_dnd (model, CTK_TYPE_TREE_DRAG_DEST(ctk_tree_drag_dest_get_type ()), "drag_data_received"))
8265 return;
8266
8267 di = get_info (tree_view);
8268
8269 if (di == NULL((void*)0))
8270 return;
8271
8272 suggested_action = get_status_pending (context);
8273
8274 if (suggested_action)
8275 {
8276 /* We are getting this data due to a request in drag_motion,
8277 * rather than due to a request in drag_drop, so we are just
8278 * supposed to call drag_status, not actually paste in the
8279 * data.
8280 */
8281 path = get_logical_dest_row (tree_view, &path_down_mode,
8282 &drop_append_mode);
8283
8284 if (path == NULL((void*)0))
8285 suggested_action = 0;
8286 else if (path_down_mode)
8287 ctk_tree_path_down (path);
8288
8289 if (suggested_action)
8290 {
8291 if (!ctk_tree_drag_dest_row_drop_possible (CTK_TREE_DRAG_DEST (model)((((CtkTreeDragDest*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_drag_dest_get_type ()))))))
,
8292 path,
8293 selection_data))
8294 {
8295 if (path_down_mode)
8296 {
8297 path_down_mode = FALSE(0);
8298 ctk_tree_path_up (path);
8299
8300 if (!ctk_tree_drag_dest_row_drop_possible (CTK_TREE_DRAG_DEST (model)((((CtkTreeDragDest*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_drag_dest_get_type ()))))))
,
8301 path,
8302 selection_data))
8303 suggested_action = 0;
8304 }
8305 else
8306 suggested_action = 0;
8307 }
8308 }
8309
8310 cdk_drag_status (context, suggested_action, time);
8311
8312 if (path)
8313 ctk_tree_path_free (path);
8314
8315 /* If you can't drop, remove user drop indicator until the next motion */
8316 if (suggested_action == 0)
8317 ctk_tree_view_set_drag_dest_row (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
,
8318 NULL((void*)0),
8319 CTK_TREE_VIEW_DROP_BEFORE);
8320
8321 return;
8322 }
8323
8324 dest_row = get_dest_row (context, &path_down_mode);
8325
8326 if (dest_row == NULL((void*)0))
8327 return;
8328
8329 if (ctk_selection_data_get_length (selection_data) >= 0)
8330 {
8331 if (path_down_mode)
8332 {
8333 ctk_tree_path_down (dest_row);
8334 if (!ctk_tree_drag_dest_row_drop_possible (CTK_TREE_DRAG_DEST (model)((((CtkTreeDragDest*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_drag_dest_get_type ()))))))
,
8335 dest_row, selection_data))
8336 ctk_tree_path_up (dest_row);
8337 }
8338 }
8339
8340 if (ctk_selection_data_get_length (selection_data) >= 0)
8341 {
8342 if (ctk_tree_drag_dest_drag_data_received (CTK_TREE_DRAG_DEST (model)((((CtkTreeDragDest*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_drag_dest_get_type ()))))))
,
8343 dest_row,
8344 selection_data))
8345 accepted = TRUE(!(0));
8346 }
8347
8348 ctk_drag_finish (context,
8349 accepted,
8350 (cdk_drag_context_get_selected_action (context) == CDK_ACTION_MOVE),
8351 time);
8352
8353 if (ctk_tree_path_get_depth (dest_row) == 1 &&
8354 ctk_tree_path_get_indices (dest_row)[0] == 0 &&
8355 ctk_tree_model_iter_n_children (tree_view->priv->model, NULL((void*)0)) != 0)
8356 {
8357 /* special special case drag to "0", scroll to first item */
8358 if (!tree_view->priv->scroll_to_path)
8359 ctk_tree_view_scroll_to_cell (tree_view, dest_row, NULL((void*)0), FALSE(0), 0.0, 0.0);
8360 }
8361
8362 ctk_tree_path_free (dest_row);
8363
8364 /* drop dest_row */
8365 set_dest_row (context, NULL((void*)0), NULL((void*)0), FALSE(0), FALSE(0), FALSE(0));
8366}
8367
8368
8369
8370/* CtkContainer Methods
8371 */
8372
8373
8374static void
8375ctk_tree_view_remove (CtkContainer *container,
8376 CtkWidget *widget)
8377{
8378 CtkTreeView *tree_view = CTK_TREE_VIEW (container)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_tree_view_get_type ()))))))
;
8379 CtkTreeViewChild *child = NULL((void*)0);
8380 GList *tmp_list;
8381
8382 tmp_list = tree_view->priv->children;
8383 while (tmp_list)
8384 {
8385 child = tmp_list->data;
8386 if (child->widget == widget)
8387 {
8388 ctk_widget_unparent (widget);
8389
8390 tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
8391 g_list_free_1 (tmp_list);
8392 g_slice_free (CtkTreeViewChild, child)do { if (1) g_slice_free1 (sizeof (CtkTreeViewChild), (child)
); else (void) ((CtkTreeViewChild*) 0 == (child)); } while (0
)
;
8393 return;
8394 }
8395
8396 tmp_list = tmp_list->next;
8397 }
8398
8399 tmp_list = tree_view->priv->columns;
8400
8401 while (tmp_list)
8402 {
8403 CtkTreeViewColumn *column;
8404 CtkWidget *button;
8405
8406 column = tmp_list->data;
8407 button = ctk_tree_view_column_get_button (column);
8408
8409 if (button == widget)
8410 {
8411 ctk_widget_unparent (widget);
8412 return;
8413 }
8414 tmp_list = tmp_list->next;
8415 }
8416}
8417
8418static void
8419ctk_tree_view_forall (CtkContainer *container,
8420 gboolean include_internals,
8421 CtkCallback callback,
8422 gpointer callback_data)
8423{
8424 CtkTreeView *tree_view = CTK_TREE_VIEW (container)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_tree_view_get_type ()))))))
;
8425 CtkTreeViewChild *child = NULL((void*)0);
8426 CtkTreeViewColumn *column;
8427 CtkWidget *button;
8428 GList *tmp_list;
8429
8430 tmp_list = tree_view->priv->children;
8431 while (tmp_list)
8432 {
8433 child = tmp_list->data;
8434 tmp_list = tmp_list->next;
8435
8436 (* callback) (child->widget, callback_data);
8437 }
8438 if (include_internals == FALSE(0))
8439 return;
8440
8441 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
8442 {
8443 column = tmp_list->data;
8444 button = ctk_tree_view_column_get_button (column);
8445
8446 if (button)
8447 (* callback) (button, callback_data);
8448 }
8449}
8450
8451/* Returns TRUE is any of the columns contains a cell that can-focus.
8452 * If this is not the case, a column-spanning focus rectangle will be
8453 * drawn.
8454 */
8455static gboolean
8456ctk_tree_view_has_can_focus_cell (CtkTreeView *tree_view)
8457{
8458 GList *list;
8459
8460 for (list = tree_view->priv->columns; list; list = list->next)
8461 {
8462 CtkTreeViewColumn *column = list->data;
8463
8464 if (!ctk_tree_view_column_get_visible (column))
8465 continue;
8466 if (ctk_cell_area_is_activatable (ctk_cell_layout_get_area (CTK_CELL_LAYOUT (column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((column)), ((ctk_cell_layout_get_type ()))))))
)))
8467 return TRUE(!(0));
8468 }
8469
8470 return FALSE(0);
8471}
8472
8473static void
8474column_sizing_notify (GObject *object,
8475 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
8476 gpointer data)
8477{
8478 CtkTreeViewColumn *c = CTK_TREE_VIEW_COLUMN (object)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), ((ctk_tree_view_column_get_type (
)))))))
;
8479
8480 if (ctk_tree_view_column_get_sizing (c) != CTK_TREE_VIEW_COLUMN_FIXED)
8481 /* disable fixed height mode */
8482 g_object_set (data, "fixed-height-mode", FALSE(0), NULL((void*)0));
8483}
8484
8485/**
8486 * ctk_tree_view_set_fixed_height_mode:
8487 * @tree_view: a #CtkTreeView
8488 * @enable: %TRUE to enable fixed height mode
8489 *
8490 * Enables or disables the fixed height mode of @tree_view.
8491 * Fixed height mode speeds up #CtkTreeView by assuming that all
8492 * rows have the same height.
8493 * Only enable this option if all rows are the same height and all
8494 * columns are of type %CTK_TREE_VIEW_COLUMN_FIXED.
8495 *
8496 * Since: 2.6
8497 **/
8498void
8499ctk_tree_view_set_fixed_height_mode (CtkTreeView *tree_view,
8500 gboolean enable)
8501{
8502 GList *l;
8503
8504 enable = enable != FALSE(0);
8505
8506 if (enable == tree_view->priv->fixed_height_mode)
8507 return;
8508
8509 if (!enable)
8510 {
8511 tree_view->priv->fixed_height_mode = 0;
8512 tree_view->priv->fixed_height = -1;
8513 }
8514 else
8515 {
8516 /* make sure all columns are of type FIXED */
8517 for (l = tree_view->priv->columns; l; l = l->next)
8518 {
8519 CtkTreeViewColumn *c = l->data;
8520
8521 g_return_if_fail (ctk_tree_view_column_get_sizing (c) == CTK_TREE_VIEW_COLUMN_FIXED)do { if ((ctk_tree_view_column_get_sizing (c) == CTK_TREE_VIEW_COLUMN_FIXED
)) { } else { g_return_if_fail_warning ("Ctk", ((const char*)
(__func__)), "ctk_tree_view_column_get_sizing (c) == CTK_TREE_VIEW_COLUMN_FIXED"
); return; } } while (0)
;
8522 }
8523
8524 /* yes, we really have to do this is in a separate loop */
8525 for (l = tree_view->priv->columns; l; l = l->next)
8526 g_signal_connect (l->data, "notify::sizing",g_signal_connect_data ((l->data), ("notify::sizing"), (((GCallback
) (column_sizing_notify))), (tree_view), ((void*)0), (GConnectFlags
) 0)
8527 G_CALLBACK (column_sizing_notify), tree_view)g_signal_connect_data ((l->data), ("notify::sizing"), (((GCallback
) (column_sizing_notify))), (tree_view), ((void*)0), (GConnectFlags
) 0)
;
8528
8529 tree_view->priv->fixed_height_mode = 1;
8530 tree_view->priv->fixed_height = -1;
8531 }
8532
8533 /* force a revalidation */
8534 install_presize_handler (tree_view);
8535
8536 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_FIXED_HEIGHT_MODE]);
8537}
8538
8539/**
8540 * ctk_tree_view_get_fixed_height_mode:
8541 * @tree_view: a #CtkTreeView
8542 *
8543 * Returns whether fixed height mode is turned on for @tree_view.
8544 *
8545 * Returns: %TRUE if @tree_view is in fixed height mode
8546 *
8547 * Since: 2.6
8548 **/
8549gboolean
8550ctk_tree_view_get_fixed_height_mode (CtkTreeView *tree_view)
8551{
8552 return tree_view->priv->fixed_height_mode;
8553}
8554
8555/* Returns TRUE if the focus is within the headers, after the focus operation is
8556 * done
8557 */
8558static gboolean
8559ctk_tree_view_header_focus (CtkTreeView *tree_view,
8560 CtkDirectionType dir,
8561 gboolean clamp_column_visible)
8562{
8563 CtkTreeViewColumn *column;
8564 CtkWidget *button;
8565 CtkWidget *focus_child;
8566 GList *last_column, *first_column;
8567 GList *tmp_list;
8568 gboolean rtl;
8569
8570 if (! tree_view->priv->headers_visible)
8571 return FALSE(0);
8572
8573 focus_child = ctk_container_get_focus_child (CTK_CONTAINER (tree_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_container_get_type ()))))))
);
8574
8575 first_column = tree_view->priv->columns;
8576 while (first_column)
8577 {
8578 column = CTK_TREE_VIEW_COLUMN (first_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((first_column->data)), ((ctk_tree_view_column_get_type
()))))))
;
8579 button = ctk_tree_view_column_get_button (column);
8580
8581 if (ctk_widget_get_can_focus (button) &&
8582 ctk_tree_view_column_get_visible (column) &&
8583 (ctk_tree_view_column_get_clickable (column) ||
8584 ctk_tree_view_column_get_reorderable (column)))
8585 break;
8586 first_column = first_column->next;
8587 }
8588
8589 /* No headers are visible, or are focusable. We can't focus in or out.
8590 */
8591 if (first_column == NULL((void*)0))
8592 return FALSE(0);
8593
8594 last_column = g_list_last (tree_view->priv->columns);
8595 while (last_column)
8596 {
8597 column = CTK_TREE_VIEW_COLUMN (last_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((last_column->data)), ((ctk_tree_view_column_get_type
()))))))
;
8598 button = ctk_tree_view_column_get_button (column);
8599
8600 if (ctk_widget_get_can_focus (button) &&
8601 ctk_tree_view_column_get_visible (column) &&
8602 (ctk_tree_view_column_get_clickable (column) ||
8603 ctk_tree_view_column_get_reorderable (column)))
8604 break;
8605 last_column = last_column->prev;
8606 }
8607
8608
8609 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
8610
8611 switch (dir)
8612 {
8613 case CTK_DIR_TAB_BACKWARD:
8614 case CTK_DIR_TAB_FORWARD:
8615 case CTK_DIR_UP:
8616 case CTK_DIR_DOWN:
8617 if (focus_child == NULL((void*)0))
8618 {
8619 if (tree_view->priv->focus_column != NULL((void*)0))
8620 button = ctk_tree_view_column_get_button (tree_view->priv->focus_column);
8621 else
8622 button = NULL((void*)0);
8623
8624 if (button && ctk_widget_get_can_focus (button))
8625 focus_child = button;
8626 else
8627 focus_child = ctk_tree_view_column_get_button (CTK_TREE_VIEW_COLUMN (first_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((first_column->data)), ((ctk_tree_view_column_get_type
()))))))
);
8628
8629 ctk_widget_grab_focus (focus_child);
8630 break;
8631 }
8632 return FALSE(0);
8633
8634 case CTK_DIR_LEFT:
8635 case CTK_DIR_RIGHT:
8636 if (focus_child == NULL((void*)0))
8637 {
8638 if (tree_view->priv->focus_column != NULL((void*)0))
8639 focus_child = ctk_tree_view_column_get_button (tree_view->priv->focus_column);
8640 else if (dir == CTK_DIR_LEFT)
8641 focus_child = ctk_tree_view_column_get_button (CTK_TREE_VIEW_COLUMN (last_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((last_column->data)), ((ctk_tree_view_column_get_type
()))))))
);
8642 else
8643 focus_child = ctk_tree_view_column_get_button (CTK_TREE_VIEW_COLUMN (first_column->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((first_column->data)), ((ctk_tree_view_column_get_type
()))))))
);
8644
8645 ctk_widget_grab_focus (focus_child);
8646 break;
8647 }
8648
8649 if (ctk_widget_child_focus (focus_child, dir))
8650 {
8651 /* The focus moves inside the button. */
8652 /* This is probably a great example of bad UI */
8653 break;
8654 }
8655
8656 /* We need to move the focus among the row of buttons. */
8657 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
8658 if (ctk_tree_view_column_get_button (CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
) == focus_child)
8659 break;
8660
8661 if ((tmp_list == first_column && dir == (rtl ? CTK_DIR_RIGHT : CTK_DIR_LEFT))
8662 || (tmp_list == last_column && dir == (rtl ? CTK_DIR_LEFT : CTK_DIR_RIGHT)))
8663 {
8664 ctk_widget_error_bell (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
8665 break;
8666 }
8667
8668 while (tmp_list)
8669 {
8670 if (dir == (rtl ? CTK_DIR_LEFT : CTK_DIR_RIGHT))
8671 tmp_list = tmp_list->next;
8672 else
8673 tmp_list = tmp_list->prev;
8674
8675 if (tmp_list == NULL((void*)0))
8676 {
8677 g_warning ("Internal button not found");
8678 break;
8679 }
8680 column = tmp_list->data;
8681 button = ctk_tree_view_column_get_button (column);
8682 if (button &&
8683 ctk_tree_view_column_get_visible (column) &&
8684 ctk_widget_get_can_focus (button))
8685 {
8686 focus_child = button;
8687 ctk_widget_grab_focus (button);
8688 break;
8689 }
8690 }
8691 break;
8692 default:
8693 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktreeview.c", 8693, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
8694 break;
8695 }
8696
8697 /* if focus child is non-null, we assume it's been set to the current focus child
8698 */
8699 if (focus_child)
8700 {
8701 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
8702 if (ctk_tree_view_column_get_button (CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
) == focus_child)
8703 {
8704 _ctk_tree_view_set_focus_column (tree_view, CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
);
8705 break;
8706 }
8707
8708 if (clamp_column_visible)
8709 {
8710 ctk_tree_view_clamp_column_visible (tree_view,
8711 tree_view->priv->focus_column,
8712 FALSE(0));
8713 }
8714 }
8715
8716 return (focus_child != NULL((void*)0));
8717}
8718
8719/* This function returns in 'path' the first focusable path, if the given path
8720 * is already focusable, it’s the returned one.
8721 */
8722static gboolean
8723search_first_focusable_path (CtkTreeView *tree_view,
8724 CtkTreePath **path,
8725 gboolean search_forward,
8726 CtkRBTree **new_tree,
8727 CtkRBNode **new_node)
8728{
8729 CtkRBTree *tree = NULL((void*)0);
8730 CtkRBNode *node = NULL((void*)0);
8731
8732 if (!path || !*path)
8733 return FALSE(0);
8734
8735 _ctk_tree_view_find_node (tree_view, *path, &tree, &node);
8736
8737 if (!tree || !node)
8738 return FALSE(0);
8739
8740 while (node && row_is_separator (tree_view, NULL((void*)0), *path))
8741 {
8742 if (search_forward)
8743 _ctk_rbtree_next_full (tree, node, &tree, &node);
8744 else
8745 _ctk_rbtree_prev_full (tree, node, &tree, &node);
8746
8747 if (*path)
8748 ctk_tree_path_free (*path);
8749
8750 if (node)
8751 *path = _ctk_tree_path_new_from_rbtree (tree, node);
8752 else
8753 *path = NULL((void*)0);
8754 }
8755
8756 if (new_tree)
8757 *new_tree = tree;
8758
8759 if (new_node)
8760 *new_node = node;
8761
8762 return (*path != NULL((void*)0));
8763}
8764
8765static gint
8766ctk_tree_view_focus (CtkWidget *widget,
8767 CtkDirectionType direction)
8768{
8769 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8770 CtkContainer *container = CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
;
8771 CtkWidget *focus_child;
8772
8773 if (!ctk_widget_is_sensitive (widget) || !ctk_widget_get_can_focus (widget))
8774 return FALSE(0);
8775
8776 focus_child = ctk_container_get_focus_child (container);
8777
8778 ctk_tree_view_stop_editing (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
, FALSE(0));
8779 /* Case 1. Headers currently have focus. */
8780 if (focus_child)
8781 {
8782 switch (direction)
8783 {
8784 case CTK_DIR_LEFT:
8785 case CTK_DIR_RIGHT:
8786 ctk_tree_view_header_focus (tree_view, direction, TRUE(!(0)));
8787 return TRUE(!(0));
8788 case CTK_DIR_TAB_BACKWARD:
8789 case CTK_DIR_UP:
8790 return FALSE(0);
8791 case CTK_DIR_TAB_FORWARD:
8792 case CTK_DIR_DOWN:
8793 ctk_widget_grab_focus (widget);
8794 return TRUE(!(0));
8795 default:
8796 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktreeview.c", 8796, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
8797 return FALSE(0);
8798 }
8799 }
8800
8801 /* Case 2. We don't have focus at all. */
8802 if (!ctk_widget_has_focus (widget))
8803 {
8804 ctk_widget_grab_focus (widget);
8805 return TRUE(!(0));
8806 }
8807
8808 /* Case 3. We have focus already. */
8809 if (direction == CTK_DIR_TAB_BACKWARD)
8810 return (ctk_tree_view_header_focus (tree_view, direction, FALSE(0)));
8811 else if (direction == CTK_DIR_TAB_FORWARD)
8812 return FALSE(0);
8813
8814 /* Other directions caught by the keybindings */
8815 ctk_widget_grab_focus (widget);
8816 return TRUE(!(0));
8817}
8818
8819static void
8820ctk_tree_view_grab_focus (CtkWidget *widget)
8821{
8822 CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->grab_focus (widget);
8823
8824 ctk_tree_view_focus_to_cursor (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
);
8825}
8826
8827static void
8828ctk_tree_view_style_updated (CtkWidget *widget)
8829{
8830 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
8831 GList *list;
8832 CtkTreeViewColumn *column;
8833 CtkStyleContext *style_context;
8834 CtkCssStyleChange *change;
8835
8836 CTK_WIDGET_CLASS (ctk_tree_view_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_widget_get_type ()))
))))
->style_updated (widget);
8837
8838 if (ctk_widget_get_realized (widget))
8839 {
8840 ctk_tree_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
8841 ctk_tree_view_set_enable_tree_lines (tree_view, tree_view->priv->tree_lines_enabled);
8842 }
8843
8844 style_context = ctk_widget_get_style_context (widget);
8845 change = ctk_style_context_get_change (style_context);
8846
8847 if (change == NULL((void*)0) || ctk_css_style_change_affects (change, CTK_CSS_AFFECTS_SIZE | CTK_CSS_AFFECTS_CLIP))
8848 {
8849 for (list = tree_view->priv->columns; list; list = list->next)
8850 {
8851 column = list->data;
8852 _ctk_tree_view_column_cell_set_dirty (column, TRUE(!(0)));
8853 }
8854
8855 tree_view->priv->fixed_height = -1;
8856 _ctk_rbtree_mark_invalid (tree_view->priv->tree);
8857 }
8858}
8859
8860
8861static void
8862ctk_tree_view_set_focus_child (CtkContainer *container,
8863 CtkWidget *child)
8864{
8865 CtkTreeView *tree_view = CTK_TREE_VIEW (container)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_tree_view_get_type ()))))))
;
8866 GList *list;
8867
8868 for (list = tree_view->priv->columns; list; list = list->next)
8869 {
8870 if (ctk_tree_view_column_get_button (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
) == child)
8871 {
8872 _ctk_tree_view_set_focus_column (tree_view, CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
);
8873 break;
8874 }
8875 }
8876
8877 CTK_CONTAINER_CLASS (ctk_tree_view_parent_class)((((CtkContainerClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_view_parent_class)), ((ctk_container_get_type (
)))))))
->set_focus_child (container, child);
8878}
8879
8880static gboolean
8881ctk_tree_view_real_move_cursor (CtkTreeView *tree_view,
8882 CtkMovementStep step,
8883 gint count)
8884{
8885 CdkModifierType state;
8886
8887 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
8888 g_return_val_if_fail (step == CTK_MOVEMENT_LOGICAL_POSITIONS ||do { if ((step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS
|| step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES
|| step == CTK_MOVEMENT_BUFFER_ENDS)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS || step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES || step == CTK_MOVEMENT_BUFFER_ENDS"
); return ((0)); } } while (0)
8889 step == CTK_MOVEMENT_VISUAL_POSITIONS ||do { if ((step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS
|| step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES
|| step == CTK_MOVEMENT_BUFFER_ENDS)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS || step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES || step == CTK_MOVEMENT_BUFFER_ENDS"
); return ((0)); } } while (0)
8890 step == CTK_MOVEMENT_DISPLAY_LINES ||do { if ((step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS
|| step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES
|| step == CTK_MOVEMENT_BUFFER_ENDS)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS || step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES || step == CTK_MOVEMENT_BUFFER_ENDS"
); return ((0)); } } while (0)
8891 step == CTK_MOVEMENT_PAGES ||do { if ((step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS
|| step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES
|| step == CTK_MOVEMENT_BUFFER_ENDS)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS || step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES || step == CTK_MOVEMENT_BUFFER_ENDS"
); return ((0)); } } while (0)
8892 step == CTK_MOVEMENT_BUFFER_ENDS, FALSE)do { if ((step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS
|| step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES
|| step == CTK_MOVEMENT_BUFFER_ENDS)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "step == CTK_MOVEMENT_LOGICAL_POSITIONS || step == CTK_MOVEMENT_VISUAL_POSITIONS || step == CTK_MOVEMENT_DISPLAY_LINES || step == CTK_MOVEMENT_PAGES || step == CTK_MOVEMENT_BUFFER_ENDS"
); return ((0)); } } while (0)
;
8893
8894 if (tree_view->priv->tree == NULL((void*)0))
8895 return FALSE(0);
8896 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
8897 return FALSE(0);
8898
8899 ctk_tree_view_stop_editing (tree_view, FALSE(0));
8900 tree_view->priv->draw_keyfocus = TRUE(!(0));
8901 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
8902
8903 if (ctk_get_current_event_state (&state))
8904 {
8905 CdkModifierType extend_mod_mask;
8906 CdkModifierType modify_mod_mask;
8907
8908 extend_mod_mask =
8909 ctk_widget_get_modifier_mask (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
8910 CDK_MODIFIER_INTENT_EXTEND_SELECTION);
8911
8912 modify_mod_mask =
8913 ctk_widget_get_modifier_mask (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
8914 CDK_MODIFIER_INTENT_MODIFY_SELECTION);
8915
8916 if ((state & modify_mod_mask) == modify_mod_mask)
8917 tree_view->priv->modify_selection_pressed = TRUE(!(0));
8918 if ((state & extend_mod_mask) == extend_mod_mask)
8919 tree_view->priv->extend_selection_pressed = TRUE(!(0));
8920 }
8921 /* else we assume not pressed */
8922
8923 switch (step)
8924 {
8925 /* currently we make no distinction. When we go bi-di, we need to */
8926 case CTK_MOVEMENT_LOGICAL_POSITIONS:
8927 case CTK_MOVEMENT_VISUAL_POSITIONS:
8928 ctk_tree_view_move_cursor_left_right (tree_view, count);
8929 break;
8930 case CTK_MOVEMENT_DISPLAY_LINES:
8931 ctk_tree_view_move_cursor_up_down (tree_view, count);
8932 break;
8933 case CTK_MOVEMENT_PAGES:
8934 ctk_tree_view_move_cursor_page_up_down (tree_view, count);
8935 break;
8936 case CTK_MOVEMENT_BUFFER_ENDS:
8937 ctk_tree_view_move_cursor_start_end (tree_view, count);
8938 break;
8939 default:
8940 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktreeview.c", 8940, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
8941 }
8942
8943 tree_view->priv->modify_selection_pressed = FALSE(0);
8944 tree_view->priv->extend_selection_pressed = FALSE(0);
8945
8946 return TRUE(!(0));
8947}
8948
8949static void
8950ctk_tree_view_put (CtkTreeView *tree_view,
8951 CtkWidget *child_widget,
8952 CtkTreePath *path,
8953 CtkTreeViewColumn *column,
8954 const CtkBorder *border)
8955{
8956 CtkTreeViewChild *child;
8957
8958 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
8959 g_return_if_fail (CTK_IS_WIDGET (child_widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child_widget)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (child_widget)"); return; } } while (0)
;
8960
8961 child = g_slice_new (CtkTreeViewChild)((CtkTreeViewChild*) g_slice_alloc (sizeof (CtkTreeViewChild)
))
;
8962
8963 child->widget = child_widget;
8964 if (_ctk_tree_view_find_node (tree_view,
8965 path,
8966 &child->tree,
8967 &child->node))
8968 {
8969 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctktreeview.c", 8969, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
8970 }
8971 child->column = column;
8972 child->border = *border;
8973
8974 tree_view->priv->children = g_list_append (tree_view->priv->children, child);
8975
8976 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
8977 ctk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
8978
8979 ctk_widget_set_parent (child_widget, CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
8980}
8981
8982/* TreeModel Callbacks
8983 */
8984
8985static void
8986ctk_tree_view_row_changed (CtkTreeModel *model,
8987 CtkTreePath *path,
8988 CtkTreeIter *iter,
8989 gpointer data)
8990{
8991 CtkTreeView *tree_view = (CtkTreeView *)data;
8992 CtkRBTree *tree;
8993 CtkRBNode *node;
8994 gboolean free_path = FALSE(0);
8995 GList *list;
8996 CtkTreePath *cursor_path;
8997
8998 g_return_if_fail (path != NULL || iter != NULL)do { if ((path != ((void*)0) || iter != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "path != NULL || iter != NULL"); return; } } while (0)
;
8999
9000 if (tree_view->priv->cursor_node != NULL((void*)0))
9001 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
9002 tree_view->priv->cursor_node);
9003 else
9004 cursor_path = NULL((void*)0);
9005
9006 if (tree_view->priv->edited_column &&
9007 (cursor_path == NULL((void*)0) || ctk_tree_path_compare (cursor_path, path) == 0))
9008 ctk_tree_view_stop_editing (tree_view, TRUE(!(0)));
9009
9010 if (cursor_path != NULL((void*)0))
9011 ctk_tree_path_free (cursor_path);
9012
9013 if (path == NULL((void*)0))
9014 {
9015 path = ctk_tree_model_get_path (model, iter);
9016 free_path = TRUE(!(0));
9017 }
9018 else if (iter == NULL((void*)0))
9019 ctk_tree_model_get_iter (model, iter, path);
9020
9021 if (_ctk_tree_view_find_node (tree_view,
9022 path,
9023 &tree,
9024 &node))
9025 /* We aren't actually showing the node */
9026 goto done;
9027
9028 if (tree == NULL((void*)0))
9029 goto done;
9030
9031 _ctk_tree_view_accessible_changed (tree_view, tree, node);
9032
9033 if (tree_view->priv->fixed_height_mode
9034 && tree_view->priv->fixed_height >= 0)
9035 {
9036 _ctk_rbtree_node_set_height (tree, node, tree_view->priv->fixed_height);
9037 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
9038 ctk_tree_view_node_queue_redraw (tree_view, tree, node);
9039 }
9040 else
9041 {
9042 _ctk_rbtree_node_mark_invalid (tree, node);
9043 for (list = tree_view->priv->columns; list; list = list->next)
9044 {
9045 CtkTreeViewColumn *column;
9046
9047 column = list->data;
9048 if (!ctk_tree_view_column_get_visible (column))
9049 continue;
9050
9051 if (ctk_tree_view_column_get_sizing (column) == CTK_TREE_VIEW_COLUMN_AUTOSIZE)
9052 {
9053 _ctk_tree_view_column_cell_set_dirty (column, TRUE(!(0)));
9054 }
9055 }
9056 }
9057
9058 done:
9059 if (!tree_view->priv->fixed_height_mode &&
9060 ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
9061 install_presize_handler (tree_view);
9062 if (free_path)
9063 ctk_tree_path_free (path);
9064}
9065
9066static void
9067ctk_tree_view_row_inserted (CtkTreeModel *model,
9068 CtkTreePath *path,
9069 CtkTreeIter *iter,
9070 gpointer data)
9071{
9072 CtkTreeView *tree_view = (CtkTreeView *) data;
9073 gint *indices;
9074 CtkRBTree *tree;
9075 CtkRBNode *tmpnode = NULL((void*)0);
9076 gint depth;
9077 gint i = 0;
9078 gint height;
9079 gboolean free_path = FALSE(0);
9080 gboolean node_visible = TRUE(!(0));
9081
9082 g_return_if_fail (path != NULL || iter != NULL)do { if ((path != ((void*)0) || iter != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "path != NULL || iter != NULL"); return; } } while (0)
;
9083
9084 if (tree_view->priv->fixed_height_mode
9085 && tree_view->priv->fixed_height >= 0)
9086 height = tree_view->priv->fixed_height;
9087 else
9088 height = 0;
9089
9090 if (path == NULL((void*)0))
9091 {
9092 path = ctk_tree_model_get_path (model, iter);
9093 free_path = TRUE(!(0));
9094 }
9095 else if (iter == NULL((void*)0))
9096 ctk_tree_model_get_iter (model, iter, path);
9097
9098 if (tree_view->priv->tree == NULL((void*)0))
9099 tree_view->priv->tree = _ctk_rbtree_new ();
9100
9101 tree = tree_view->priv->tree;
9102
9103 /* Update all row-references */
9104 ctk_tree_row_reference_inserted (G_OBJECT (data)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (((GType) ((20) << (2))))))))
, path);
9105 depth = ctk_tree_path_get_depth (path);
9106 indices = ctk_tree_path_get_indices (path);
9107
9108 /* First, find the parent tree */
9109 while (i < depth - 1)
9110 {
9111 if (tree == NULL((void*)0))
9112 {
9113 /* We aren't showing the node */
9114 node_visible = FALSE(0);
9115 goto done;
9116 }
9117
9118 tmpnode = _ctk_rbtree_find_count (tree, indices[i] + 1);
9119 if (tmpnode == NULL((void*)0))
9120 {
9121 g_warning ("A node was inserted with a parent that's not in the tree.\n" \
9122 "This possibly means that a CtkTreeModel inserted a child node\n" \
9123 "before the parent was inserted.");
9124 goto done;
9125 }
9126 else if (!CTK_RBNODE_FLAG_SET (tmpnode, CTK_RBNODE_IS_PARENT)(tmpnode?(((tmpnode->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
)
9127 {
9128 /* FIXME enforce correct behavior on model, probably */
9129 /* In theory, the model should have emitted has_child_toggled here. We
9130 * try to catch it anyway, just to be safe, in case the model hasn't.
9131 */
9132 CtkTreePath *tmppath = _ctk_tree_path_new_from_rbtree (tree, tmpnode);
9133 ctk_tree_view_row_has_child_toggled (model, tmppath, NULL((void*)0), data);
9134 ctk_tree_path_free (tmppath);
9135 goto done;
9136 }
9137
9138 tree = tmpnode->children;
9139 i++;
9140 }
9141
9142 if (tree == NULL((void*)0))
9143 {
9144 node_visible = FALSE(0);
9145 goto done;
9146 }
9147
9148 /* ref the node */
9149 ctk_tree_model_ref_node (tree_view->priv->model, iter);
9150 if (indices[depth - 1] == 0)
9151 {
9152 tmpnode = _ctk_rbtree_find_count (tree, 1);
9153 tmpnode = _ctk_rbtree_insert_before (tree, tmpnode, height, FALSE(0));
9154 }
9155 else
9156 {
9157 tmpnode = _ctk_rbtree_find_count (tree, indices[depth - 1]);
9158 tmpnode = _ctk_rbtree_insert_after (tree, tmpnode, height, FALSE(0));
9159 }
9160
9161 _ctk_tree_view_accessible_add (tree_view, tree, tmpnode);
9162
9163 done:
9164 if (height > 0)
9165 {
9166 if (tree)
9167 _ctk_rbtree_node_mark_valid (tree, tmpnode);
9168
9169 if (node_visible && node_is_visible (tree_view, tree, tmpnode))
9170 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
9171 else
9172 ctk_widget_queue_resize_no_redraw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
9173 }
9174 else
9175 install_presize_handler (tree_view);
9176 if (free_path)
9177 ctk_tree_path_free (path);
9178}
9179
9180static void
9181ctk_tree_view_row_has_child_toggled (CtkTreeModel *model,
9182 CtkTreePath *path,
9183 CtkTreeIter *iter,
9184 gpointer data)
9185{
9186 CtkTreeView *tree_view = (CtkTreeView *)data;
9187 CtkTreeIter real_iter;
9188 gboolean has_child;
9189 CtkRBTree *tree;
9190 CtkRBNode *node;
9191 gboolean free_path = FALSE(0);
9192
9193 g_return_if_fail (path != NULL || iter != NULL)do { if ((path != ((void*)0) || iter != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "path != NULL || iter != NULL"); return; } } while (0)
;
9194
9195 if (iter)
9196 real_iter = *iter;
9197
9198 if (path == NULL((void*)0))
9199 {
9200 path = ctk_tree_model_get_path (model, iter);
9201 free_path = TRUE(!(0));
9202 }
9203 else if (iter == NULL((void*)0))
9204 ctk_tree_model_get_iter (model, &real_iter, path);
9205
9206 if (_ctk_tree_view_find_node (tree_view,
9207 path,
9208 &tree,
9209 &node))
9210 /* We aren't actually showing the node */
9211 goto done;
9212
9213 if (tree == NULL((void*)0))
9214 goto done;
9215
9216 has_child = ctk_tree_model_iter_has_child (model, &real_iter);
9217 /* Sanity check.
9218 */
9219 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
== has_child)
9220 goto done;
9221
9222 if (has_child)
9223 {
9224 CTK_RBNODE_SET_FLAG (node, CTK_RBNODE_IS_PARENT)do{ (node->flags|=CTK_RBNODE_IS_PARENT); }while (0);
9225 _ctk_tree_view_accessible_add_state (tree_view, tree, node, CTK_CELL_RENDERER_EXPANDABLE);
9226 }
9227 else
9228 {
9229 CTK_RBNODE_UNSET_FLAG (node, CTK_RBNODE_IS_PARENT)do{ (node->flags&=~(CTK_RBNODE_IS_PARENT)); }while (0);
9230 _ctk_tree_view_accessible_remove_state (tree_view, tree, node, CTK_CELL_RENDERER_EXPANDABLE);
9231 }
9232
9233 if (has_child && tree_view->priv->is_list)
9234 {
9235 tree_view->priv->is_list = FALSE(0);
9236 if (tree_view->priv->show_expanders)
9237 {
9238 GList *list;
9239
9240 for (list = tree_view->priv->columns; list; list = list->next)
9241 if (ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
))
9242 {
9243 _ctk_tree_view_column_cell_set_dirty (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
, TRUE(!(0)));
9244 break;
9245 }
9246 }
9247 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
9248 }
9249 else
9250 {
9251 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
9252 }
9253
9254 done:
9255 if (free_path)
9256 ctk_tree_path_free (path);
9257}
9258
9259static void
9260count_children_helper (CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)),
9261 CtkRBNode *node,
9262 gpointer data)
9263{
9264 if (node->children)
9265 _ctk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, data);
9266 (*((gint *)data))++;
9267}
9268
9269static void
9270check_selection_helper (CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)),
9271 CtkRBNode *node,
9272 gpointer data)
9273{
9274 gint *value = (gint *)data;
9275
9276 *value |= CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
;
9277
9278 if (node->children && !*value)
9279 _ctk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, check_selection_helper, data);
9280}
9281
9282static void
9283ctk_tree_view_row_deleted (CtkTreeModel *model G_GNUC_UNUSED__attribute__ ((__unused__)),
9284 CtkTreePath *path,
9285 gpointer data)
9286{
9287 CtkTreeView *tree_view = (CtkTreeView *)data;
9288 CtkRBTree *tree;
9289 CtkRBNode *node;
9290 GList *list;
9291 gboolean selection_changed = FALSE(0), cursor_changed = FALSE(0);
9292 CtkRBTree *cursor_tree = NULL((void*)0);
9293 CtkRBNode *cursor_node = NULL((void*)0);
9294
9295 g_return_if_fail (path != NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return;
} } while (0)
;
9296
9297 ctk_tree_row_reference_deleted (G_OBJECT (data)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (((GType) ((20) << (2))))))))
, path);
9298
9299 if (_ctk_tree_view_find_node (tree_view, path, &tree, &node))
9300 return;
9301
9302 if (tree == NULL((void*)0))
9303 return;
9304
9305 /* check if the selection has been changed */
9306 _ctk_rbtree_traverse (tree, node, G_POST_ORDER,
9307 check_selection_helper, &selection_changed);
9308
9309 for (list = tree_view->priv->columns; list; list = list->next)
9310 if (ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
) &&
9311 ctk_tree_view_column_get_sizing (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
) == CTK_TREE_VIEW_COLUMN_AUTOSIZE)
9312 _ctk_tree_view_column_cell_set_dirty ((CtkTreeViewColumn *)list->data, TRUE(!(0)));
9313
9314 /* Ensure we don't have a dangling pointer to a dead node */
9315 ensure_unprelighted (tree_view);
9316
9317 /* Cancel editting if we've started */
9318 ctk_tree_view_stop_editing (tree_view, TRUE(!(0)));
9319
9320 /* If the cursor row got deleted, move the cursor to the next row */
9321 if (tree_view->priv->cursor_node &&
9322 (tree_view->priv->cursor_node == node ||
9323 (node->children && (tree_view->priv->cursor_tree == node->children ||
9324 _ctk_rbtree_contains (node->children, tree_view->priv->cursor_tree)))))
9325 {
9326 CtkTreePath *cursor_path;
9327
9328 cursor_tree = tree;
9329 cursor_node = _ctk_rbtree_next (tree, node);
9330 /* find the first node that is not going to be deleted */
9331 while (cursor_node == NULL((void*)0) && cursor_tree->parent_tree)
9332 {
9333 cursor_node = _ctk_rbtree_next (cursor_tree->parent_tree,
9334 cursor_tree->parent_node);
9335 cursor_tree = cursor_tree->parent_tree;
9336 }
9337
9338 if (cursor_node != NULL((void*)0))
9339 cursor_path = _ctk_tree_path_new_from_rbtree (cursor_tree, cursor_node);
9340 else
9341 cursor_path = NULL((void*)0);
9342
9343 if (cursor_path == NULL((void*)0) ||
9344 ! search_first_focusable_path (tree_view, &cursor_path, TRUE(!(0)),
9345 &cursor_tree, &cursor_node))
9346 {
9347 /* It looks like we reached the end of the view without finding
9348 * a focusable row. We will step backwards to find the last
9349 * focusable row.
9350 */
9351 _ctk_rbtree_prev_full (tree, node, &cursor_tree, &cursor_node);
9352 if (cursor_node)
9353 {
9354 cursor_path = _ctk_tree_path_new_from_rbtree (cursor_tree, cursor_node);
9355 if (! search_first_focusable_path (tree_view, &cursor_path, FALSE(0),
9356 &cursor_tree, &cursor_node))
9357 cursor_node = NULL((void*)0);
9358 ctk_tree_path_free (cursor_path);
9359 }
9360 }
9361 else if (cursor_path)
9362 ctk_tree_path_free (cursor_path);
9363
9364 cursor_changed = TRUE(!(0));
9365 }
9366
9367 if (tree_view->priv->destroy_count_func)
9368 {
9369 gint child_count = 0;
9370 if (node->children)
9371 _ctk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
9372 tree_view->priv->destroy_count_func (tree_view, path, child_count, tree_view->priv->destroy_count_data);
9373 }
9374
9375 if (tree->root->count == 1)
9376 {
9377 if (tree_view->priv->tree == tree)
9378 tree_view->priv->tree = NULL((void*)0);
9379
9380 _ctk_tree_view_accessible_remove_state (tree_view,
9381 tree->parent_tree, tree->parent_node,
9382 CTK_CELL_RENDERER_EXPANDED);
9383 _ctk_tree_view_accessible_remove (tree_view, tree, NULL((void*)0));
9384 _ctk_rbtree_remove (tree);
9385 }
9386 else
9387 {
9388 _ctk_tree_view_accessible_remove (tree_view, tree, node);
9389 _ctk_rbtree_remove_node (tree, node);
9390 }
9391
9392 if (! ctk_tree_row_reference_valid (tree_view->priv->top_row))
9393 {
9394 ctk_tree_row_reference_free (tree_view->priv->top_row);
9395 tree_view->priv->top_row = NULL((void*)0);
9396 }
9397
9398 install_scroll_sync_handler (tree_view);
9399
9400 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
9401
9402 if (cursor_changed)
9403 {
9404 if (cursor_node)
9405 {
9406 CtkTreePath *cursor_path = _ctk_tree_path_new_from_rbtree (cursor_tree, cursor_node);
9407 ctk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT | CURSOR_INVALID);
9408 ctk_tree_path_free (cursor_path);
9409 }
9410 else
9411 ctk_tree_view_real_set_cursor (tree_view, NULL((void*)0), CLEAR_AND_SELECT | CURSOR_INVALID);
9412 }
9413 if (selection_changed)
9414 g_signal_emit_by_name (tree_view->priv->selection, "changed");
9415}
9416
9417static void
9418ctk_tree_view_rows_reordered (CtkTreeModel *model,
9419 CtkTreePath *parent,
9420 CtkTreeIter *iter,
9421 gint *new_order,
9422 gpointer data)
9423{
9424 CtkTreeView *tree_view = CTK_TREE_VIEW (data)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_view_get_type ()))))))
;
9425 CtkRBTree *tree;
9426 CtkRBNode *node;
9427 gint len;
9428
9429 len = ctk_tree_model_iter_n_children (model, iter);
9430
9431 if (len < 2)
9432 return;
9433
9434 ctk_tree_row_reference_reordered (G_OBJECT (data)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (((GType) ((20) << (2))))))))
,
9435 parent,
9436 iter,
9437 new_order);
9438
9439 if (_ctk_tree_view_find_node (tree_view,
9440 parent,
9441 &tree,
9442 &node))
9443 return;
9444
9445 /* We need to special case the parent path */
9446 if (tree == NULL((void*)0))
9447 tree = tree_view->priv->tree;
9448 else
9449 tree = node->children;
9450
9451 if (tree == NULL((void*)0))
9452 return;
9453
9454 if (tree_view->priv->edited_column)
9455 ctk_tree_view_stop_editing (tree_view, TRUE(!(0)));
9456
9457 /* we need to be unprelighted */
9458 ensure_unprelighted (tree_view);
9459
9460 _ctk_rbtree_reorder (tree, new_order, len);
9461
9462 _ctk_tree_view_accessible_reorder (tree_view);
9463
9464 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
9465
9466 ctk_tree_view_dy_to_top_row (tree_view);
9467}
9468
9469
9470/* Internal tree functions
9471 */
9472
9473
9474static void
9475ctk_tree_view_get_background_xrange (CtkTreeView *tree_view,
9476 CtkRBTree *tree G_GNUC_UNUSED__attribute__ ((__unused__)),
9477 CtkTreeViewColumn *column,
9478 gint *x1,
9479 gint *x2)
9480{
9481 CtkTreeViewColumn *tmp_column = NULL((void*)0);
9482 gint total_width;
9483 GList *list;
9484 gboolean rtl;
9485
9486 if (x1)
9487 *x1 = 0;
9488
9489 if (x2)
9490 *x2 = 0;
9491
9492 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
9493
9494 total_width = 0;
9495 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
9496 list;
9497 list = (rtl ? list->prev : list->next))
9498 {
9499 tmp_column = list->data;
9500
9501 if (tmp_column == column)
9502 break;
9503
9504 if (ctk_tree_view_column_get_visible (tmp_column))
9505 total_width += ctk_tree_view_column_get_width (tmp_column);
9506 }
9507
9508 if (tmp_column != column)
9509 {
9510 g_warning (G_STRLOC"ctktreeview.c" ":" "9510"": passed-in column isn't in the tree");
9511 return;
9512 }
9513
9514 if (x1)
9515 *x1 = total_width;
9516
9517 if (x2)
9518 {
9519 if (ctk_tree_view_column_get_visible (column))
9520 *x2 = total_width + ctk_tree_view_column_get_width (column);
9521 else
9522 *x2 = total_width; /* width of 0 */
9523 }
9524}
9525
9526static void
9527ctk_tree_view_get_arrow_xrange (CtkTreeView *tree_view,
9528 CtkRBTree *tree,
9529 gint *x1,
9530 gint *x2)
9531{
9532 gint x_offset = 0;
9533 GList *list;
9534 CtkTreeViewColumn *tmp_column = NULL((void*)0);
9535 gint total_width;
9536 gint expander_size, expander_render_size;
9537 gint horizontal_separator;
9538 gboolean indent_expanders;
9539 gboolean rtl;
9540
9541 ctk_widget_style_get (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
9542 "indent-expanders", &indent_expanders,
9543 "horizontal-separator", &horizontal_separator,
9544 NULL((void*)0));
9545
9546 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
9547 expander_size = ctk_tree_view_get_expander_size (tree_view);
9548 expander_render_size = expander_size - (horizontal_separator / 2);
9549
9550 total_width = 0;
9551 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
9552 list;
9553 list = (rtl ? list->prev : list->next))
9554 {
9555 tmp_column = list->data;
9556
9557 if (ctk_tree_view_is_expander_column (tree_view, tmp_column))
9558 {
9559 if (rtl)
9560 x_offset = total_width + ctk_tree_view_column_get_width (tmp_column) - expander_size;
9561 else
9562 x_offset = total_width;
9563 break;
9564 }
9565
9566 if (ctk_tree_view_column_get_visible (tmp_column))
9567 total_width += ctk_tree_view_column_get_width (tmp_column);
9568 }
9569
9570 x_offset += (expander_size - expander_render_size);
9571
9572 if (indent_expanders)
9573 {
9574 if (rtl)
9575 x_offset -= expander_size * _ctk_rbtree_get_depth (tree);
9576 else
9577 x_offset += expander_size * _ctk_rbtree_get_depth (tree);
9578 }
9579
9580 *x1 = x_offset;
9581
9582 if (tmp_column &&
9583 ctk_tree_view_column_get_visible (tmp_column))
9584 *x2 = *x1 + expander_render_size;
9585 else
9586 *x2 = *x1;
9587}
9588
9589static void
9590ctk_tree_view_build_tree (CtkTreeView *tree_view,
9591 CtkRBTree *tree,
9592 CtkTreeIter *iter,
9593 gint depth,
9594 gboolean recurse)
9595{
9596 CtkRBNode *temp = NULL((void*)0);
9597 CtkTreePath *path = NULL((void*)0);
9598
9599 do
9600 {
9601 ctk_tree_model_ref_node (tree_view->priv->model, iter);
9602 temp = _ctk_rbtree_insert_after (tree, temp, 0, FALSE(0));
9603
9604 if (tree_view->priv->fixed_height > 0)
9605 {
9606 if (CTK_RBNODE_FLAG_SET (temp, CTK_RBNODE_INVALID)(temp?(((temp->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
)
9607 {
9608 _ctk_rbtree_node_set_height (tree, temp, tree_view->priv->fixed_height);
9609 _ctk_rbtree_node_mark_valid (tree, temp);
9610 }
9611 }
9612
9613 if (tree_view->priv->is_list)
9614 continue;
9615
9616 if (recurse)
9617 {
9618 CtkTreeIter child;
9619
9620 if (!path)
9621 path = ctk_tree_model_get_path (tree_view->priv->model, iter);
9622 else
9623 ctk_tree_path_next (path);
9624
9625 if (ctk_tree_model_iter_has_child (tree_view->priv->model, iter))
9626 {
9627 gboolean expand;
9628
9629 g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, iter, path, &expand);
9630
9631 if (ctk_tree_model_iter_children (tree_view->priv->model, &child, iter)
9632 && !expand)
9633 {
9634 temp->children = _ctk_rbtree_new ();
9635 temp->children->parent_tree = tree;
9636 temp->children->parent_node = temp;
9637 ctk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse);
9638 }
9639 }
9640 }
9641
9642 if (ctk_tree_model_iter_has_child (tree_view->priv->model, iter))
9643 {
9644 if ((temp->flags&CTK_RBNODE_IS_PARENT) != CTK_RBNODE_IS_PARENT)
9645 temp->flags ^= CTK_RBNODE_IS_PARENT;
9646 }
9647 }
9648 while (ctk_tree_model_iter_next (tree_view->priv->model, iter));
9649
9650 if (path)
9651 ctk_tree_path_free (path);
9652}
9653
9654/* Make sure the node is visible vertically */
9655static void
9656ctk_tree_view_clamp_node_visible (CtkTreeView *tree_view,
9657 CtkRBTree *tree,
9658 CtkRBNode *node)
9659{
9660 gint node_dy, height;
9661 CtkTreePath *path = NULL((void*)0);
9662
9663 if (!ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
9664 return;
9665
9666 /* just return if the node is visible, avoiding a costly expose */
9667 node_dy = _ctk_rbtree_node_find_offset (tree, node);
9668 height = ctk_tree_view_get_row_height (tree_view, node);
9669 if (! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_INVALID)(node?(((node->flags&CTK_RBNODE_INVALID)==CTK_RBNODE_INVALID
)?(!(0)):(0)):(0))
9670 && node_dy >= ctk_adjustment_get_value (tree_view->priv->vadjustment)
9671 && node_dy + height <= (ctk_adjustment_get_value (tree_view->priv->vadjustment)
9672 + ctk_adjustment_get_page_size (tree_view->priv->vadjustment)))
9673 return;
9674
9675 path = _ctk_tree_path_new_from_rbtree (tree, node);
9676 if (path)
9677 {
9678 ctk_tree_view_scroll_to_cell (tree_view, path, NULL((void*)0), FALSE(0), 0.0, 0.0);
9679 ctk_tree_path_free (path);
9680 }
9681}
9682
9683static void
9684ctk_tree_view_clamp_column_visible (CtkTreeView *tree_view,
9685 CtkTreeViewColumn *column,
9686 gboolean focus_to_cell)
9687{
9688 CtkAllocation allocation;
9689 gint x, width;
9690
9691 if (column == NULL((void*)0))
9692 return;
9693
9694 ctk_widget_get_allocation (ctk_tree_view_column_get_button (column), &allocation);
9695 x = allocation.x;
9696 width = allocation.width;
9697
9698 if (width > ctk_adjustment_get_page_size (tree_view->priv->hadjustment))
9699 {
9700 /* The column is larger than the horizontal page size. If the
9701 * column has cells which can be focused individually, then we make
9702 * sure the cell which gets focus is fully visible (if even the
9703 * focus cell is bigger than the page size, we make sure the
9704 * left-hand side of the cell is visible).
9705 *
9706 * If the column does not have an activatable cell, we
9707 * make sure the left-hand side of the column is visible.
9708 */
9709
9710 if (focus_to_cell && ctk_tree_view_has_can_focus_cell (tree_view))
9711 {
9712 CtkCellArea *cell_area;
9713 CtkCellRenderer *focus_cell;
9714
9715 cell_area = ctk_cell_layout_get_area (CTK_CELL_LAYOUT (column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((column)), ((ctk_cell_layout_get_type ()))))))
);
9716 focus_cell = ctk_cell_area_get_focus_cell (cell_area);
9717
9718 if (ctk_tree_view_column_cell_get_position (column, focus_cell,
9719 &x, &width))
9720 {
9721 if (width < ctk_adjustment_get_page_size (tree_view->priv->hadjustment))
9722 {
9723 if (ctk_adjustment_get_value (tree_view->priv->hadjustment) + ctk_adjustment_get_page_size (tree_view->priv->hadjustment) < x + width)
9724 ctk_adjustment_set_value (tree_view->priv->hadjustment,
9725 x + width - ctk_adjustment_get_page_size (tree_view->priv->hadjustment));
9726 else if (ctk_adjustment_get_value (tree_view->priv->hadjustment) > x)
9727 ctk_adjustment_set_value (tree_view->priv->hadjustment, x);
9728 }
9729 }
9730 }
9731
9732 ctk_adjustment_set_value (tree_view->priv->hadjustment, x);
9733 }
9734 else
9735 {
9736 if ((ctk_adjustment_get_value (tree_view->priv->hadjustment) + ctk_adjustment_get_page_size (tree_view->priv->hadjustment)) < (x + width))
9737 ctk_adjustment_set_value (tree_view->priv->hadjustment,
9738 x + width - ctk_adjustment_get_page_size (tree_view->priv->hadjustment));
9739 else if (ctk_adjustment_get_value (tree_view->priv->hadjustment) > x)
9740 ctk_adjustment_set_value (tree_view->priv->hadjustment, x);
9741 }
9742}
9743
9744/* This function could be more efficient. I'll optimize it if profiling seems
9745 * to imply that it is important */
9746CtkTreePath *
9747_ctk_tree_path_new_from_rbtree (CtkRBTree *tree,
9748 CtkRBNode *node)
9749{
9750 CtkTreePath *path;
9751 CtkRBTree *tmp_tree;
9752 CtkRBNode *tmp_node, *last;
9753 gint count;
9754
9755 path = ctk_tree_path_new ();
9756
9757 g_return_val_if_fail (node != NULL, path)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "node != NULL"); return (
path); } } while (0)
;
9758
9759 count = 1 + node->left->count;
9760
9761 last = node;
9762 tmp_node = node->parent;
9763 tmp_tree = tree;
9764 while (tmp_tree)
9765 {
9766 while (!_ctk_rbtree_is_nil (tmp_node))
9767 {
9768 if (tmp_node->right == last)
9769 count += 1 + tmp_node->left->count;
9770 last = tmp_node;
9771 tmp_node = tmp_node->parent;
9772 }
9773 ctk_tree_path_prepend_index (path, count - 1);
9774 last = tmp_tree->parent_node;
9775 tmp_tree = tmp_tree->parent_tree;
9776 if (last)
9777 {
9778 count = 1 + last->left->count;
9779 tmp_node = last->parent;
9780 }
9781 }
9782 return path;
9783}
9784
9785/* Returns TRUE if we ran out of tree before finding the path. If the path is
9786 * invalid (ie. points to a node that’s not in the tree), *tree and *node are
9787 * both set to NULL.
9788 */
9789gboolean
9790_ctk_tree_view_find_node (CtkTreeView *tree_view,
9791 CtkTreePath *path,
9792 CtkRBTree **tree,
9793 CtkRBNode **node)
9794{
9795 CtkRBNode *tmpnode = NULL((void*)0);
9796 CtkRBTree *tmptree = tree_view->priv->tree;
9797 gint *indices = ctk_tree_path_get_indices (path);
9798 gint depth = ctk_tree_path_get_depth (path);
9799 gint i = 0;
9800
9801 *node = NULL((void*)0);
9802 *tree = NULL((void*)0);
9803
9804 if (depth == 0 || tmptree == NULL((void*)0))
9805 return FALSE(0);
9806 do
9807 {
9808 tmpnode = _ctk_rbtree_find_count (tmptree, indices[i] + 1);
9809 ++i;
9810 if (tmpnode == NULL((void*)0))
9811 {
9812 *tree = NULL((void*)0);
9813 *node = NULL((void*)0);
9814 return FALSE(0);
9815 }
9816 if (i >= depth)
9817 {
9818 *tree = tmptree;
9819 *node = tmpnode;
9820 return FALSE(0);
9821 }
9822 *tree = tmptree;
9823 *node = tmpnode;
9824 tmptree = tmpnode->children;
9825 if (tmptree == NULL((void*)0))
9826 return TRUE(!(0));
9827 }
9828 while (1);
9829}
9830
9831static gboolean
9832ctk_tree_view_is_expander_column (CtkTreeView *tree_view,
9833 CtkTreeViewColumn *column)
9834{
9835 GList *list;
9836
9837 if (tree_view->priv->is_list)
9838 return FALSE(0);
9839
9840 if (tree_view->priv->expander_column != NULL((void*)0))
9841 {
9842 if (tree_view->priv->expander_column == column)
9843 return TRUE(!(0));
9844 return FALSE(0);
9845 }
9846 else
9847 {
9848 for (list = tree_view->priv->columns;
9849 list;
9850 list = list->next)
9851 if (ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
))
9852 break;
9853 if (list && list->data == column)
9854 return TRUE(!(0));
9855 }
9856 return FALSE(0);
9857}
9858
9859static inline gboolean
9860ctk_tree_view_draw_expanders (CtkTreeView *tree_view)
9861{
9862 if (!tree_view->priv->is_list && tree_view->priv->show_expanders)
9863 return TRUE(!(0));
9864 /* else */
9865 return FALSE(0);
9866}
9867
9868static void
9869ctk_tree_view_add_move_binding (CtkBindingSet *binding_set,
9870 guint keyval,
9871 guint modmask,
9872 gboolean add_shifted_binding,
9873 CtkMovementStep step,
9874 gint count)
9875{
9876
9877 ctk_binding_entry_add_signal (binding_set, keyval, modmask,
9878 "move-cursor", 2,
9879 G_TYPE_ENUM((GType) ((12) << (2))), step,
9880 G_TYPE_INT((GType) ((6) << (2))), count);
9881
9882 if (add_shifted_binding)
9883 ctk_binding_entry_add_signal (binding_set, keyval, CDK_SHIFT_MASK,
9884 "move-cursor", 2,
9885 G_TYPE_ENUM((GType) ((12) << (2))), step,
9886 G_TYPE_INT((GType) ((6) << (2))), count);
9887
9888 if ((modmask & CDK_CONTROL_MASK) == CDK_CONTROL_MASK)
9889 return;
9890
9891 ctk_binding_entry_add_signal (binding_set, keyval, CDK_CONTROL_MASK | CDK_SHIFT_MASK,
9892 "move-cursor", 2,
9893 G_TYPE_ENUM((GType) ((12) << (2))), step,
9894 G_TYPE_INT((GType) ((6) << (2))), count);
9895
9896 ctk_binding_entry_add_signal (binding_set, keyval, CDK_CONTROL_MASK,
9897 "move-cursor", 2,
9898 G_TYPE_ENUM((GType) ((12) << (2))), step,
9899 G_TYPE_INT((GType) ((6) << (2))), count);
9900}
9901
9902static gint
9903ctk_tree_view_unref_tree_helper (CtkTreeModel *model,
9904 CtkTreeIter *iter,
9905 CtkRBTree *tree,
9906 CtkRBNode *node)
9907{
9908 gint retval = FALSE(0);
9909 do
9910 {
9911 g_return_val_if_fail (node != NULL, FALSE)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "node != NULL"); return (
(0)); } } while (0)
;
9912
9913 if (node->children)
9914 {
9915 CtkTreeIter child;
9916 CtkRBTree *new_tree;
9917 CtkRBNode *new_node;
9918
9919 new_tree = node->children;
9920 new_node = _ctk_rbtree_first (new_tree);
9921
9922 if (!ctk_tree_model_iter_children (model, &child, iter))
9923 return FALSE(0);
9924
9925 retval = ctk_tree_view_unref_tree_helper (model, &child, new_tree, new_node) | retval;
9926 }
9927
9928 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
9929 retval = TRUE(!(0));
9930 ctk_tree_model_unref_node (model, iter);
9931 node = _ctk_rbtree_next (tree, node);
9932 }
9933 while (ctk_tree_model_iter_next (model, iter));
9934
9935 return retval;
9936}
9937
9938static gint
9939ctk_tree_view_unref_and_check_selection_tree (CtkTreeView *tree_view,
9940 CtkRBTree *tree)
9941{
9942 CtkTreeIter iter;
9943 CtkTreePath *path;
9944 CtkRBNode *node;
9945 gint retval;
9946
9947 if (!tree)
9948 return FALSE(0);
9949
9950 node = _ctk_rbtree_first (tree);
9951
9952 g_return_val_if_fail (node != NULL, FALSE)do { if ((node != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "node != NULL"); return (
(0)); } } while (0)
;
9953 path = _ctk_tree_path_new_from_rbtree (tree, node);
9954 ctk_tree_model_get_iter (CTK_TREE_MODEL (tree_view->priv->model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->model)), ((ctk_tree_model_get_type
()))))))
,
9955 &iter, path);
9956 retval = ctk_tree_view_unref_tree_helper (CTK_TREE_MODEL (tree_view->priv->model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->model)), ((ctk_tree_model_get_type
()))))))
, &iter, tree, node);
9957 ctk_tree_path_free (path);
9958
9959 return retval;
9960}
9961
9962static void
9963ctk_tree_view_set_column_drag_info (CtkTreeView *tree_view,
9964 CtkTreeViewColumn *column)
9965{
9966 CtkTreeViewColumn *left_column;
9967 CtkTreeViewColumn *cur_column = NULL((void*)0);
9968 CtkTreeViewColumnReorder *reorder;
9969 gboolean rtl;
9970 GList *tmp_list;
9971 gint left;
9972
9973 /* We want to precalculate the motion list such that we know what column slots
9974 * are available.
9975 */
9976 left_column = NULL((void*)0);
9977 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
9978
9979 /* First, identify all possible drop spots */
9980 if (rtl)
9981 tmp_list = g_list_last (tree_view->priv->columns);
9982 else
9983 tmp_list = g_list_first (tree_view->priv->columns);
9984
9985 while (tmp_list)
9986 {
9987 cur_column = CTK_TREE_VIEW_COLUMN (tmp_list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tmp_list->data)), ((ctk_tree_view_column_get_type
()))))))
;
9988 tmp_list = rtl ? tmp_list->prev : tmp_list->next;
9989
9990 if (ctk_tree_view_column_get_visible (cur_column) == FALSE(0))
9991 continue;
9992
9993 /* If it's not the column moving and func tells us to skip over the column, we continue. */
9994 if (left_column != column && cur_column != column &&
9995 tree_view->priv->column_drop_func &&
9996 ! tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
9997 {
9998 left_column = cur_column;
9999 continue;
10000 }
10001 reorder = g_slice_new0 (CtkTreeViewColumnReorder)((CtkTreeViewColumnReorder*) g_slice_alloc0 (sizeof (CtkTreeViewColumnReorder
)))
;
10002 reorder->left_column = left_column;
10003 left_column = reorder->right_column = cur_column;
10004
10005 tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
10006 }
10007
10008 /* Add the last one */
10009 if (tree_view->priv->column_drop_func == NULL((void*)0) ||
10010 ((left_column != column) &&
10011 tree_view->priv->column_drop_func (tree_view, column, left_column, NULL((void*)0), tree_view->priv->column_drop_func_data)))
10012 {
10013 reorder = g_slice_new0 (CtkTreeViewColumnReorder)((CtkTreeViewColumnReorder*) g_slice_alloc0 (sizeof (CtkTreeViewColumnReorder
)))
;
10014 reorder->left_column = left_column;
10015 reorder->right_column = NULL((void*)0);
10016 tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
10017 }
10018
10019 /* We quickly check to see if it even makes sense to reorder columns. */
10020 /* If there is nothing that can be moved, then we return */
10021
10022 if (tree_view->priv->column_drag_info == NULL((void*)0))
10023 return;
10024
10025 /* We know there are always 2 slots possbile, as you can always return column. */
10026 /* If that's all there is, return */
10027 if (tree_view->priv->column_drag_info->next == NULL((void*)0) ||
10028 (tree_view->priv->column_drag_info->next->next == NULL((void*)0) &&
10029 ((CtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
10030 ((CtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column))
10031 {
10032 for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
10033 g_slice_free (CtkTreeViewColumnReorder, tmp_list->data)do { if (1) g_slice_free1 (sizeof (CtkTreeViewColumnReorder),
(tmp_list->data)); else (void) ((CtkTreeViewColumnReorder
*) 0 == (tmp_list->data)); } while (0)
;
10034 g_list_free (tree_view->priv->column_drag_info);
10035 tree_view->priv->column_drag_info = NULL((void*)0);
10036 return;
10037 }
10038 /* We fill in the ranges for the columns, now that we've isolated them */
10039 left = - TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view)(10*ctk_tree_view_get_effective_header_height(tree_view));
10040
10041 for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
10042 {
10043 reorder = (CtkTreeViewColumnReorder *) tmp_list->data;
10044
10045 reorder->left_align = left;
10046 if (tmp_list->next != NULL((void*)0))
10047 {
10048 CtkAllocation right_allocation, left_allocation;
10049 CtkWidget *left_button, *right_button;
10050
10051 g_assert (tmp_list->next->data)do { if (tmp_list->next->data) ; else g_assertion_message_expr
("Ctk", "ctktreeview.c", 10051, ((const char*) (__func__)), "tmp_list->next->data"
); } while (0)
;
10052
10053 right_button = ctk_tree_view_column_get_button (reorder->right_column);
10054 left_button = ctk_tree_view_column_get_button
10055 (((CtkTreeViewColumnReorder *)tmp_list->next->data)->left_column);
10056
10057 ctk_widget_get_allocation (right_button, &right_allocation);
10058 ctk_widget_get_allocation (left_button, &left_allocation);
10059 left = reorder->right_align = (right_allocation.x + right_allocation.width + left_allocation.x) / 2;
10060 }
10061 else
10062 {
10063 reorder->right_align = cdk_window_get_width (tree_view->priv->header_window)
10064 + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view)(10*ctk_tree_view_get_effective_header_height(tree_view));
10065 }
10066 }
10067}
10068
10069void
10070_ctk_tree_view_column_start_drag (CtkTreeView *tree_view,
10071 CtkTreeViewColumn *column,
10072 CdkDevice *device)
10073{
10074 CtkAllocation allocation;
10075 CtkAllocation button_allocation;
10076 CtkWidget *button;
10077 CdkWindowAttr attributes;
10078 guint attributes_mask;
10079 CtkStyleContext *context;
10080
10081 g_return_if_fail (tree_view->priv->column_drag_info == NULL)do { if ((tree_view->priv->column_drag_info == ((void*)
0))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "tree_view->priv->column_drag_info == NULL"
); return; } } while (0)
;
10082 g_return_if_fail (tree_view->priv->cur_reorder == NULL)do { if ((tree_view->priv->cur_reorder == ((void*)0))) {
} else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "tree_view->priv->cur_reorder == NULL"); return; } }
while (0)
;
10083 g_return_if_fail (tree_view->priv->drag_window == NULL)do { if ((tree_view->priv->drag_window == ((void*)0))) {
} else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "tree_view->priv->drag_window == NULL"); return; } }
while (0)
;
10084
10085 ctk_tree_view_set_column_drag_info (tree_view, column);
10086
10087 if (tree_view->priv->column_drag_info == NULL((void*)0))
10088 return;
10089
10090 button = ctk_tree_view_column_get_button (column);
10091
10092 context = ctk_widget_get_style_context (button);
10093 ctk_style_context_add_class (context, CTK_STYLE_CLASS_DND"dnd");
10094
10095 ctk_widget_get_allocation (button, &button_allocation);
10096
10097 attributes.window_type = CDK_WINDOW_CHILD;
10098 attributes.wclass = CDK_INPUT_OUTPUT;
10099 attributes.x = button_allocation.x;
10100 attributes.y = 0;
10101 attributes.width = button_allocation.width;
10102 attributes.height = button_allocation.height;
10103 attributes.visual = ctk_widget_get_visual (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10104 attributes.event_mask = CDK_VISIBILITY_NOTIFY_MASK | CDK_POINTER_MOTION_MASK;
10105 attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_VISUAL;
10106
10107 tree_view->priv->drag_window = cdk_window_new (tree_view->priv->header_window,
10108 &attributes,
10109 attributes_mask);
10110 ctk_widget_register_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, tree_view->priv->drag_window);
10111
10112 /* Kids, don't try this at home */
10113 g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button));
10114 ctk_container_remove (CTK_CONTAINER (tree_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_container_get_type ()))))))
, button);
10115 ctk_widget_set_parent_window (button, tree_view->priv->drag_window);
10116 ctk_widget_set_parent (button, CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10117 g_object_unref (button);
10118
10119 ctk_widget_get_allocation (button, &button_allocation);
10120 tree_view->priv->drag_column_x = button_allocation.x;
10121 allocation = button_allocation;
10122 allocation.x = 0;
10123 ctk_widget_size_allocate (button, &allocation);
10124
10125 tree_view->priv->drag_column = column;
10126 cdk_window_show (tree_view->priv->drag_window);
10127
10128 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10129
10130 tree_view->priv->in_column_drag = TRUE(!(0));
10131
10132 /* Widget reparenting above unmaps and indirectly breaks
10133 * the implicit grab, replace it with an active one.
10134 */
10135 cdk_seat_grab (cdk_device_get_seat (device),
10136 tree_view->priv->drag_window,
10137 CDK_SEAT_CAPABILITY_ALL, FALSE(0),
10138 NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0));
10139
10140 ctk_gesture_set_state (tree_view->priv->column_drag_gesture,
10141 CTK_EVENT_SEQUENCE_CLAIMED);
10142}
10143
10144static void
10145ctk_tree_view_queue_draw_arrow (CtkTreeView *tree_view,
10146 CtkRBTree *tree,
10147 CtkRBNode *node)
10148{
10149 CtkAllocation allocation;
10150 CdkRectangle rect;
10151
10152 if (!ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10153 return;
10154
10155 ctk_widget_get_allocation (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &allocation);
10156 rect.x = 0;
10157 rect.width = ctk_tree_view_get_expander_size (tree_view);
10158 rect.width = MAX (rect.width, MAX (tree_view->priv->width, allocation.width))(((rect.width) > ((((tree_view->priv->width) > (allocation
.width)) ? (tree_view->priv->width) : (allocation.width
)))) ? (rect.width) : ((((tree_view->priv->width) > (
allocation.width)) ? (tree_view->priv->width) : (allocation
.width))))
;
10159
10160 rect.y = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
10161 rect.height = ctk_tree_view_get_row_height (tree_view, node);
10162
10163 cdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE(!(0)));
10164}
10165
10166void
10167_ctk_tree_view_queue_draw_node (CtkTreeView *tree_view,
10168 CtkRBTree *tree,
10169 CtkRBNode *node,
10170 const CdkRectangle *clip_rect)
10171{
10172 CtkAllocation allocation;
10173 CdkRectangle rect;
10174
10175 if (!ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10176 return;
10177
10178 ctk_widget_get_allocation (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &allocation);
10179 rect.x = 0;
10180 rect.width = MAX (tree_view->priv->width, allocation.width)(((tree_view->priv->width) > (allocation.width)) ? (
tree_view->priv->width) : (allocation.width))
;
10181
10182 rect.y = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
10183 rect.height = ctk_tree_view_get_row_height (tree_view, node);
10184
10185 if (clip_rect)
10186 {
10187 CdkRectangle new_rect;
10188
10189 cdk_rectangle_intersect (clip_rect, &rect, &new_rect);
10190
10191 cdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE(!(0)));
10192 }
10193 else
10194 {
10195 cdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE(!(0)));
10196 }
10197}
10198
10199static inline gint
10200ctk_tree_view_get_effective_header_height (CtkTreeView *tree_view)
10201{
10202 if (tree_view->priv->headers_visible)
10203 return tree_view->priv->header_height;
10204 /* else */
10205 return 0;
10206}
10207
10208gint
10209_ctk_tree_view_get_header_height (CtkTreeView *tree_view)
10210{
10211 return tree_view->priv->header_height;
10212}
10213
10214void
10215_ctk_tree_view_get_row_separator_func (CtkTreeView *tree_view,
10216 CtkTreeViewRowSeparatorFunc *func,
10217 gpointer *data)
10218{
10219 *func = tree_view->priv->row_separator_func;
10220 *data = tree_view->priv->row_separator_data;
10221}
10222
10223CtkTreePath *
10224_ctk_tree_view_get_anchor_path (CtkTreeView *tree_view)
10225{
10226 if (tree_view->priv->anchor)
10227 return ctk_tree_row_reference_get_path (tree_view->priv->anchor);
10228
10229 return NULL((void*)0);
10230}
10231
10232void
10233_ctk_tree_view_set_anchor_path (CtkTreeView *tree_view,
10234 CtkTreePath *anchor_path)
10235{
10236 if (tree_view->priv->anchor)
10237 {
10238 ctk_tree_row_reference_free (tree_view->priv->anchor);
10239 tree_view->priv->anchor = NULL((void*)0);
10240 }
10241
10242 if (anchor_path && tree_view->priv->model)
10243 tree_view->priv->anchor =
10244 ctk_tree_row_reference_new_proxy (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
,
10245 tree_view->priv->model, anchor_path);
10246}
10247
10248CtkRBTree *
10249_ctk_tree_view_get_rbtree (CtkTreeView *tree_view)
10250{
10251 return tree_view->priv->tree;
10252}
10253
10254gboolean
10255_ctk_tree_view_get_cursor_node (CtkTreeView *tree_view,
10256 CtkRBTree **tree,
10257 CtkRBNode **node)
10258{
10259 CtkTreeViewPrivate *priv;
10260
10261 priv = tree_view->priv;
10262
10263 if (priv->cursor_node == NULL((void*)0))
10264 return FALSE(0);
10265
10266 *tree = priv->cursor_tree;
10267 *node = priv->cursor_node;
10268
10269 return TRUE(!(0));
10270}
10271
10272CdkWindow *
10273_ctk_tree_view_get_header_window (CtkTreeView *tree_view)
10274{
10275 return tree_view->priv->header_window;
10276}
10277
10278CtkTreeViewColumn *
10279_ctk_tree_view_get_focus_column (CtkTreeView *tree_view)
10280{
10281 return tree_view->priv->focus_column;
10282}
10283
10284void
10285_ctk_tree_view_set_focus_column (CtkTreeView *tree_view,
10286 CtkTreeViewColumn *column)
10287{
10288 CtkTreeViewColumn *old_column = tree_view->priv->focus_column;
10289
10290 if (old_column == column)
10291 return;
10292
10293 tree_view->priv->focus_column = column;
10294
10295 _ctk_tree_view_accessible_update_focus_column (tree_view,
10296 old_column,
10297 column);
10298}
10299
10300
10301static void
10302ctk_tree_view_queue_draw_path (CtkTreeView *tree_view,
10303 CtkTreePath *path,
10304 const CdkRectangle *clip_rect)
10305{
10306 CtkRBTree *tree = NULL((void*)0);
10307 CtkRBNode *node = NULL((void*)0);
10308
10309 _ctk_tree_view_find_node (tree_view, path, &tree, &node);
10310
10311 if (tree)
10312 _ctk_tree_view_queue_draw_node (tree_view, tree, node, clip_rect);
10313}
10314
10315/* x and y are the mouse position
10316 */
10317static void
10318ctk_tree_view_draw_arrow (CtkTreeView *tree_view,
10319 cairo_t *cr,
10320 CtkRBTree *tree,
10321 CtkRBNode *node)
10322{
10323 CdkRectangle area;
10324 CtkStateFlags state = 0;
10325 CtkStyleContext *context;
10326 CtkWidget *widget;
10327 gint x_offset = 0;
10328 gint x2;
10329 gint vertical_separator;
10330 CtkCellRendererState flags = 0;
10331
10332 widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
10333 context = ctk_widget_get_style_context (widget);
10334
10335 ctk_widget_style_get (widget,
10336 "vertical-separator", &vertical_separator,
10337 NULL((void*)0));
10338
10339 if (! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
)
10340 return;
10341
10342 ctk_tree_view_get_arrow_xrange (tree_view, tree, &x_offset, &x2);
10343
10344 area.x = x_offset;
10345 area.y = ctk_tree_view_get_cell_area_y_offset (tree_view, tree, node,
10346 vertical_separator);
10347 area.width = x2 - x_offset;
10348 area.height = ctk_tree_view_get_cell_area_height (tree_view, node,
10349 vertical_separator);
10350
10351 if (CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_SELECTED)(node?(((node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
10352 flags |= CTK_CELL_RENDERER_SELECTED;
10353
10354 if (node == tree_view->priv->prelight_node &&
10355 tree_view->priv->arrow_prelit)
10356 flags |= CTK_CELL_RENDERER_PRELIT;
10357
10358 state = ctk_cell_renderer_get_state (NULL((void*)0), widget, flags);
10359
10360 if (node->children != NULL((void*)0))
10361 state |= CTK_STATE_FLAG_CHECKED;
10362 else
10363 state &= ~(CTK_STATE_FLAG_CHECKED);
10364
10365 ctk_style_context_save (context);
10366
10367 ctk_style_context_set_state (context, state);
10368 ctk_style_context_add_class (context, CTK_STYLE_CLASS_EXPANDER"expander");
10369
10370 /* Make sure area.height has the same parity as the "expander-size" style
10371 * property (which area.width is assumed to be exactly equal to). This is done
10372 * to avoid the arrow being vertically centered in a half-pixel, which would
10373 * result in a fuzzy rendering.
10374 */
10375 if (area.height % 2 != area.width % 2)
10376 {
10377 area.y += 1;
10378 area.height -= 1;
10379 }
10380
10381 ctk_render_expander (context, cr,
10382 area.x, area.y,
10383 area.width, area.height);
10384
10385 ctk_style_context_restore (context);
10386}
10387
10388static void
10389ctk_tree_view_focus_to_cursor (CtkTreeView *tree_view)
10390
10391{
10392 CtkTreePath *cursor_path;
10393
10394 if ((tree_view->priv->tree == NULL((void*)0)) ||
10395 (! ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
)))
10396 return;
10397
10398 cursor_path = NULL((void*)0);
10399 if (tree_view->priv->cursor_node)
10400 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
10401 tree_view->priv->cursor_node);
10402
10403 if (cursor_path == NULL((void*)0))
10404 {
10405 /* Consult the selection before defaulting to the
10406 * first focusable element
10407 */
10408 GList *selected_rows;
10409 CtkTreeModel *model;
10410 CtkTreeSelection *selection;
10411
10412 selection = ctk_tree_view_get_selection (tree_view);
10413 selected_rows = ctk_tree_selection_get_selected_rows (selection, &model);
10414
10415 if (selected_rows)
10416 {
10417 cursor_path = ctk_tree_path_copy((const CtkTreePath *)(selected_rows->data));
10418 g_list_free_full (selected_rows, (GDestroyNotify) ctk_tree_path_free);
10419 }
10420 else
10421 {
10422 cursor_path = ctk_tree_path_new_first ();
10423 search_first_focusable_path (tree_view, &cursor_path,
10424 TRUE(!(0)), NULL((void*)0), NULL((void*)0));
10425 }
10426
10427 if (cursor_path)
10428 {
10429 if (ctk_tree_selection_get_mode (tree_view->priv->selection) == CTK_SELECTION_MULTIPLE)
10430 ctk_tree_view_real_set_cursor (tree_view, cursor_path, 0);
10431 else
10432 ctk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT);
10433 }
10434 }
10435
10436 if (cursor_path)
10437 {
10438 tree_view->priv->draw_keyfocus = TRUE(!(0));
10439
10440 ctk_tree_view_queue_draw_path (tree_view, cursor_path, NULL((void*)0));
10441 ctk_tree_path_free (cursor_path);
10442
10443 if (tree_view->priv->focus_column == NULL((void*)0))
10444 {
10445 GList *list;
10446 for (list = tree_view->priv->columns; list; list = list->next)
10447 {
10448 if (ctk_tree_view_column_get_visible (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
))
10449 {
10450 CtkCellArea *cell_area;
10451
10452 _ctk_tree_view_set_focus_column (tree_view, CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
);
10453
10454 /* This happens when the treeview initially grabs focus and there
10455 * is no column in focus, here we explicitly focus into the first cell */
10456 cell_area = ctk_cell_layout_get_area (CTK_CELL_LAYOUT (tree_view->priv->focus_column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->focus_column)), ((ctk_cell_layout_get_type
()))))))
);
10457 if (!ctk_cell_area_get_focus_cell (cell_area))
10458 {
10459 gboolean rtl;
10460
10461 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
10462 ctk_cell_area_focus (cell_area,
10463 rtl ? CTK_DIR_LEFT : CTK_DIR_RIGHT);
10464 }
10465
10466 break;
10467 }
10468 }
10469 }
10470 }
10471}
10472
10473static void
10474ctk_tree_view_move_cursor_up_down (CtkTreeView *tree_view,
10475 gint count)
10476{
10477 gint selection_count;
10478 CtkRBTree *new_cursor_tree = NULL((void*)0);
10479 CtkRBNode *new_cursor_node = NULL((void*)0);
10480 CtkTreePath *cursor_path = NULL((void*)0);
10481 gboolean grab_focus = TRUE(!(0));
10482 gboolean selectable;
10483 CtkDirectionType direction;
10484 CtkCellArea *cell_area = NULL((void*)0);
10485 CtkCellRenderer *last_focus_cell = NULL((void*)0);
10486 CtkTreeIter iter;
10487
10488 if (! ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10489 return;
10490
10491 if (tree_view->priv->cursor_node == NULL((void*)0))
10492 return;
10493
10494 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
10495 tree_view->priv->cursor_node);
10496
10497 direction = count < 0 ? CTK_DIR_UP : CTK_DIR_DOWN;
10498
10499 if (tree_view->priv->focus_column)
10500 cell_area = ctk_cell_layout_get_area (CTK_CELL_LAYOUT (tree_view->priv->focus_column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->focus_column)), ((ctk_cell_layout_get_type
()))))))
);
10501
10502 /* If focus stays in the area for this row, then just return for this round */
10503 if (cell_area && (count == -1 || count == 1) &&
10504 ctk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path))
10505 {
10506 ctk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column,
10507 tree_view->priv->model,
10508 &iter,
10509 CTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, CTK_RBNODE_IS_PARENT)(tree_view->priv->cursor_node?(((tree_view->priv->
cursor_node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
10510 tree_view->priv->cursor_node->children ? TRUE(!(0)) : FALSE(0));
10511
10512 /* Save the last cell that had focus, if we hit the end of the view we'll give
10513 * focus back to it. */
10514 last_focus_cell = ctk_cell_area_get_focus_cell (cell_area);
10515
10516 /* If focus stays in the area, no need to change the cursor row */
10517 if (ctk_cell_area_focus (cell_area, direction))
10518 return;
10519 }
10520
10521 selection_count = ctk_tree_selection_count_selected_rows (tree_view->priv->selection);
10522 selectable = _ctk_tree_selection_row_is_selectable (tree_view->priv->selection,
10523 tree_view->priv->cursor_node,
10524 cursor_path);
10525
10526 if (selection_count == 0
10527 && ctk_tree_selection_get_mode (tree_view->priv->selection) != CTK_SELECTION_NONE
10528 && !tree_view->priv->modify_selection_pressed
10529 && selectable)
10530 {
10531 /* Don't move the cursor, but just select the current node */
10532 new_cursor_tree = tree_view->priv->cursor_tree;
10533 new_cursor_node = tree_view->priv->cursor_node;
10534 }
10535 else
10536 {
10537 if (count == -1)
10538 _ctk_rbtree_prev_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
10539 &new_cursor_tree, &new_cursor_node);
10540 else
10541 _ctk_rbtree_next_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
10542 &new_cursor_tree, &new_cursor_node);
10543 }
10544
10545 ctk_tree_path_free (cursor_path);
10546
10547 if (new_cursor_node)
10548 {
10549 cursor_path = _ctk_tree_path_new_from_rbtree (new_cursor_tree, new_cursor_node);
10550
10551 search_first_focusable_path (tree_view, &cursor_path,
10552 (count != -1),
10553 &new_cursor_tree,
10554 &new_cursor_node);
10555
10556 if (cursor_path)
10557 ctk_tree_path_free (cursor_path);
10558 }
10559
10560 /*
10561 * If the list has only one item and multi-selection is set then select
10562 * the row (if not yet selected).
10563 */
10564 if (ctk_tree_selection_get_mode (tree_view->priv->selection) == CTK_SELECTION_MULTIPLE &&
10565 new_cursor_node == NULL((void*)0))
10566 {
10567 if (count == -1)
10568 _ctk_rbtree_next_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
10569 &new_cursor_tree, &new_cursor_node);
10570 else
10571 _ctk_rbtree_prev_full (tree_view->priv->cursor_tree, tree_view->priv->cursor_node,
10572 &new_cursor_tree, &new_cursor_node);
10573
10574 if (new_cursor_node == NULL((void*)0)
10575 && !CTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, CTK_RBNODE_IS_SELECTED)(tree_view->priv->cursor_node?(((tree_view->priv->
cursor_node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
10576 {
10577 new_cursor_node = tree_view->priv->cursor_node;
10578 new_cursor_tree = tree_view->priv->cursor_tree;
10579 }
10580 else
10581 {
10582 new_cursor_tree = NULL((void*)0);
10583 new_cursor_node = NULL((void*)0);
10584 }
10585 }
10586
10587 if (new_cursor_node)
10588 {
10589 cursor_path = _ctk_tree_path_new_from_rbtree (new_cursor_tree, new_cursor_node);
10590 ctk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT | CLAMP_NODE);
10591 ctk_tree_path_free (cursor_path);
10592
10593 /* Give focus to the area in the new row */
10594 if (cell_area)
10595 ctk_cell_area_focus (cell_area, direction);
10596 }
10597 else
10598 {
10599 ctk_tree_view_clamp_node_visible (tree_view,
10600 tree_view->priv->cursor_tree,
10601 tree_view->priv->cursor_node);
10602
10603 if (!tree_view->priv->extend_selection_pressed)
10604 {
10605 if (! ctk_widget_keynav_failed (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
10606 count < 0 ?
10607 CTK_DIR_UP : CTK_DIR_DOWN))
10608 {
10609 CtkWidget *toplevel = ctk_widget_get_toplevel (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10610
10611 if (toplevel)
10612 ctk_widget_child_focus (toplevel,
10613 count < 0 ?
10614 CTK_DIR_TAB_BACKWARD :
10615 CTK_DIR_TAB_FORWARD);
10616
10617 grab_focus = FALSE(0);
10618 }
10619 }
10620 else
10621 {
10622 ctk_widget_error_bell (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10623 }
10624
10625 if (cell_area)
10626 ctk_cell_area_set_focus_cell (cell_area, last_focus_cell);
10627 }
10628
10629 if (grab_focus)
10630 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10631}
10632
10633static void
10634ctk_tree_view_move_cursor_page_up_down (CtkTreeView *tree_view,
10635 gint count)
10636{
10637 CtkTreePath *old_cursor_path = NULL((void*)0);
10638 CtkTreePath *cursor_path = NULL((void*)0);
10639 CtkRBTree *start_cursor_tree = NULL((void*)0);
10640 CtkRBNode *start_cursor_node = NULL((void*)0);
10641 CtkRBTree *cursor_tree;
10642 CtkRBNode *cursor_node;
10643 gint y;
10644 gint window_y;
10645 gint vertical_separator;
10646
10647 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10648 return;
10649
10650 if (tree_view->priv->cursor_node == NULL((void*)0))
10651 return;
10652
10653 old_cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
10654 tree_view->priv->cursor_node);
10655
10656 ctk_widget_style_get (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, "vertical-separator", &vertical_separator, NULL((void*)0));
10657
10658 y = _ctk_rbtree_node_find_offset (tree_view->priv->cursor_tree, tree_view->priv->cursor_node);
10659 window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y)((y) - tree_view->priv->dy);
10660 y += tree_view->priv->cursor_offset;
10661 y += count * (int)ctk_adjustment_get_page_increment (tree_view->priv->vadjustment);
10662 y = CLAMP (y, (gint)ctk_adjustment_get_lower (tree_view->priv->vadjustment), (gint)ctk_adjustment_get_upper (tree_view->priv->vadjustment) - vertical_separator)(((y) > ((gint)ctk_adjustment_get_upper (tree_view->priv
->vadjustment) - vertical_separator)) ? ((gint)ctk_adjustment_get_upper
(tree_view->priv->vadjustment) - vertical_separator) :
(((y) < ((gint)ctk_adjustment_get_lower (tree_view->priv
->vadjustment))) ? ((gint)ctk_adjustment_get_lower (tree_view
->priv->vadjustment)) : (y)))
;
10663
10664 if (y >= ctk_tree_view_get_height (tree_view))
10665 y = ctk_tree_view_get_height (tree_view) - 1;
10666
10667 tree_view->priv->cursor_offset =
10668 _ctk_rbtree_find_offset (tree_view->priv->tree, y,
10669 &cursor_tree, &cursor_node);
10670
10671 if (cursor_tree == NULL((void*)0))
10672 {
10673 /* FIXME: we lost the cursor. Should we try to get one? */
10674 ctk_tree_path_free (old_cursor_path);
10675 return;
10676 }
10677
10678 if (tree_view->priv->cursor_offset
10679 > ctk_tree_view_get_row_height (tree_view, cursor_node))
10680 {
10681 _ctk_rbtree_next_full (cursor_tree, cursor_node,
10682 &cursor_tree, &cursor_node);
10683 tree_view->priv->cursor_offset -= ctk_tree_view_get_row_height (tree_view, cursor_node);
10684 }
10685
10686 y -= tree_view->priv->cursor_offset;
10687 cursor_path = _ctk_tree_path_new_from_rbtree (cursor_tree, cursor_node);
10688
10689 start_cursor_tree = cursor_tree;
10690 start_cursor_node = cursor_node;
10691
10692 if (! search_first_focusable_path (tree_view, &cursor_path,
10693 (count != -1),
10694 &cursor_tree, &cursor_node))
10695 {
10696 /* It looks like we reached the end of the view without finding
10697 * a focusable row. We will step backwards to find the last
10698 * focusable row.
10699 */
10700 cursor_tree = start_cursor_tree;
10701 cursor_node = start_cursor_node;
10702 cursor_path = _ctk_tree_path_new_from_rbtree (cursor_tree, cursor_node);
10703
10704 search_first_focusable_path (tree_view, &cursor_path,
10705 (count == -1),
10706 &cursor_tree, &cursor_node);
10707 }
10708
10709 if (!cursor_path)
10710 goto cleanup;
10711
10712 /* update y */
10713 y = _ctk_rbtree_node_find_offset (cursor_tree, cursor_node);
10714
10715 ctk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT);
10716
10717 y -= window_y;
10718 ctk_tree_view_scroll_to_point (tree_view, -1, y);
10719 ctk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
10720 _ctk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL((void*)0));
10721
10722 if (!ctk_tree_path_compare (old_cursor_path, cursor_path))
10723 ctk_widget_error_bell (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10724
10725 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10726
10727cleanup:
10728 ctk_tree_path_free (old_cursor_path);
10729 ctk_tree_path_free (cursor_path);
10730}
10731
10732static void
10733ctk_tree_view_move_cursor_left_right (CtkTreeView *tree_view,
10734 gint count)
10735{
10736 CtkTreePath *cursor_path = NULL((void*)0);
10737 CtkTreeViewColumn *column;
10738 CtkTreeIter iter;
10739 GList *list;
10740 gboolean found_column = FALSE(0);
10741 gboolean rtl;
10742 CtkDirectionType direction;
10743 CtkCellArea *cell_area;
10744 CtkCellRenderer *last_focus_cell = NULL((void*)0);
10745 CtkCellArea *last_focus_area = NULL((void*)0);
10746
10747 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
10748
10749 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10750 return;
10751
10752 if (tree_view->priv->cursor_node == NULL((void*)0))
10753 return;
10754
10755 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
10756 tree_view->priv->cursor_node);
10757
10758 if (ctk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE(0))
10759 {
10760 ctk_tree_path_free (cursor_path);
10761 return;
10762 }
10763 ctk_tree_path_free (cursor_path);
10764
10765 list = rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns);
10766 if (tree_view->priv->focus_column)
10767 {
10768 /* Save the cell/area we are moving focus from, if moving the cursor
10769 * by one step hits the end we'll set focus back here */
10770 last_focus_area = ctk_cell_layout_get_area (CTK_CELL_LAYOUT (tree_view->priv->focus_column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->focus_column)), ((ctk_cell_layout_get_type
()))))))
);
10771 last_focus_cell = ctk_cell_area_get_focus_cell (last_focus_area);
10772
10773 for (; list; list = (rtl ? list->prev : list->next))
10774 {
10775 if (list->data == tree_view->priv->focus_column)
10776 break;
10777 }
10778 }
10779
10780 direction = count > 0 ? CTK_DIR_RIGHT : CTK_DIR_LEFT;
10781
10782 while (list)
10783 {
10784 column = list->data;
10785 if (ctk_tree_view_column_get_visible (column) == FALSE(0))
10786 goto loop_end;
10787
10788 ctk_tree_view_column_cell_set_cell_data (column,
10789 tree_view->priv->model,
10790 &iter,
10791 CTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, CTK_RBNODE_IS_PARENT)(tree_view->priv->cursor_node?(((tree_view->priv->
cursor_node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
10792 tree_view->priv->cursor_node->children ? TRUE(!(0)) : FALSE(0));
10793
10794 cell_area = ctk_cell_layout_get_area (CTK_CELL_LAYOUT (column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((column)), ((ctk_cell_layout_get_type ()))))))
);
10795 if (ctk_cell_area_focus (cell_area, direction))
10796 {
10797 _ctk_tree_view_set_focus_column (tree_view, column);
10798 found_column = TRUE(!(0));
10799 break;
10800 }
10801
10802 loop_end:
10803 if (count == 1)
10804 list = rtl ? list->prev : list->next;
10805 else
10806 list = rtl ? list->next : list->prev;
10807 }
10808
10809 if (found_column)
10810 {
10811 if (!ctk_tree_view_has_can_focus_cell (tree_view))
10812 _ctk_tree_view_queue_draw_node (tree_view,
10813 tree_view->priv->cursor_tree,
10814 tree_view->priv->cursor_node,
10815 NULL((void*)0));
10816 g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
10817 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10818 }
10819 else
10820 {
10821 ctk_widget_error_bell (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10822
10823 if (last_focus_area)
10824 ctk_cell_area_set_focus_cell (last_focus_area, last_focus_cell);
10825 }
10826
10827 ctk_tree_view_clamp_column_visible (tree_view,
10828 tree_view->priv->focus_column, TRUE(!(0)));
10829}
10830
10831static void
10832ctk_tree_view_move_cursor_start_end (CtkTreeView *tree_view,
10833 gint count)
10834{
10835 CtkRBTree *cursor_tree;
10836 CtkRBNode *cursor_node;
10837 CtkTreePath *path;
10838 CtkTreePath *old_path;
10839
10840 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10841 return;
10842
10843 g_return_if_fail (tree_view->priv->tree != NULL)do { if ((tree_view->priv->tree != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "tree_view->priv->tree != NULL"); return; } } while (
0)
;
10844
10845 ctk_tree_view_get_cursor (tree_view, &old_path, NULL((void*)0));
10846
10847 cursor_tree = tree_view->priv->tree;
10848
10849 if (count == -1)
10850 {
10851 cursor_node = _ctk_rbtree_first (cursor_tree);
10852
10853 /* Now go forward to find the first focusable row. */
10854 path = _ctk_tree_path_new_from_rbtree (cursor_tree, cursor_node);
10855 search_first_focusable_path (tree_view, &path,
10856 TRUE(!(0)), &cursor_tree, &cursor_node);
10857 }
10858 else
10859 {
10860 cursor_node = cursor_tree->root;
10861
10862 do
10863 {
10864 while (cursor_node && !_ctk_rbtree_is_nil (cursor_node->right))
10865 cursor_node = cursor_node->right;
10866 if (cursor_node->children == NULL((void*)0))
10867 break;
10868
10869 cursor_tree = cursor_node->children;
10870 cursor_node = cursor_tree->root;
10871 }
10872 while (1);
10873
10874 /* Now go backwards to find last focusable row. */
10875 path = _ctk_tree_path_new_from_rbtree (cursor_tree, cursor_node);
10876 search_first_focusable_path (tree_view, &path,
10877 FALSE(0), &cursor_tree, &cursor_node);
10878 }
10879
10880 if (!path)
10881 goto cleanup;
10882
10883 if (ctk_tree_path_compare (old_path, path))
10884 {
10885 ctk_tree_view_real_set_cursor (tree_view, path, CLEAR_AND_SELECT | CLAMP_NODE);
10886 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10887 }
10888 else
10889 {
10890 ctk_widget_error_bell (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10891 }
10892
10893cleanup:
10894 ctk_tree_path_free (old_path);
10895 ctk_tree_path_free (path);
10896}
10897
10898static gboolean
10899ctk_tree_view_real_select_all (CtkTreeView *tree_view)
10900{
10901 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10902 return FALSE(0);
10903
10904 if (ctk_tree_selection_get_mode (tree_view->priv->selection) != CTK_SELECTION_MULTIPLE)
10905 return FALSE(0);
10906
10907 ctk_tree_selection_select_all (tree_view->priv->selection);
10908
10909 return TRUE(!(0));
10910}
10911
10912static gboolean
10913ctk_tree_view_real_unselect_all (CtkTreeView *tree_view)
10914{
10915 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10916 return FALSE(0);
10917
10918 if (ctk_tree_selection_get_mode (tree_view->priv->selection) != CTK_SELECTION_MULTIPLE)
10919 return FALSE(0);
10920
10921 ctk_tree_selection_unselect_all (tree_view->priv->selection);
10922
10923 return TRUE(!(0));
10924}
10925
10926static gboolean
10927ctk_tree_view_real_select_cursor_row (CtkTreeView *tree_view,
10928 gboolean start_editing)
10929{
10930 CtkRBTree *new_tree = NULL((void*)0);
10931 CtkRBNode *new_node = NULL((void*)0);
10932 CtkRBTree *cursor_tree = NULL((void*)0);
10933 CtkRBNode *cursor_node = NULL((void*)0);
10934 CtkTreePath *cursor_path = NULL((void*)0);
10935 CtkTreeSelectMode mode = 0;
10936
10937 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
10938 return FALSE(0);
10939
10940 if (tree_view->priv->cursor_node == NULL((void*)0))
10941 return FALSE(0);
10942
10943 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
10944 tree_view->priv->cursor_node);
10945
10946 _ctk_tree_view_find_node (tree_view, cursor_path,
10947 &cursor_tree, &cursor_node);
10948
10949 if (cursor_tree == NULL((void*)0))
10950 {
10951 ctk_tree_path_free (cursor_path);
10952 return FALSE(0);
10953 }
10954
10955 if (!tree_view->priv->extend_selection_pressed && start_editing &&
10956 tree_view->priv->focus_column)
10957 {
10958 if (ctk_tree_view_start_editing (tree_view, cursor_path, FALSE(0)))
10959 {
10960 ctk_tree_path_free (cursor_path);
10961 return TRUE(!(0));
10962 }
10963 }
10964
10965 if (tree_view->priv->modify_selection_pressed)
10966 mode |= CTK_TREE_SELECT_MODE_TOGGLE;
10967 if (tree_view->priv->extend_selection_pressed)
10968 mode |= CTK_TREE_SELECT_MODE_EXTEND;
10969
10970 _ctk_tree_selection_internal_select_node (tree_view->priv->selection,
10971 cursor_node,
10972 cursor_tree,
10973 cursor_path,
10974 mode,
10975 FALSE(0));
10976
10977 /* We bail out if the original (tree, node) don't exist anymore after
10978 * handling the selection-changed callback. We do return TRUE because
10979 * the key press has been handled at this point.
10980 */
10981 _ctk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node);
10982
10983 if (cursor_tree != new_tree || cursor_node != new_node)
10984 return FALSE(0);
10985
10986 ctk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
10987
10988 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
10989 _ctk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL((void*)0));
10990
10991 if (!tree_view->priv->extend_selection_pressed)
10992 ctk_tree_view_row_activated (tree_view, cursor_path,
10993 tree_view->priv->focus_column);
10994
10995 ctk_tree_path_free (cursor_path);
10996
10997 return TRUE(!(0));
10998}
10999
11000static gboolean
11001ctk_tree_view_real_toggle_cursor_row (CtkTreeView *tree_view)
11002{
11003 CtkRBTree *new_tree = NULL((void*)0);
11004 CtkRBNode *new_node = NULL((void*)0);
11005 CtkTreePath *cursor_path = NULL((void*)0);
11006
11007 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11008 return FALSE(0);
11009
11010 if (tree_view->priv->cursor_node == NULL((void*)0))
11011 return FALSE(0);
11012
11013 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
11014 tree_view->priv->cursor_node);
11015
11016 _ctk_tree_selection_internal_select_node (tree_view->priv->selection,
11017 tree_view->priv->cursor_node,
11018 tree_view->priv->cursor_tree,
11019 cursor_path,
11020 CTK_TREE_SELECT_MODE_TOGGLE,
11021 FALSE(0));
11022
11023 /* We bail out if the original (tree, node) don't exist anymore after
11024 * handling the selection-changed callback. We do return TRUE because
11025 * the key press has been handled at this point.
11026 */
11027 _ctk_tree_view_find_node (tree_view, cursor_path, &new_tree, &new_node);
11028
11029 if (tree_view->priv->cursor_node != new_node)
11030 return FALSE(0);
11031
11032 ctk_tree_view_clamp_node_visible (tree_view,
11033 tree_view->priv->cursor_tree,
11034 tree_view->priv->cursor_node);
11035
11036 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11037 ctk_tree_view_queue_draw_path (tree_view, cursor_path, NULL((void*)0));
11038 ctk_tree_path_free (cursor_path);
11039
11040 return TRUE(!(0));
11041}
11042
11043static gboolean
11044ctk_tree_view_real_expand_collapse_cursor_row (CtkTreeView *tree_view,
11045 gboolean logical,
11046 gboolean expand,
11047 gboolean open_all)
11048{
11049 CtkTreePath *cursor_path = NULL((void*)0);
11050
11051 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11052 return FALSE(0);
11053
11054 if (tree_view->priv->cursor_node == NULL((void*)0))
11055 return FALSE(0);
11056
11057 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
11058 tree_view->priv->cursor_node);
11059
11060 /* Don't handle the event if we aren't an expander */
11061 if (!CTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, CTK_RBNODE_IS_PARENT)(tree_view->priv->cursor_node?(((tree_view->priv->
cursor_node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
)
11062 return FALSE(0);
11063
11064 if (!logical
11065 && ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL)
11066 expand = !expand;
11067
11068 if (expand)
11069 ctk_tree_view_real_expand_row (tree_view,
11070 cursor_path,
11071 tree_view->priv->cursor_tree,
11072 tree_view->priv->cursor_node,
11073 open_all,
11074 TRUE(!(0)));
11075 else
11076 ctk_tree_view_real_collapse_row (tree_view,
11077 cursor_path,
11078 tree_view->priv->cursor_tree,
11079 tree_view->priv->cursor_node,
11080 TRUE(!(0)));
11081
11082 ctk_tree_path_free (cursor_path);
11083
11084 return TRUE(!(0));
11085}
11086
11087static gboolean
11088ctk_tree_view_real_select_cursor_parent (CtkTreeView *tree_view)
11089{
11090 CtkTreePath *cursor_path = NULL((void*)0);
11091 CdkModifierType state;
11092
11093 if (!ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11094 goto out;
11095
11096 if (tree_view->priv->cursor_node == NULL((void*)0))
11097 goto out;
11098
11099 cursor_path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
11100 tree_view->priv->cursor_node);
11101
11102 if (tree_view->priv->cursor_tree->parent_node)
11103 {
11104 ctk_tree_view_queue_draw_path (tree_view, cursor_path, NULL((void*)0));
11105
11106 ctk_tree_path_up (cursor_path);
11107
11108 if (ctk_get_current_event_state (&state))
11109 {
11110 CdkModifierType modify_mod_mask;
11111
11112 modify_mod_mask =
11113 ctk_widget_get_modifier_mask (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
11114 CDK_MODIFIER_INTENT_MODIFY_SELECTION);
11115
11116 if ((state & modify_mod_mask) == modify_mod_mask)
11117 tree_view->priv->modify_selection_pressed = TRUE(!(0));
11118 }
11119
11120 ctk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT | CLAMP_NODE);
11121 ctk_tree_path_free (cursor_path);
11122
11123 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11124
11125 tree_view->priv->modify_selection_pressed = FALSE(0);
11126
11127 return TRUE(!(0));
11128 }
11129
11130 out:
11131
11132 tree_view->priv->search_entry_avoid_unhandled_binding = TRUE(!(0));
11133 return FALSE(0);
11134}
11135
11136static gboolean
11137ctk_tree_view_search_entry_flush_timeout (CtkTreeView *tree_view)
11138{
11139 ctk_tree_view_search_window_hide (tree_view->priv->search_window, tree_view, NULL((void*)0));
11140 tree_view->priv->typeselect_flush_timeout = 0;
11141
11142 return FALSE(0);
11143}
11144
11145/* Cut and paste from ctkwindow.c */
11146static void
11147send_focus_change (CtkWidget *widget,
11148 CdkDevice *device,
11149 gboolean in)
11150{
11151 CdkDeviceManager *device_manager;
11152 GList *devices, *d;
11153
11154 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
;
11155 device_manager = cdk_display_get_device_manager (ctk_widget_get_display (widget));
11156 devices = cdk_device_manager_list_devices (device_manager, CDK_DEVICE_TYPE_MASTER);
11157 devices = g_list_concat (devices, cdk_device_manager_list_devices (device_manager, CDK_DEVICE_TYPE_SLAVE));
11158 devices = g_list_concat (devices, cdk_device_manager_list_devices (device_manager, CDK_DEVICE_TYPE_FLOATING));
11159 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop ;
11160
11161 for (d = devices; d; d = d->next)
11162 {
11163 CdkDevice *dev = d->data;
11164 CdkEvent *fevent;
11165 CdkWindow *window;
11166
11167 if (cdk_device_get_source (dev) != CDK_SOURCE_KEYBOARD)
11168 continue;
11169
11170 window = ctk_widget_get_window (widget);
11171
11172 /* Skip non-master keyboards that haven't
11173 * selected for events from this window
11174 */
11175 if (cdk_device_get_device_type (dev) != CDK_DEVICE_TYPE_MASTER &&
11176 !cdk_window_get_device_events (window, dev))
11177 continue;
11178
11179 fevent = cdk_event_new (CDK_FOCUS_CHANGE);
11180
11181 fevent->focus_change.type = CDK_FOCUS_CHANGE;
11182 fevent->focus_change.window = g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
11183 fevent->focus_change.in = in;
11184 cdk_event_set_device (fevent, device);
11185
11186 ctk_widget_send_focus_change (widget, fevent);
11187
11188 cdk_event_free (fevent);
11189 }
11190
11191 g_list_free (devices);
11192}
11193
11194static void
11195ctk_tree_view_ensure_interactive_directory (CtkTreeView *tree_view)
11196{
11197 CtkWidget *frame, *vbox, *toplevel;
11198 CdkScreen *screen;
11199
11200 if (tree_view->priv->search_custom_entry_set)
11201 return;
11202
11203 toplevel = ctk_widget_get_toplevel (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11204 screen = ctk_widget_get_screen (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11205
11206 if (tree_view->priv->search_window != NULL((void*)0))
11207 {
11208 if (ctk_window_has_group (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
))
11209 ctk_window_group_add_window (ctk_window_get_group (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
),
11210 CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
);
11211 else if (ctk_window_has_group (CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
))
11212 ctk_window_group_remove_window (ctk_window_get_group (CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
),
11213 CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
);
11214
11215 ctk_window_set_screen (CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
, screen);
11216
11217 return;
11218 }
11219
11220 tree_view->priv->search_window = ctk_window_new (CTK_WINDOW_POPUP);
11221 ctk_window_set_screen (CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
, screen);
11222
11223 if (ctk_window_has_group (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
))
11224 ctk_window_group_add_window (ctk_window_get_group (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
),
11225 CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
);
11226
11227 ctk_window_set_type_hint (CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
,
11228 CDK_WINDOW_TYPE_HINT_UTILITY);
11229 ctk_window_set_modal (CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
, TRUE(!(0)));
11230 ctk_window_set_transient_for (CTK_WINDOW (tree_view->priv->search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_window_get_type
()))))))
,
11231 CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
11232
11233 g_signal_connect (tree_view->priv->search_window, "delete-event",g_signal_connect_data ((tree_view->priv->search_window)
, ("delete-event"), (((GCallback) (ctk_tree_view_search_delete_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11234 G_CALLBACK (ctk_tree_view_search_delete_event),g_signal_connect_data ((tree_view->priv->search_window)
, ("delete-event"), (((GCallback) (ctk_tree_view_search_delete_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11235 tree_view)g_signal_connect_data ((tree_view->priv->search_window)
, ("delete-event"), (((GCallback) (ctk_tree_view_search_delete_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
11236 g_signal_connect (tree_view->priv->search_window, "key-press-event",g_signal_connect_data ((tree_view->priv->search_window)
, ("key-press-event"), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11237 G_CALLBACK (ctk_tree_view_search_key_press_event),g_signal_connect_data ((tree_view->priv->search_window)
, ("key-press-event"), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11238 tree_view)g_signal_connect_data ((tree_view->priv->search_window)
, ("key-press-event"), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
11239 g_signal_connect (tree_view->priv->search_window, "button-press-event",g_signal_connect_data ((tree_view->priv->search_window)
, ("button-press-event"), (((GCallback) (ctk_tree_view_search_button_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11240 G_CALLBACK (ctk_tree_view_search_button_press_event),g_signal_connect_data ((tree_view->priv->search_window)
, ("button-press-event"), (((GCallback) (ctk_tree_view_search_button_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11241 tree_view)g_signal_connect_data ((tree_view->priv->search_window)
, ("button-press-event"), (((GCallback) (ctk_tree_view_search_button_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
11242 g_signal_connect (tree_view->priv->search_window, "scroll-event",g_signal_connect_data ((tree_view->priv->search_window)
, ("scroll-event"), (((GCallback) (ctk_tree_view_search_scroll_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11243 G_CALLBACK (ctk_tree_view_search_scroll_event),g_signal_connect_data ((tree_view->priv->search_window)
, ("scroll-event"), (((GCallback) (ctk_tree_view_search_scroll_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11244 tree_view)g_signal_connect_data ((tree_view->priv->search_window)
, ("scroll-event"), (((GCallback) (ctk_tree_view_search_scroll_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
11245
11246 frame = ctk_frame_new (NULL((void*)0));
11247 ctk_frame_set_shadow_type (CTK_FRAME (frame)((((CtkFrame*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((frame)), ((ctk_frame_get_type ()))))))
, CTK_SHADOW_ETCHED_IN);
11248 ctk_widget_show (frame);
11249 ctk_container_add (CTK_CONTAINER (tree_view->priv->search_window)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_window)), ((ctk_container_get_type
()))))))
, frame);
11250
11251 vbox = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0);
11252 ctk_widget_show (vbox);
11253 ctk_container_add (CTK_CONTAINER (frame)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((frame)), ((ctk_container_get_type ()))))))
, vbox);
11254 ctk_container_set_border_width (CTK_CONTAINER (vbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_container_get_type ()))))))
, 3);
11255
11256 /* add entry */
11257 tree_view->priv->search_entry = ctk_entry_new ();
11258 ctk_widget_show (tree_view->priv->search_entry);
11259 g_signal_connect (tree_view->priv->search_entry, "populate-popup",g_signal_connect_data ((tree_view->priv->search_entry),
("populate-popup"), (((GCallback) (ctk_tree_view_search_disable_popdown
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11260 G_CALLBACK (ctk_tree_view_search_disable_popdown),g_signal_connect_data ((tree_view->priv->search_entry),
("populate-popup"), (((GCallback) (ctk_tree_view_search_disable_popdown
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11261 tree_view)g_signal_connect_data ((tree_view->priv->search_entry),
("populate-popup"), (((GCallback) (ctk_tree_view_search_disable_popdown
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
11262 g_signal_connect (tree_view->priv->search_entry,g_signal_connect_data ((tree_view->priv->search_entry),
("activate"), (((GCallback) (ctk_tree_view_search_activate))
), (tree_view), ((void*)0), (GConnectFlags) 0)
11263 "activate", G_CALLBACK (ctk_tree_view_search_activate),g_signal_connect_data ((tree_view->priv->search_entry),
("activate"), (((GCallback) (ctk_tree_view_search_activate))
), (tree_view), ((void*)0), (GConnectFlags) 0)
11264 tree_view)g_signal_connect_data ((tree_view->priv->search_entry),
("activate"), (((GCallback) (ctk_tree_view_search_activate))
), (tree_view), ((void*)0), (GConnectFlags) 0)
;
11265
11266 g_signal_connect (_ctk_entry_get_im_context (CTK_ENTRY (tree_view->priv->search_entry)),g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("preedit-changed"), (((GCallback) (ctk_tree_view_search_preedit_changed
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11267 "preedit-changed",g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("preedit-changed"), (((GCallback) (ctk_tree_view_search_preedit_changed
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11268 G_CALLBACK (ctk_tree_view_search_preedit_changed),g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("preedit-changed"), (((GCallback) (ctk_tree_view_search_preedit_changed
))), (tree_view), ((void*)0), (GConnectFlags) 0)
11269 tree_view)g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("preedit-changed"), (((GCallback) (ctk_tree_view_search_preedit_changed
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
11270 g_signal_connect (_ctk_entry_get_im_context (CTK_ENTRY (tree_view->priv->search_entry)),g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("commit"), (((GCallback) (ctk_tree_view_search_commit))), (
tree_view), ((void*)0), (GConnectFlags) 0)
11271 "commit",g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("commit"), (((GCallback) (ctk_tree_view_search_commit))), (
tree_view), ((void*)0), (GConnectFlags) 0)
11272 G_CALLBACK (ctk_tree_view_search_commit),g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("commit"), (((GCallback) (ctk_tree_view_search_commit))), (
tree_view), ((void*)0), (GConnectFlags) 0)
11273 tree_view)g_signal_connect_data ((_ctk_entry_get_im_context (((((CtkEntry
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((tree_view
->priv->search_entry)), ((ctk_entry_get_type ()))))))))
, ("commit"), (((GCallback) (ctk_tree_view_search_commit))), (
tree_view), ((void*)0), (GConnectFlags) 0)
;
11274
11275 ctk_container_add (CTK_CONTAINER (vbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_container_get_type ()))))))
,
11276 tree_view->priv->search_entry);
11277
11278 ctk_widget_realize (tree_view->priv->search_entry);
11279}
11280
11281/* Pops up the interactive search entry. If keybinding is TRUE then the user
11282 * started this by typing the start_interactive_search keybinding. Otherwise, it came from
11283 */
11284static gboolean
11285ctk_tree_view_real_start_interactive_search (CtkTreeView *tree_view,
11286 CdkDevice *device,
11287 gboolean keybinding)
11288{
11289 /* We only start interactive search if we have focus or the columns
11290 * have focus. If one of our children have focus, we don't want to
11291 * start the search.
11292 */
11293 GList *list;
11294 gboolean found_focus = FALSE(0);
11295
11296 if (!tree_view->priv->enable_search && !keybinding)
11297 return FALSE(0);
11298
11299 if (tree_view->priv->search_custom_entry_set)
11300 return FALSE(0);
11301
11302 if (tree_view->priv->search_window != NULL((void*)0) &&
11303 ctk_widget_get_visible (tree_view->priv->search_window))
11304 return TRUE(!(0));
11305
11306 for (list = tree_view->priv->columns; list; list = list->next)
11307 {
11308 CtkTreeViewColumn *column;
11309 CtkWidget *button;
11310
11311 column = list->data;
11312 if (!ctk_tree_view_column_get_visible (column))
11313 continue;
11314
11315 button = ctk_tree_view_column_get_button (column);
11316 if (ctk_widget_has_focus (button))
11317 {
11318 found_focus = TRUE(!(0));
11319 break;
11320 }
11321 }
11322
11323 if (ctk_widget_has_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11324 found_focus = TRUE(!(0));
11325
11326 if (!found_focus)
11327 return FALSE(0);
11328
11329 if (tree_view->priv->search_column < 0)
11330 return FALSE(0);
11331
11332 ctk_tree_view_ensure_interactive_directory (tree_view);
11333
11334 if (keybinding)
11335 ctk_entry_set_text (CTK_ENTRY (tree_view->priv->search_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_entry_get_type
()))))))
, "");
11336
11337 /* done, show it */
11338 tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window, tree_view->priv->search_position_user_data);
11339
11340 /* Grab focus without selecting all the text. */
11341 ctk_entry_grab_focus_without_selecting (CTK_ENTRY (tree_view->priv->search_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_entry_get_type
()))))))
);
11342
11343 ctk_widget_show (tree_view->priv->search_window);
11344 if (tree_view->priv->search_entry_changed_id == 0)
11345 {
11346 tree_view->priv->search_entry_changed_id =
11347 g_signal_connect (tree_view->priv->search_entry, "changed",g_signal_connect_data ((tree_view->priv->search_entry),
("changed"), (((GCallback) (ctk_tree_view_search_init))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11348 G_CALLBACK (ctk_tree_view_search_init),g_signal_connect_data ((tree_view->priv->search_entry),
("changed"), (((GCallback) (ctk_tree_view_search_init))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11349 tree_view)g_signal_connect_data ((tree_view->priv->search_entry),
("changed"), (((GCallback) (ctk_tree_view_search_init))), (tree_view
), ((void*)0), (GConnectFlags) 0)
;
11350 }
11351
11352 tree_view->priv->typeselect_flush_timeout =
11353 cdk_threads_add_timeout (CTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT5000,
11354 (GSourceFunc) ctk_tree_view_search_entry_flush_timeout,
11355 tree_view);
11356 g_source_set_name_by_id (tree_view->priv->typeselect_flush_timeout, "[ctk+] ctk_tree_view_search_entry_flush_timeout");
11357
11358 /* send focus-in event */
11359 send_focus_change (tree_view->priv->search_entry, device, TRUE(!(0)));
11360
11361 /* search first matching iter */
11362 ctk_tree_view_search_init (tree_view->priv->search_entry, tree_view);
11363
11364 return TRUE(!(0));
11365}
11366
11367static gboolean
11368ctk_tree_view_start_interactive_search (CtkTreeView *tree_view)
11369{
11370 return ctk_tree_view_real_start_interactive_search (tree_view,
11371 ctk_get_current_event_device (),
11372 TRUE(!(0)));
11373}
11374
11375/* Callbacks */
11376static void
11377ctk_tree_view_adjustment_changed (CtkAdjustment *adjustment G_GNUC_UNUSED__attribute__ ((__unused__)),
11378 CtkTreeView *tree_view)
11379{
11380 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11381 {
11382 gint dy;
11383
11384 cdk_window_move (tree_view->priv->bin_window,
11385 - ctk_adjustment_get_value (tree_view->priv->hadjustment),
11386 ctk_tree_view_get_effective_header_height (tree_view));
11387 cdk_window_move (tree_view->priv->header_window,
11388 - ctk_adjustment_get_value (tree_view->priv->hadjustment),
11389 0);
11390 dy = tree_view->priv->dy - (int) ctk_adjustment_get_value (tree_view->priv->vadjustment);
11391 cdk_window_scroll (tree_view->priv->bin_window, 0, dy);
11392
11393 if (dy != 0)
11394 {
11395 /* update our dy and top_row */
11396 tree_view->priv->dy = (int) ctk_adjustment_get_value (tree_view->priv->vadjustment);
11397
11398 update_prelight (tree_view,
11399 tree_view->priv->event_last_x,
11400 tree_view->priv->event_last_y);
11401
11402 if (!tree_view->priv->in_top_row_to_dy)
11403 ctk_tree_view_dy_to_top_row (tree_view);
11404
11405 }
11406 }
11407}
11408
11409
11410
11411/* Public methods
11412 */
11413
11414/**
11415 * ctk_tree_view_new:
11416 *
11417 * Creates a new #CtkTreeView widget.
11418 *
11419 * Returns: A newly created #CtkTreeView widget.
11420 **/
11421CtkWidget *
11422ctk_tree_view_new (void)
11423{
11424 return g_object_new (CTK_TYPE_TREE_VIEW(ctk_tree_view_get_type ()), NULL((void*)0));
11425}
11426
11427/**
11428 * ctk_tree_view_new_with_model:
11429 * @model: the model.
11430 *
11431 * Creates a new #CtkTreeView widget with the model initialized to @model.
11432 *
11433 * Returns: A newly created #CtkTreeView widget.
11434 **/
11435CtkWidget *
11436ctk_tree_view_new_with_model (CtkTreeModel *model)
11437{
11438 return g_object_new (CTK_TYPE_TREE_VIEW(ctk_tree_view_get_type ()), "model", model, NULL((void*)0));
11439}
11440
11441/* Public Accessors
11442 */
11443
11444/**
11445 * ctk_tree_view_get_model:
11446 * @tree_view: a #CtkTreeView
11447 *
11448 * Returns the model the #CtkTreeView is based on. Returns %NULL if the
11449 * model is unset.
11450 *
11451 * Returns: (transfer none) (nullable): A #CtkTreeModel, or %NULL if
11452 * none is currently being used.
11453 **/
11454CtkTreeModel *
11455ctk_tree_view_get_model (CtkTreeView *tree_view)
11456{
11457 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
11458
11459 return tree_view->priv->model;
11460}
11461
11462/**
11463 * ctk_tree_view_set_model:
11464 * @tree_view: A #CtkTreeView.
11465 * @model: (allow-none): The model.
11466 *
11467 * Sets the model for a #CtkTreeView. If the @tree_view already has a model
11468 * set, it will remove it before setting the new model. If @model is %NULL,
11469 * then it will unset the old model.
11470 **/
11471void
11472ctk_tree_view_set_model (CtkTreeView *tree_view,
11473 CtkTreeModel *model)
11474{
11475 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
11476 g_return_if_fail (model == NULL || CTK_IS_TREE_MODEL (model))do { if ((model == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((model)); GType __t = ((ctk_tree_model_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "model == NULL || CTK_IS_TREE_MODEL (model)"
); return; } } while (0)
;
11477
11478 if (model == tree_view->priv->model)
11479 return;
11480
11481 if (tree_view->priv->scroll_to_path)
11482 {
11483 ctk_tree_row_reference_free (tree_view->priv->scroll_to_path);
11484 tree_view->priv->scroll_to_path = NULL((void*)0);
11485 }
11486
11487 if (tree_view->priv->rubber_band_status)
11488 ctk_tree_view_stop_rubber_band (tree_view);
11489
11490 if (tree_view->priv->model)
11491 {
11492 GList *tmplist = tree_view->priv->columns;
11493
11494 ctk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
11495 ctk_tree_view_stop_editing (tree_view, TRUE(!(0)));
11496
11497 g_signal_handlers_disconnect_by_func (tree_view->priv->model,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_changed), (tree_view)
)
11498 ctk_tree_view_row_changed,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_changed), (tree_view)
)
11499 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_changed), (tree_view)
)
;
11500 g_signal_handlers_disconnect_by_func (tree_view->priv->model,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_inserted), (tree_view
))
11501 ctk_tree_view_row_inserted,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_inserted), (tree_view
))
11502 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_inserted), (tree_view
))
;
11503 g_signal_handlers_disconnect_by_func (tree_view->priv->model,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_has_child_toggled), (
tree_view))
11504 ctk_tree_view_row_has_child_toggled,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_has_child_toggled), (
tree_view))
11505 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_has_child_toggled), (
tree_view))
;
11506 g_signal_handlers_disconnect_by_func (tree_view->priv->model,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_deleted), (tree_view)
)
11507 ctk_tree_view_row_deleted,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_deleted), (tree_view)
)
11508 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_row_deleted), (tree_view)
)
;
11509 g_signal_handlers_disconnect_by_func (tree_view->priv->model,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_rows_reordered), (tree_view
))
11510 ctk_tree_view_rows_reordered,g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_rows_reordered), (tree_view
))
11511 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
model), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_rows_reordered), (tree_view
))
;
11512
11513 for (; tmplist; tmplist = tmplist->next)
11514 _ctk_tree_view_column_unset_model (tmplist->data,
11515 tree_view->priv->model);
11516
11517 if (tree_view->priv->tree)
11518 ctk_tree_view_free_rbtree (tree_view);
11519
11520 ctk_tree_row_reference_free (tree_view->priv->drag_dest_row);
11521 tree_view->priv->drag_dest_row = NULL((void*)0);
11522 ctk_tree_row_reference_free (tree_view->priv->anchor);
11523 tree_view->priv->anchor = NULL((void*)0);
11524 ctk_tree_row_reference_free (tree_view->priv->top_row);
11525 tree_view->priv->top_row = NULL((void*)0);
11526 ctk_tree_row_reference_free (tree_view->priv->scroll_to_path);
11527 tree_view->priv->scroll_to_path = NULL((void*)0);
11528
11529 tree_view->priv->scroll_to_column = NULL((void*)0);
11530
11531 g_object_unref (tree_view->priv->model);
11532
11533 tree_view->priv->search_column = -1;
11534 tree_view->priv->fixed_height_check = 0;
11535 tree_view->priv->fixed_height = -1;
11536 tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
11537 }
11538
11539 tree_view->priv->model = model;
11540
11541 if (tree_view->priv->model)
11542 {
11543 gint i;
11544 CtkTreePath *path;
11545 CtkTreeIter iter;
11546 CtkTreeModelFlags flags;
11547
11548 if (tree_view->priv->search_column == -1)
11549 {
11550 for (i = 0; i < ctk_tree_model_get_n_columns (model); i++)
11551 {
11552 GType type = ctk_tree_model_get_column_type (model, i);
11553
11554 if (g_value_type_transformable (type, G_TYPE_STRING((GType) ((16) << (2)))))
11555 {
11556 tree_view->priv->search_column = i;
11557 break;
11558 }
11559 }
11560 }
11561
11562 g_object_ref (tree_view->priv->model)((__typeof__ (tree_view->priv->model)) (g_object_ref) (
tree_view->priv->model))
;
11563 g_signal_connect (tree_view->priv->model,g_signal_connect_data ((tree_view->priv->model), ("row-changed"
), (((GCallback) (ctk_tree_view_row_changed))), (tree_view), (
(void*)0), (GConnectFlags) 0)
11564 "row-changed",g_signal_connect_data ((tree_view->priv->model), ("row-changed"
), (((GCallback) (ctk_tree_view_row_changed))), (tree_view), (
(void*)0), (GConnectFlags) 0)
11565 G_CALLBACK (ctk_tree_view_row_changed),g_signal_connect_data ((tree_view->priv->model), ("row-changed"
), (((GCallback) (ctk_tree_view_row_changed))), (tree_view), (
(void*)0), (GConnectFlags) 0)
11566 tree_view)g_signal_connect_data ((tree_view->priv->model), ("row-changed"
), (((GCallback) (ctk_tree_view_row_changed))), (tree_view), (
(void*)0), (GConnectFlags) 0)
;
11567 g_signal_connect (tree_view->priv->model,g_signal_connect_data ((tree_view->priv->model), ("row-inserted"
), (((GCallback) (ctk_tree_view_row_inserted))), (tree_view),
((void*)0), (GConnectFlags) 0)
11568 "row-inserted",g_signal_connect_data ((tree_view->priv->model), ("row-inserted"
), (((GCallback) (ctk_tree_view_row_inserted))), (tree_view),
((void*)0), (GConnectFlags) 0)
11569 G_CALLBACK (ctk_tree_view_row_inserted),g_signal_connect_data ((tree_view->priv->model), ("row-inserted"
), (((GCallback) (ctk_tree_view_row_inserted))), (tree_view),
((void*)0), (GConnectFlags) 0)
11570 tree_view)g_signal_connect_data ((tree_view->priv->model), ("row-inserted"
), (((GCallback) (ctk_tree_view_row_inserted))), (tree_view),
((void*)0), (GConnectFlags) 0)
;
11571 g_signal_connect (tree_view->priv->model,g_signal_connect_data ((tree_view->priv->model), ("row-has-child-toggled"
), (((GCallback) (ctk_tree_view_row_has_child_toggled))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11572 "row-has-child-toggled",g_signal_connect_data ((tree_view->priv->model), ("row-has-child-toggled"
), (((GCallback) (ctk_tree_view_row_has_child_toggled))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11573 G_CALLBACK (ctk_tree_view_row_has_child_toggled),g_signal_connect_data ((tree_view->priv->model), ("row-has-child-toggled"
), (((GCallback) (ctk_tree_view_row_has_child_toggled))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11574 tree_view)g_signal_connect_data ((tree_view->priv->model), ("row-has-child-toggled"
), (((GCallback) (ctk_tree_view_row_has_child_toggled))), (tree_view
), ((void*)0), (GConnectFlags) 0)
;
11575 g_signal_connect (tree_view->priv->model,g_signal_connect_data ((tree_view->priv->model), ("row-deleted"
), (((GCallback) (ctk_tree_view_row_deleted))), (tree_view), (
(void*)0), (GConnectFlags) 0)
11576 "row-deleted",g_signal_connect_data ((tree_view->priv->model), ("row-deleted"
), (((GCallback) (ctk_tree_view_row_deleted))), (tree_view), (
(void*)0), (GConnectFlags) 0)
11577 G_CALLBACK (ctk_tree_view_row_deleted),g_signal_connect_data ((tree_view->priv->model), ("row-deleted"
), (((GCallback) (ctk_tree_view_row_deleted))), (tree_view), (
(void*)0), (GConnectFlags) 0)
11578 tree_view)g_signal_connect_data ((tree_view->priv->model), ("row-deleted"
), (((GCallback) (ctk_tree_view_row_deleted))), (tree_view), (
(void*)0), (GConnectFlags) 0)
;
11579 g_signal_connect (tree_view->priv->model,g_signal_connect_data ((tree_view->priv->model), ("rows-reordered"
), (((GCallback) (ctk_tree_view_rows_reordered))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11580 "rows-reordered",g_signal_connect_data ((tree_view->priv->model), ("rows-reordered"
), (((GCallback) (ctk_tree_view_rows_reordered))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11581 G_CALLBACK (ctk_tree_view_rows_reordered),g_signal_connect_data ((tree_view->priv->model), ("rows-reordered"
), (((GCallback) (ctk_tree_view_rows_reordered))), (tree_view
), ((void*)0), (GConnectFlags) 0)
11582 tree_view)g_signal_connect_data ((tree_view->priv->model), ("rows-reordered"
), (((GCallback) (ctk_tree_view_rows_reordered))), (tree_view
), ((void*)0), (GConnectFlags) 0)
;
11583
11584 flags = ctk_tree_model_get_flags (tree_view->priv->model);
11585 if ((flags & CTK_TREE_MODEL_LIST_ONLY) == CTK_TREE_MODEL_LIST_ONLY)
11586 tree_view->priv->is_list = TRUE(!(0));
11587 else
11588 tree_view->priv->is_list = FALSE(0);
11589
11590 path = ctk_tree_path_new_first ();
11591 if (ctk_tree_model_get_iter (tree_view->priv->model, &iter, path))
11592 {
11593 tree_view->priv->tree = _ctk_rbtree_new ();
11594 ctk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE(0));
11595 _ctk_tree_view_accessible_add (tree_view, tree_view->priv->tree, NULL((void*)0));
11596 }
11597 ctk_tree_path_free (path);
11598
11599 /* FIXME: do I need to do this? ctk_tree_view_create_buttons (tree_view); */
11600 install_presize_handler (tree_view);
11601 }
11602
11603 ctk_tree_view_real_set_cursor (tree_view, NULL((void*)0), CURSOR_INVALID);
11604
11605 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_MODEL]);
11606
11607 if (tree_view->priv->selection)
11608 _ctk_tree_selection_emit_changed (tree_view->priv->selection);
11609
11610 if (tree_view->priv->pixel_cache != NULL((void*)0))
11611 _ctk_pixel_cache_set_always_cache (tree_view->priv->pixel_cache, (model != NULL((void*)0)));
11612
11613 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11614 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11615}
11616
11617/**
11618 * ctk_tree_view_get_selection:
11619 * @tree_view: A #CtkTreeView.
11620 *
11621 * Gets the #CtkTreeSelection associated with @tree_view.
11622 *
11623 * Returns: (transfer none): A #CtkTreeSelection object.
11624 **/
11625CtkTreeSelection *
11626ctk_tree_view_get_selection (CtkTreeView *tree_view)
11627{
11628 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
11629
11630 return tree_view->priv->selection;
11631}
11632
11633/**
11634 * ctk_tree_view_get_hadjustment:
11635 * @tree_view: A #CtkTreeView
11636 *
11637 * Gets the #CtkAdjustment currently being used for the horizontal aspect.
11638 *
11639 * Returns: (transfer none): A #CtkAdjustment object, or %NULL
11640 * if none is currently being used.
11641 *
11642 * Deprecated: 3.0: Use ctk_scrollable_get_hadjustment()
11643 **/
11644CtkAdjustment *
11645ctk_tree_view_get_hadjustment (CtkTreeView *tree_view)
11646{
11647 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
11648
11649 return ctk_tree_view_do_get_hadjustment (tree_view);
11650}
11651
11652static CtkAdjustment *
11653ctk_tree_view_do_get_hadjustment (CtkTreeView *tree_view)
11654{
11655 return tree_view->priv->hadjustment;
11656}
11657
11658/**
11659 * ctk_tree_view_set_hadjustment:
11660 * @tree_view: A #CtkTreeView
11661 * @adjustment: (allow-none): The #CtkAdjustment to set, or %NULL
11662 *
11663 * Sets the #CtkAdjustment for the current horizontal aspect.
11664 *
11665 * Deprecated: 3.0: Use ctk_scrollable_set_hadjustment()
11666 **/
11667void
11668ctk_tree_view_set_hadjustment (CtkTreeView *tree_view,
11669 CtkAdjustment *adjustment)
11670{
11671 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
11672 g_return_if_fail (adjustment == NULL || CTK_IS_ADJUSTMENT (adjustment))do { if ((adjustment == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((adjustment)); GType __t = ((ctk_adjustment_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "adjustment == NULL || CTK_IS_ADJUSTMENT (adjustment)"
); return; } } while (0)
;
11673
11674 ctk_tree_view_do_set_hadjustment (tree_view, adjustment);
11675}
11676
11677static void
11678ctk_tree_view_do_set_hadjustment (CtkTreeView *tree_view,
11679 CtkAdjustment *adjustment)
11680{
11681 CtkTreeViewPrivate *priv = tree_view->priv;
11682
11683 if (adjustment && priv->hadjustment == adjustment)
11684 return;
11685
11686 if (priv->hadjustment != NULL((void*)0))
11687 {
11688 g_signal_handlers_disconnect_by_func (priv->hadjustment,g_signal_handlers_disconnect_matched ((priv->hadjustment),
(GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_adjustment_changed), (tree_view
))
11689 ctk_tree_view_adjustment_changed,g_signal_handlers_disconnect_matched ((priv->hadjustment),
(GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_adjustment_changed), (tree_view
))
11690 tree_view)g_signal_handlers_disconnect_matched ((priv->hadjustment),
(GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_adjustment_changed), (tree_view
))
;
11691 g_object_unref (priv->hadjustment);
11692 }
11693
11694 if (adjustment == NULL((void*)0))
11695 adjustment = ctk_adjustment_new (0.0, 0.0, 0.0,
11696 0.0, 0.0, 0.0);
11697
11698 g_signal_connect (adjustment, "value-changed",g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback
) (ctk_tree_view_adjustment_changed))), (tree_view), ((void*)
0), (GConnectFlags) 0)
11699 G_CALLBACK (ctk_tree_view_adjustment_changed), tree_view)g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback
) (ctk_tree_view_adjustment_changed))), (tree_view), ((void*)
0), (GConnectFlags) 0)
;
11700 priv->hadjustment = g_object_ref_sink (adjustment)((__typeof__ (adjustment)) (g_object_ref_sink) (adjustment));
11701 /* FIXME: Adjustment should probably be populated here with fresh values, but
11702 * internal details are too complicated for me to decipher right now.
11703 */
11704 ctk_tree_view_adjustment_changed (NULL((void*)0), tree_view);
11705
11706 g_object_notify (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, "hadjustment");
11707}
11708
11709/**
11710 * ctk_tree_view_get_vadjustment:
11711 * @tree_view: A #CtkTreeView
11712 *
11713 * Gets the #CtkAdjustment currently being used for the vertical aspect.
11714 *
11715 * Returns: (transfer none): A #CtkAdjustment object, or %NULL
11716 * if none is currently being used.
11717 *
11718 * Deprecated: 3.0: Use ctk_scrollable_get_vadjustment()
11719 **/
11720CtkAdjustment *
11721ctk_tree_view_get_vadjustment (CtkTreeView *tree_view)
11722{
11723 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
11724
11725 return ctk_tree_view_do_get_vadjustment (tree_view);
11726}
11727
11728static CtkAdjustment *
11729ctk_tree_view_do_get_vadjustment (CtkTreeView *tree_view)
11730{
11731 return tree_view->priv->vadjustment;
11732}
11733
11734/**
11735 * ctk_tree_view_set_vadjustment:
11736 * @tree_view: A #CtkTreeView
11737 * @adjustment: (allow-none): The #CtkAdjustment to set, or %NULL
11738 *
11739 * Sets the #CtkAdjustment for the current vertical aspect.
11740 *
11741 * Deprecated: 3.0: Use ctk_scrollable_set_vadjustment()
11742 **/
11743void
11744ctk_tree_view_set_vadjustment (CtkTreeView *tree_view,
11745 CtkAdjustment *adjustment)
11746{
11747 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
11748 g_return_if_fail (adjustment == NULL || CTK_IS_ADJUSTMENT (adjustment))do { if ((adjustment == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((adjustment)); GType __t = ((ctk_adjustment_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "adjustment == NULL || CTK_IS_ADJUSTMENT (adjustment)"
); return; } } while (0)
;
11749
11750 ctk_tree_view_do_set_vadjustment (tree_view, adjustment);
11751}
11752
11753static void
11754ctk_tree_view_do_set_vadjustment (CtkTreeView *tree_view,
11755 CtkAdjustment *adjustment)
11756{
11757 CtkTreeViewPrivate *priv = tree_view->priv;
11758
11759 if (adjustment && priv->vadjustment == adjustment)
11760 return;
11761
11762 if (priv->vadjustment != NULL((void*)0))
11763 {
11764 g_signal_handlers_disconnect_by_func (priv->vadjustment,g_signal_handlers_disconnect_matched ((priv->vadjustment),
(GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_adjustment_changed), (tree_view
))
11765 ctk_tree_view_adjustment_changed,g_signal_handlers_disconnect_matched ((priv->vadjustment),
(GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_adjustment_changed), (tree_view
))
11766 tree_view)g_signal_handlers_disconnect_matched ((priv->vadjustment),
(GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (ctk_tree_view_adjustment_changed), (tree_view
))
;
11767 g_object_unref (priv->vadjustment);
11768 }
11769
11770 if (adjustment == NULL((void*)0))
11771 adjustment = ctk_adjustment_new (0.0, 0.0, 0.0,
11772 0.0, 0.0, 0.0);
11773
11774 g_signal_connect (adjustment, "value-changed",g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback
) (ctk_tree_view_adjustment_changed))), (tree_view), ((void*)
0), (GConnectFlags) 0)
11775 G_CALLBACK (ctk_tree_view_adjustment_changed), tree_view)g_signal_connect_data ((adjustment), ("value-changed"), (((GCallback
) (ctk_tree_view_adjustment_changed))), (tree_view), ((void*)
0), (GConnectFlags) 0)
;
11776 priv->vadjustment = g_object_ref_sink (adjustment)((__typeof__ (adjustment)) (g_object_ref_sink) (adjustment));
11777 /* FIXME: Adjustment should probably be populated here with fresh values, but
11778 * internal details are too complicated for me to decipher right now.
11779 */
11780 ctk_tree_view_adjustment_changed (NULL((void*)0), tree_view);
11781 g_object_notify (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, "vadjustment");
11782}
11783
11784/* Column and header operations */
11785
11786/**
11787 * ctk_tree_view_get_headers_visible:
11788 * @tree_view: A #CtkTreeView.
11789 *
11790 * Returns %TRUE if the headers on the @tree_view are visible.
11791 *
11792 * Returns: Whether the headers are visible or not.
11793 **/
11794gboolean
11795ctk_tree_view_get_headers_visible (CtkTreeView *tree_view)
11796{
11797 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
11798
11799 return tree_view->priv->headers_visible;
11800}
11801
11802/**
11803 * ctk_tree_view_set_headers_visible:
11804 * @tree_view: A #CtkTreeView.
11805 * @headers_visible: %TRUE if the headers are visible
11806 *
11807 * Sets the visibility state of the headers.
11808 **/
11809void
11810ctk_tree_view_set_headers_visible (CtkTreeView *tree_view,
11811 gboolean headers_visible)
11812{
11813 gint x, y;
11814 GList *list;
11815 CtkTreeViewColumn *column;
11816 CtkAllocation allocation;
11817 CtkWidget *button;
11818
11819 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
11820
11821 headers_visible = !! headers_visible;
11822
11823 if (tree_view->priv->headers_visible == headers_visible)
11824 return;
11825
11826 tree_view->priv->headers_visible = headers_visible == TRUE(!(0));
11827
11828 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11829 {
11830 cdk_window_get_position (tree_view->priv->bin_window, &x, &y);
11831 if (headers_visible)
11832 {
11833 ctk_widget_get_allocation (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &allocation);
11834 cdk_window_move_resize (tree_view->priv->bin_window,
11835 x, y + ctk_tree_view_get_effective_header_height (tree_view),
11836 tree_view->priv->width, allocation.height - + ctk_tree_view_get_effective_header_height (tree_view));
11837
11838 if (ctk_widget_get_mapped (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
11839 ctk_tree_view_map_buttons (tree_view);
11840 }
11841 else
11842 {
11843 cdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, ctk_tree_view_get_height (tree_view));
11844
11845 for (list = tree_view->priv->columns; list; list = list->next)
11846 {
11847 column = list->data;
11848 button = ctk_tree_view_column_get_button (column);
11849
11850 ctk_widget_hide (button);
11851 ctk_widget_unmap (button);
11852 }
11853 cdk_window_hide (tree_view->priv->header_window);
11854 }
11855 }
11856
11857 ctk_widget_get_allocation (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &allocation);
11858 ctk_adjustment_configure (tree_view->priv->vadjustment,
11859 ctk_adjustment_get_value (tree_view->priv->vadjustment),
11860 0,
11861 ctk_tree_view_get_height (tree_view),
11862 ctk_adjustment_get_step_increment (tree_view->priv->vadjustment),
11863 (allocation.height - ctk_tree_view_get_effective_header_height (tree_view)) / 2,
11864 allocation.height - ctk_tree_view_get_effective_header_height (tree_view));
11865
11866 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11867
11868 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_HEADERS_VISIBLE]);
11869}
11870
11871/**
11872 * ctk_tree_view_columns_autosize:
11873 * @tree_view: A #CtkTreeView.
11874 *
11875 * Resizes all columns to their optimal width. Only works after the
11876 * treeview has been realized.
11877 **/
11878void
11879ctk_tree_view_columns_autosize (CtkTreeView *tree_view)
11880{
11881 gboolean dirty = FALSE(0);
11882 GList *list;
11883 CtkTreeViewColumn *column;
11884
11885 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
11886
11887 for (list = tree_view->priv->columns; list; list = list->next)
11888 {
11889 column = list->data;
11890 if (ctk_tree_view_column_get_sizing (column) == CTK_TREE_VIEW_COLUMN_AUTOSIZE)
11891 continue;
11892 _ctk_tree_view_column_cell_set_dirty (column, TRUE(!(0)));
11893 dirty = TRUE(!(0));
11894 }
11895
11896 if (dirty)
11897 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11898}
11899
11900/**
11901 * ctk_tree_view_set_headers_clickable:
11902 * @tree_view: A #CtkTreeView.
11903 * @setting: %TRUE if the columns are clickable.
11904 *
11905 * Allow the column title buttons to be clicked.
11906 **/
11907void
11908ctk_tree_view_set_headers_clickable (CtkTreeView *tree_view,
11909 gboolean setting)
11910{
11911 GList *list;
11912 gboolean changed = FALSE(0);
11913
11914 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
11915
11916 for (list = tree_view->priv->columns; list; list = list->next)
11917 {
11918 if (ctk_tree_view_column_get_clickable (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
) != setting)
11919 {
11920 ctk_tree_view_column_set_clickable (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
, setting);
11921 changed = TRUE(!(0));
11922 }
11923 }
11924
11925 if (changed)
11926 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_HEADERS_CLICKABLE]);
11927}
11928
11929
11930/**
11931 * ctk_tree_view_get_headers_clickable:
11932 * @tree_view: A #CtkTreeView.
11933 *
11934 * Returns whether all header columns are clickable.
11935 *
11936 * Returns: %TRUE if all header columns are clickable, otherwise %FALSE
11937 *
11938 * Since: 2.10
11939 **/
11940gboolean
11941ctk_tree_view_get_headers_clickable (CtkTreeView *tree_view)
11942{
11943 GList *list;
11944
11945 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
11946
11947 for (list = tree_view->priv->columns; list; list = list->next)
11948 if (!ctk_tree_view_column_get_clickable (CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
))
11949 return FALSE(0);
11950
11951 return TRUE(!(0));
11952}
11953
11954/**
11955 * ctk_tree_view_set_rules_hint:
11956 * @tree_view: a #CtkTreeView
11957 * @setting: %TRUE if the tree requires reading across rows
11958 *
11959 * Sets a hint for the theme to draw even/odd rows in the @tree_view
11960 * with different colors, also known as "zebra striping".
11961 *
11962 * This function tells the CTK+ theme that the user interface for your
11963 * application requires users to read across tree rows and associate
11964 * cells with one another.
11965 *
11966 * Do not use it just because you prefer the appearance of the ruled
11967 * tree; that’s a question for the theme. Some themes will draw tree
11968 * rows in alternating colors even when rules are turned off, and
11969 * users who prefer that appearance all the time can choose those
11970 * themes. You should call this function only as a semantic hint to
11971 * the theme engine that your tree makes alternating colors useful
11972 * from a functional standpoint (since it has lots of columns,
11973 * generally).
11974 *
11975 * Deprecated: 3.14
11976 */
11977void
11978ctk_tree_view_set_rules_hint (CtkTreeView *tree_view,
11979 gboolean setting)
11980{
11981 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
11982
11983 setting = setting != FALSE(0);
11984
11985 if (tree_view->priv->has_rules != setting)
11986 {
11987 tree_view->priv->has_rules = setting;
11988 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
11989 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_RULES_HINT]);
11990 }
11991}
11992
11993/**
11994 * ctk_tree_view_get_rules_hint:
11995 * @tree_view: a #CtkTreeView
11996 *
11997 * Gets the setting set by ctk_tree_view_set_rules_hint().
11998 *
11999 * Returns: %TRUE if the hint is set
12000 *
12001 * Deprecated: 3.14
12002 */
12003gboolean
12004ctk_tree_view_get_rules_hint (CtkTreeView *tree_view)
12005{
12006 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
12007
12008 return tree_view->priv->has_rules;
12009}
12010
12011
12012/**
12013 * ctk_tree_view_set_activate_on_single_click:
12014 * @tree_view: a #CtkTreeView
12015 * @single: %TRUE to emit row-activated on a single click
12016 *
12017 * Cause the #CtkTreeView::row-activated signal to be emitted
12018 * on a single click instead of a double click.
12019 *
12020 * Since: 3.8
12021 **/
12022void
12023ctk_tree_view_set_activate_on_single_click (CtkTreeView *tree_view,
12024 gboolean single)
12025{
12026 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12027
12028 single = single != FALSE(0);
12029
12030 if (tree_view->priv->activate_on_single_click == single)
12031 return;
12032
12033 tree_view->priv->activate_on_single_click = single;
12034 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_ACTIVATE_ON_SINGLE_CLICK]);
12035}
12036
12037/**
12038 * ctk_tree_view_get_activate_on_single_click:
12039 * @tree_view: a #CtkTreeView
12040 *
12041 * Gets the setting set by ctk_tree_view_set_activate_on_single_click().
12042 *
12043 * Returns: %TRUE if row-activated will be emitted on a single click
12044 *
12045 * Since: 3.8
12046 **/
12047gboolean
12048ctk_tree_view_get_activate_on_single_click (CtkTreeView *tree_view)
12049{
12050 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
12051
12052 return tree_view->priv->activate_on_single_click;
12053}
12054
12055/* Public Column functions
12056 */
12057
12058/**
12059 * ctk_tree_view_append_column:
12060 * @tree_view: A #CtkTreeView.
12061 * @column: The #CtkTreeViewColumn to add.
12062 *
12063 * Appends @column to the list of columns. If @tree_view has “fixed_height”
12064 * mode enabled, then @column must have its “sizing” property set to be
12065 * CTK_TREE_VIEW_COLUMN_FIXED.
12066 *
12067 * Returns: The number of columns in @tree_view after appending.
12068 **/
12069gint
12070ctk_tree_view_append_column (CtkTreeView *tree_view,
12071 CtkTreeViewColumn *column)
12072{
12073 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (-1); } } while (
0)
;
12074 g_return_val_if_fail (CTK_IS_TREE_VIEW_COLUMN (column), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((column)); GType __t = ((ctk_tree_view_column_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_VIEW_COLUMN (column)"); return
(-1); } } while (0)
;
12075 g_return_val_if_fail (ctk_tree_view_column_get_tree_view (column) == NULL, -1)do { if ((ctk_tree_view_column_get_tree_view (column) == ((void
*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "ctk_tree_view_column_get_tree_view (column) == NULL"
); return (-1); } } while (0)
;
12076
12077 return ctk_tree_view_insert_column (tree_view, column, -1);
12078}
12079
12080/**
12081 * ctk_tree_view_remove_column:
12082 * @tree_view: A #CtkTreeView.
12083 * @column: The #CtkTreeViewColumn to remove.
12084 *
12085 * Removes @column from @tree_view.
12086 *
12087 * Returns: The number of columns in @tree_view after removing.
12088 **/
12089gint
12090ctk_tree_view_remove_column (CtkTreeView *tree_view,
12091 CtkTreeViewColumn *column)
12092{
12093 guint position;
12094
12095 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (-1); } } while (
0)
;
12096 g_return_val_if_fail (CTK_IS_TREE_VIEW_COLUMN (column), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((column)); GType __t = ((ctk_tree_view_column_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_VIEW_COLUMN (column)"); return
(-1); } } while (0)
;
12097 g_return_val_if_fail (ctk_tree_view_column_get_tree_view (column) == CTK_WIDGET (tree_view), -1)do { if ((ctk_tree_view_column_get_tree_view (column) == ((((
CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ())))))))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"ctk_tree_view_column_get_tree_view (column) == CTK_WIDGET (tree_view)"
); return (-1); } } while (0)
;
12098
12099 if (tree_view->priv->focus_column == column)
12100 _ctk_tree_view_set_focus_column (tree_view, NULL((void*)0));
12101
12102 if (tree_view->priv->edited_column == column)
12103 {
12104 ctk_tree_view_stop_editing (tree_view, TRUE(!(0)));
12105
12106 /* no need to, but just to be sure ... */
12107 tree_view->priv->edited_column = NULL((void*)0);
12108 }
12109
12110 if (tree_view->priv->expander_column == column)
12111 tree_view->priv->expander_column = NULL((void*)0);
12112
12113 g_signal_handlers_disconnect_by_func (column,g_signal_handlers_disconnect_matched ((column), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (column_sizing_notify))), (tree_view))
12114 G_CALLBACK (column_sizing_notify),g_signal_handlers_disconnect_matched ((column), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (column_sizing_notify))), (tree_view))
12115 tree_view)g_signal_handlers_disconnect_matched ((column), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (column_sizing_notify))), (tree_view))
;
12116
12117 position = g_list_index (tree_view->priv->columns, column);
12118
12119 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
12120 _ctk_tree_view_column_unrealize_button (column);
12121
12122 _ctk_tree_view_column_unset_tree_view (column);
12123
12124 tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
12125 tree_view->priv->n_columns--;
12126
12127 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
12128 {
12129 GList *list;
12130
12131 for (list = tree_view->priv->columns; list; list = list->next)
12132 {
12133 CtkTreeViewColumn *tmp_column;
12134
12135 tmp_column = CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
;
12136 if (ctk_tree_view_column_get_visible (tmp_column))
12137 _ctk_tree_view_column_cell_set_dirty (tmp_column, TRUE(!(0)));
12138 }
12139
12140 if (tree_view->priv->n_columns == 0 &&
12141 ctk_tree_view_get_headers_visible (tree_view))
12142 cdk_window_hide (tree_view->priv->header_window);
12143
12144 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
12145 }
12146
12147 _ctk_tree_view_accessible_remove_column (tree_view, column, position);
12148
12149 g_object_unref (column);
12150 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
12151
12152 return tree_view->priv->n_columns;
12153}
12154
12155/**
12156 * ctk_tree_view_insert_column:
12157 * @tree_view: A #CtkTreeView.
12158 * @column: The #CtkTreeViewColumn to be inserted.
12159 * @position: The position to insert @column in.
12160 *
12161 * This inserts the @column into the @tree_view at @position. If @position is
12162 * -1, then the column is inserted at the end. If @tree_view has
12163 * “fixed_height” mode enabled, then @column must have its “sizing” property
12164 * set to be CTK_TREE_VIEW_COLUMN_FIXED.
12165 *
12166 * Returns: The number of columns in @tree_view after insertion.
12167 **/
12168gint
12169ctk_tree_view_insert_column (CtkTreeView *tree_view,
12170 CtkTreeViewColumn *column,
12171 gint position)
12172{
12173 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (-1); } } while (
0)
;
12174 g_return_val_if_fail (CTK_IS_TREE_VIEW_COLUMN (column), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((column)); GType __t = ((ctk_tree_view_column_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_VIEW_COLUMN (column)"); return
(-1); } } while (0)
;
12175 g_return_val_if_fail (ctk_tree_view_column_get_tree_view (column) == NULL, -1)do { if ((ctk_tree_view_column_get_tree_view (column) == ((void
*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "ctk_tree_view_column_get_tree_view (column) == NULL"
); return (-1); } } while (0)
;
12176
12177 if (tree_view->priv->fixed_height_mode)
12178 g_return_val_if_fail (ctk_tree_view_column_get_sizing (column)do { if ((ctk_tree_view_column_get_sizing (column) == CTK_TREE_VIEW_COLUMN_FIXED
)) { } else { g_return_if_fail_warning ("Ctk", ((const char*)
(__func__)), "ctk_tree_view_column_get_sizing (column) == CTK_TREE_VIEW_COLUMN_FIXED"
); return (-1); } } while (0)
12179 == CTK_TREE_VIEW_COLUMN_FIXED, -1)do { if ((ctk_tree_view_column_get_sizing (column) == CTK_TREE_VIEW_COLUMN_FIXED
)) { } else { g_return_if_fail_warning ("Ctk", ((const char*)
(__func__)), "ctk_tree_view_column_get_sizing (column) == CTK_TREE_VIEW_COLUMN_FIXED"
); return (-1); } } while (0)
;
12180
12181 if (position < 0 || position > tree_view->priv->n_columns)
12182 position = tree_view->priv->n_columns;
12183
12184 g_object_ref_sink (column)((__typeof__ (column)) (g_object_ref_sink) (column));
12185
12186 if (tree_view->priv->n_columns == 0 &&
12187 ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) &&
12188 ctk_tree_view_get_headers_visible (tree_view))
12189 {
12190 cdk_window_show (tree_view->priv->header_window);
12191 }
12192
12193 g_signal_connect (column, "notify::sizing",g_signal_connect_data ((column), ("notify::sizing"), (((GCallback
) (column_sizing_notify))), (tree_view), ((void*)0), (GConnectFlags
) 0)
12194 G_CALLBACK (column_sizing_notify), tree_view)g_signal_connect_data ((column), ("notify::sizing"), (((GCallback
) (column_sizing_notify))), (tree_view), ((void*)0), (GConnectFlags
) 0)
;
12195
12196 tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
12197 column, position);
12198 tree_view->priv->n_columns++;
12199
12200 _ctk_tree_view_column_set_tree_view (column, tree_view);
12201
12202 ctk_tree_view_update_button_position (tree_view, column);
12203
12204 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
12205 {
12206 GList *list;
12207
12208 _ctk_tree_view_column_realize_button (column);
12209
12210 for (list = tree_view->priv->columns; list; list = list->next)
12211 {
12212 column = CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
;
12213 if (ctk_tree_view_column_get_visible (column))
12214 _ctk_tree_view_column_cell_set_dirty (column, TRUE(!(0)));
12215 }
12216 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
12217 }
12218
12219 _ctk_tree_view_accessible_add_column (tree_view, column, position);
12220
12221 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
12222
12223 return tree_view->priv->n_columns;
12224}
12225
12226/**
12227 * ctk_tree_view_insert_column_with_attributes:
12228 * @tree_view: A #CtkTreeView
12229 * @position: The position to insert the new column in
12230 * @title: The title to set the header to
12231 * @cell: The #CtkCellRenderer
12232 * @...: A %NULL-terminated list of attributes
12233 *
12234 * Creates a new #CtkTreeViewColumn and inserts it into the @tree_view at
12235 * @position. If @position is -1, then the newly created column is inserted at
12236 * the end. The column is initialized with the attributes given. If @tree_view
12237 * has “fixed_height” mode enabled, then the new column will have its sizing
12238 * property set to be CTK_TREE_VIEW_COLUMN_FIXED.
12239 *
12240 * Returns: The number of columns in @tree_view after insertion.
12241 **/
12242gint
12243ctk_tree_view_insert_column_with_attributes (CtkTreeView *tree_view,
12244 gint position,
12245 const gchar *title,
12246 CtkCellRenderer *cell,
12247 ...)
12248{
12249 CtkTreeViewColumn *column;
12250 gchar *attribute;
12251 va_list args;
12252 gint column_id;
12253
12254 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (-1); } } while (
0)
;
12255
12256 column = ctk_tree_view_column_new ();
12257 if (tree_view->priv->fixed_height_mode)
12258 ctk_tree_view_column_set_sizing (column, CTK_TREE_VIEW_COLUMN_FIXED);
12259
12260 ctk_tree_view_column_set_title (column, title);
12261 ctk_tree_view_column_pack_start (column, cell, TRUE(!(0)));
12262
12263 va_start (args, cell)__builtin_va_start(args, cell);
12264
12265 attribute = va_arg (args, gchar *)__builtin_va_arg(args, gchar *);
12266
12267 while (attribute != NULL((void*)0))
12268 {
12269 column_id = va_arg (args, gint)__builtin_va_arg(args, gint);
12270 ctk_tree_view_column_add_attribute (column, cell, attribute, column_id);
12271 attribute = va_arg (args, gchar *)__builtin_va_arg(args, gchar *);
12272 }
12273
12274 va_end (args)__builtin_va_end(args);
12275
12276 return ctk_tree_view_insert_column (tree_view, column, position);
12277}
12278
12279/**
12280 * ctk_tree_view_insert_column_with_data_func:
12281 * @tree_view: a #CtkTreeView
12282 * @position: Position to insert, -1 for append
12283 * @title: column title
12284 * @cell: cell renderer for column
12285 * @func: function to set attributes of cell renderer
12286 * @data: data for @func
12287 * @dnotify: destroy notifier for @data
12288 *
12289 * Convenience function that inserts a new column into the #CtkTreeView
12290 * with the given cell renderer and a #CtkTreeCellDataFunc to set cell renderer
12291 * attributes (normally using data from the model). See also
12292 * ctk_tree_view_column_set_cell_data_func(), ctk_tree_view_column_pack_start().
12293 * If @tree_view has “fixed_height” mode enabled, then the new column will have its
12294 * “sizing” property set to be CTK_TREE_VIEW_COLUMN_FIXED.
12295 *
12296 * Returns: number of columns in the tree view post-insert
12297 **/
12298gint
12299ctk_tree_view_insert_column_with_data_func (CtkTreeView *tree_view,
12300 gint position,
12301 const gchar *title,
12302 CtkCellRenderer *cell,
12303 CtkTreeCellDataFunc func,
12304 gpointer data,
12305 GDestroyNotify dnotify)
12306{
12307 CtkTreeViewColumn *column;
12308
12309 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (-1); } } while (
0)
;
12310
12311 column = ctk_tree_view_column_new ();
12312 if (tree_view->priv->fixed_height_mode)
12313 ctk_tree_view_column_set_sizing (column, CTK_TREE_VIEW_COLUMN_FIXED);
12314
12315 ctk_tree_view_column_set_title (column, title);
12316 ctk_tree_view_column_pack_start (column, cell, TRUE(!(0)));
12317 ctk_tree_view_column_set_cell_data_func (column, cell, func, data, dnotify);
12318
12319 return ctk_tree_view_insert_column (tree_view, column, position);
12320}
12321
12322/**
12323 * ctk_tree_view_get_n_columns:
12324 * @tree_view: a #CtkTreeView
12325 *
12326 * Queries the number of columns in the given @tree_view.
12327 *
12328 * Returns: The number of columns in the @tree_view
12329 *
12330 * Since: 3.4
12331 **/
12332guint
12333ctk_tree_view_get_n_columns (CtkTreeView *tree_view)
12334{
12335 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (0); } } while (0
)
;
12336
12337 return tree_view->priv->n_columns;
12338}
12339
12340/**
12341 * ctk_tree_view_get_column:
12342 * @tree_view: A #CtkTreeView.
12343 * @n: The position of the column, counting from 0.
12344 *
12345 * Gets the #CtkTreeViewColumn at the given position in the #tree_view.
12346 *
12347 * Returns: (nullable) (transfer none): The #CtkTreeViewColumn, or %NULL if the
12348 * position is outside the range of columns.
12349 **/
12350CtkTreeViewColumn *
12351ctk_tree_view_get_column (CtkTreeView *tree_view,
12352 gint n)
12353{
12354 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
12355
12356 if (n < 0 || n >= tree_view->priv->n_columns)
12357 return NULL((void*)0);
12358
12359 if (tree_view->priv->columns == NULL((void*)0))
12360 return NULL((void*)0);
12361
12362 return CTK_TREE_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((g_list_nth (tree_view->priv->columns
, n)->data)), ((ctk_tree_view_column_get_type ()))))))
;
12363}
12364
12365/**
12366 * ctk_tree_view_get_columns:
12367 * @tree_view: A #CtkTreeView
12368 *
12369 * Returns a #GList of all the #CtkTreeViewColumn s currently in @tree_view.
12370 * The returned list must be freed with g_list_free ().
12371 *
12372 * Returns: (element-type CtkTreeViewColumn) (transfer container): A list of #CtkTreeViewColumn s
12373 **/
12374GList *
12375ctk_tree_view_get_columns (CtkTreeView *tree_view)
12376{
12377 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
12378
12379 return g_list_copy (tree_view->priv->columns);
12380}
12381
12382/**
12383 * ctk_tree_view_move_column_after:
12384 * @tree_view: A #CtkTreeView
12385 * @column: The #CtkTreeViewColumn to be moved.
12386 * @base_column: (allow-none): The #CtkTreeViewColumn to be moved relative to, or %NULL.
12387 *
12388 * Moves @column to be after to @base_column. If @base_column is %NULL, then
12389 * @column is placed in the first position.
12390 **/
12391void
12392ctk_tree_view_move_column_after (CtkTreeView *tree_view,
12393 CtkTreeViewColumn *column,
12394 CtkTreeViewColumn *base_column)
12395{
12396 GList *column_list_el, *base_el = NULL((void*)0);
12397
12398 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12399
12400 column_list_el = g_list_find (tree_view->priv->columns, column);
12401 g_return_if_fail (column_list_el != NULL)do { if ((column_list_el != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "column_list_el != NULL"
); return; } } while (0)
;
12402
12403 if (base_column)
12404 {
12405 base_el = g_list_find (tree_view->priv->columns, base_column);
12406 g_return_if_fail (base_el != NULL)do { if ((base_el != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "base_el != NULL"); return
; } } while (0)
;
12407 }
12408
12409 if (column_list_el->prev == base_el)
12410 return;
12411
12412 tree_view->priv->columns = g_list_remove_link (tree_view->priv->columns, column_list_el);
12413 if (base_el == NULL((void*)0))
12414 {
12415 column_list_el->prev = NULL((void*)0);
12416 column_list_el->next = tree_view->priv->columns;
12417 if (column_list_el->next)
12418 column_list_el->next->prev = column_list_el;
12419 tree_view->priv->columns = column_list_el;
12420 }
12421 else
12422 {
12423 column_list_el->prev = base_el;
12424 column_list_el->next = base_el->next;
12425 if (column_list_el->next)
12426 column_list_el->next->prev = column_list_el;
12427 base_el->next = column_list_el;
12428 }
12429
12430 ctk_tree_view_update_button_position (tree_view, column);
12431
12432 if (ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
12433 {
12434 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
12435 ctk_tree_view_size_allocate_columns (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, NULL((void*)0));
12436 }
12437
12438 _ctk_tree_view_accessible_reorder_column (tree_view, column);
12439
12440 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
12441}
12442
12443/**
12444 * ctk_tree_view_set_expander_column:
12445 * @tree_view: A #CtkTreeView
12446 * @column: (nullable): %NULL, or the column to draw the expander arrow at.
12447 *
12448 * Sets the column to draw the expander arrow at. It must be in @tree_view.
12449 * If @column is %NULL, then the expander arrow is always at the first
12450 * visible column.
12451 *
12452 * If you do not want expander arrow to appear in your tree, set the
12453 * expander column to a hidden column.
12454 **/
12455void
12456ctk_tree_view_set_expander_column (CtkTreeView *tree_view,
12457 CtkTreeViewColumn *column)
12458{
12459 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12460 g_return_if_fail (column == NULL || CTK_IS_TREE_VIEW_COLUMN (column))do { if ((column == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((column)); GType __t = ((ctk_tree_view_column_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "column == NULL || CTK_IS_TREE_VIEW_COLUMN (column)"
); return; } } while (0)
;
12461 g_return_if_fail (column == NULL || ctk_tree_view_column_get_tree_view (column) == CTK_WIDGET (tree_view))do { if ((column == ((void*)0) || ctk_tree_view_column_get_tree_view
(column) == ((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((tree_view)), ((ctk_widget_get_type ())))
))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "column == NULL || ctk_tree_view_column_get_tree_view (column) == CTK_WIDGET (tree_view)"
); return; } } while (0)
;
12462
12463 if (tree_view->priv->expander_column != column)
12464 {
12465 tree_view->priv->expander_column = column;
12466 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_EXPANDER_COLUMN]);
12467 }
12468}
12469
12470/**
12471 * ctk_tree_view_get_expander_column:
12472 * @tree_view: A #CtkTreeView
12473 *
12474 * Returns the column that is the current expander column.
12475 * This column has the expander arrow drawn next to it.
12476 *
12477 * Returns: (transfer none): The expander column.
12478 **/
12479CtkTreeViewColumn *
12480ctk_tree_view_get_expander_column (CtkTreeView *tree_view)
12481{
12482 GList *list;
12483
12484 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
12485
12486 for (list = tree_view->priv->columns; list; list = list->next)
12487 if (ctk_tree_view_is_expander_column (tree_view, CTK_TREE_VIEW_COLUMN (list->data)((((CtkTreeViewColumn*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((list->data)), ((ctk_tree_view_column_get_type
()))))))
))
12488 return (CtkTreeViewColumn *) list->data;
12489 return NULL((void*)0);
12490}
12491
12492
12493/**
12494 * ctk_tree_view_set_column_drag_function:
12495 * @tree_view: A #CtkTreeView.
12496 * @func: (allow-none): A function to determine which columns are reorderable, or %NULL.
12497 * @user_data: (allow-none): User data to be passed to @func, or %NULL
12498 * @destroy: (allow-none): Destroy notifier for @user_data, or %NULL
12499 *
12500 * Sets a user function for determining where a column may be dropped when
12501 * dragged. This function is called on every column pair in turn at the
12502 * beginning of a column drag to determine where a drop can take place. The
12503 * arguments passed to @func are: the @tree_view, the #CtkTreeViewColumn being
12504 * dragged, the two #CtkTreeViewColumn s determining the drop spot, and
12505 * @user_data. If either of the #CtkTreeViewColumn arguments for the drop spot
12506 * are %NULL, then they indicate an edge. If @func is set to be %NULL, then
12507 * @tree_view reverts to the default behavior of allowing all columns to be
12508 * dropped everywhere.
12509 **/
12510void
12511ctk_tree_view_set_column_drag_function (CtkTreeView *tree_view,
12512 CtkTreeViewColumnDropFunc func,
12513 gpointer user_data,
12514 GDestroyNotify destroy)
12515{
12516 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12517
12518 if (tree_view->priv->column_drop_func_data_destroy)
12519 tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
12520
12521 tree_view->priv->column_drop_func = func;
12522 tree_view->priv->column_drop_func_data = user_data;
12523 tree_view->priv->column_drop_func_data_destroy = destroy;
12524}
12525
12526/**
12527 * ctk_tree_view_scroll_to_point:
12528 * @tree_view: a #CtkTreeView
12529 * @tree_x: X coordinate of new top-left pixel of visible area, or -1
12530 * @tree_y: Y coordinate of new top-left pixel of visible area, or -1
12531 *
12532 * Scrolls the tree view such that the top-left corner of the visible
12533 * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
12534 * in tree coordinates. The @tree_view must be realized before
12535 * this function is called. If it isn't, you probably want to be
12536 * using ctk_tree_view_scroll_to_cell().
12537 *
12538 * If either @tree_x or @tree_y are -1, then that direction isn’t scrolled.
12539 **/
12540void
12541ctk_tree_view_scroll_to_point (CtkTreeView *tree_view,
12542 gint tree_x,
12543 gint tree_y)
12544{
12545 CtkAdjustment *hadj;
12546 CtkAdjustment *vadj;
12547
12548 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12549 g_return_if_fail (ctk_widget_get_realized (CTK_WIDGET (tree_view)))do { if ((ctk_widget_get_realized (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((tree_view)), ((ctk_widget_get_type ())))
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "ctk_widget_get_realized (CTK_WIDGET (tree_view))"
); return; } } while (0)
;
12550
12551 hadj = tree_view->priv->hadjustment;
12552 vadj = tree_view->priv->vadjustment;
12553
12554 if (tree_x != -1)
12555 ctk_adjustment_animate_to_value (hadj, tree_x);
12556 if (tree_y != -1)
12557 ctk_adjustment_animate_to_value (vadj, tree_y);
12558}
12559
12560/**
12561 * ctk_tree_view_scroll_to_cell:
12562 * @tree_view: A #CtkTreeView.
12563 * @path: (allow-none): The path of the row to move to, or %NULL.
12564 * @column: (allow-none): The #CtkTreeViewColumn to move horizontally to, or %NULL.
12565 * @use_align: whether to use alignment arguments, or %FALSE.
12566 * @row_align: The vertical alignment of the row specified by @path.
12567 * @col_align: The horizontal alignment of the column specified by @column.
12568 *
12569 * Moves the alignments of @tree_view to the position specified by @column and
12570 * @path. If @column is %NULL, then no horizontal scrolling occurs. Likewise,
12571 * if @path is %NULL no vertical scrolling occurs. At a minimum, one of @column
12572 * or @path need to be non-%NULL. @row_align determines where the row is
12573 * placed, and @col_align determines where @column is placed. Both are expected
12574 * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
12575 * right/bottom alignment, 0.5 means center.
12576 *
12577 * If @use_align is %FALSE, then the alignment arguments are ignored, and the
12578 * tree does the minimum amount of work to scroll the cell onto the screen.
12579 * This means that the cell will be scrolled to the edge closest to its current
12580 * position. If the cell is currently visible on the screen, nothing is done.
12581 *
12582 * This function only works if the model is set, and @path is a valid row on the
12583 * model. If the model changes before the @tree_view is realized, the centered
12584 * path will be modified to reflect this change.
12585 **/
12586void
12587ctk_tree_view_scroll_to_cell (CtkTreeView *tree_view,
12588 CtkTreePath *path,
12589 CtkTreeViewColumn *column,
12590 gboolean use_align,
12591 gfloat row_align,
12592 gfloat col_align)
12593{
12594 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12595 g_return_if_fail (tree_view->priv->model != NULL)do { if ((tree_view->priv->model != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "tree_view->priv->model != NULL"); return; } } while
(0)
;
12596 g_return_if_fail (tree_view->priv->tree != NULL)do { if ((tree_view->priv->tree != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "tree_view->priv->tree != NULL"); return; } } while (
0)
;
12597 g_return_if_fail (row_align >= 0.0 && row_align <= 1.0)do { if ((row_align >= 0.0 && row_align <= 1.0)
) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "row_align >= 0.0 && row_align <= 1.0"
); return; } } while (0)
;
12598 g_return_if_fail (col_align >= 0.0 && col_align <= 1.0)do { if ((col_align >= 0.0 && col_align <= 1.0)
) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "col_align >= 0.0 && col_align <= 1.0"
); return; } } while (0)
;
12599 g_return_if_fail (path != NULL || column != NULL)do { if ((path != ((void*)0) || column != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "path != NULL || column != NULL"); return; } } while (0)
;
12600
12601 row_align = CLAMP (row_align, 0.0, 1.0)(((row_align) > (1.0)) ? (1.0) : (((row_align) < (0.0))
? (0.0) : (row_align)))
;
12602 col_align = CLAMP (col_align, 0.0, 1.0)(((col_align) > (1.0)) ? (1.0) : (((col_align) < (0.0))
? (0.0) : (col_align)))
;
12603
12604
12605 /* Note: Despite the benefits that come from having one code path for the
12606 * scrolling code, we short-circuit validate_visible_area's immplementation as
12607 * it is much slower than just going to the point.
12608 */
12609 if (!ctk_widget_get_visible (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) ||
12610 !ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) ||
12611 _ctk_widget_get_alloc_needed (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) ||
12612 CTK_RBNODE_FLAG_SET (tree_view->priv->tree->root, CTK_RBNODE_DESCENDANTS_INVALID)(tree_view->priv->tree->root?(((tree_view->priv->
tree->root->flags&CTK_RBNODE_DESCENDANTS_INVALID)==
CTK_RBNODE_DESCENDANTS_INVALID)?(!(0)):(0)):(0))
)
12613 {
12614 if (tree_view->priv->scroll_to_path)
12615 ctk_tree_row_reference_free (tree_view->priv->scroll_to_path);
12616
12617 tree_view->priv->scroll_to_path = NULL((void*)0);
12618 tree_view->priv->scroll_to_column = NULL((void*)0);
12619
12620 if (path)
12621 tree_view->priv->scroll_to_path = ctk_tree_row_reference_new_proxy (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view->priv->model, path);
12622 if (column)
12623 tree_view->priv->scroll_to_column = column;
12624 tree_view->priv->scroll_to_use_align = use_align;
12625 tree_view->priv->scroll_to_row_align = row_align;
12626 tree_view->priv->scroll_to_col_align = col_align;
12627
12628 install_presize_handler (tree_view);
12629 }
12630 else
12631 {
12632 CdkRectangle cell_rect;
12633 CdkRectangle vis_rect;
12634 gint dest_x, dest_y;
12635
12636 ctk_tree_view_get_background_area (tree_view, path, column, &cell_rect);
12637 ctk_tree_view_get_visible_rect (tree_view, &vis_rect);
12638
12639 cell_rect.y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, cell_rect.y)((cell_rect.y) + tree_view->priv->dy);
12640
12641 dest_x = vis_rect.x;
12642 dest_y = vis_rect.y;
12643
12644 if (column)
12645 {
12646 if (use_align)
12647 {
12648 dest_x = cell_rect.x - ((vis_rect.width - cell_rect.width) * col_align);
12649 }
12650 else
12651 {
12652 if (cell_rect.x < vis_rect.x)
12653 dest_x = cell_rect.x;
12654 if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
12655 dest_x = cell_rect.x + cell_rect.width - vis_rect.width;
12656 }
12657 }
12658
12659 if (path)
12660 {
12661 if (use_align)
12662 {
12663 dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * row_align);
12664 dest_y = MAX (dest_y, 0)(((dest_y) > (0)) ? (dest_y) : (0));
12665 }
12666 else
12667 {
12668 if (cell_rect.y < vis_rect.y)
12669 dest_y = cell_rect.y;
12670 if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
12671 dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
12672 }
12673 }
12674
12675 ctk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
12676 }
12677}
12678
12679/**
12680 * ctk_tree_view_row_activated:
12681 * @tree_view: A #CtkTreeView
12682 * @path: The #CtkTreePath to be activated.
12683 * @column: The #CtkTreeViewColumn to be activated.
12684 *
12685 * Activates the cell determined by @path and @column.
12686 **/
12687void
12688ctk_tree_view_row_activated (CtkTreeView *tree_view,
12689 CtkTreePath *path,
12690 CtkTreeViewColumn *column)
12691{
12692 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12693
12694 g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
12695}
12696
12697
12698static void
12699ctk_tree_view_expand_all_emission_helper (CtkRBTree *tree,
12700 CtkRBNode *node,
12701 gpointer data)
12702{
12703 CtkTreeView *tree_view = data;
12704
12705 if ((node->flags & CTK_RBNODE_IS_PARENT) == CTK_RBNODE_IS_PARENT &&
12706 node->children)
12707 {
12708 CtkTreePath *path;
12709 CtkTreeIter iter;
12710
12711 path = _ctk_tree_path_new_from_rbtree (tree, node);
12712 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
12713
12714 g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
12715
12716 ctk_tree_path_free (path);
12717 }
12718
12719 if (node->children)
12720 _ctk_rbtree_traverse (node->children,
12721 node->children->root,
12722 G_PRE_ORDER,
12723 ctk_tree_view_expand_all_emission_helper,
12724 tree_view);
12725}
12726
12727/**
12728 * ctk_tree_view_expand_all:
12729 * @tree_view: A #CtkTreeView.
12730 *
12731 * Recursively expands all nodes in the @tree_view.
12732 **/
12733void
12734ctk_tree_view_expand_all (CtkTreeView *tree_view)
12735{
12736 CtkTreePath *path;
12737 CtkRBTree *tree;
12738 CtkRBNode *node;
12739
12740 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12741
12742 if (tree_view->priv->tree == NULL((void*)0))
12743 return;
12744
12745 path = ctk_tree_path_new_first ();
12746 _ctk_tree_view_find_node (tree_view, path, &tree, &node);
12747
12748 while (node)
12749 {
12750 ctk_tree_view_real_expand_row (tree_view, path, tree, node, TRUE(!(0)), FALSE(0));
12751 node = _ctk_rbtree_next (tree, node);
12752 ctk_tree_path_next (path);
12753 }
12754
12755 ctk_tree_path_free (path);
12756}
12757
12758/**
12759 * ctk_tree_view_collapse_all:
12760 * @tree_view: A #CtkTreeView.
12761 *
12762 * Recursively collapses all visible, expanded nodes in @tree_view.
12763 **/
12764void
12765ctk_tree_view_collapse_all (CtkTreeView *tree_view)
12766{
12767 CtkRBTree *tree;
12768 CtkRBNode *node;
12769 CtkTreePath *path;
12770 gint *indices;
12771
12772 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12773
12774 if (tree_view->priv->tree == NULL((void*)0))
12775 return;
12776
12777 path = ctk_tree_path_new ();
12778 ctk_tree_path_down (path);
12779 indices = ctk_tree_path_get_indices (path);
12780
12781 tree = tree_view->priv->tree;
12782 node = _ctk_rbtree_first (tree);
12783
12784 while (node)
12785 {
12786 if (node->children)
12787 ctk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE(0));
12788 indices[0]++;
12789 node = _ctk_rbtree_next (tree, node);
12790 }
12791
12792 ctk_tree_path_free (path);
12793}
12794
12795/**
12796 * ctk_tree_view_expand_to_path:
12797 * @tree_view: A #CtkTreeView.
12798 * @path: path to a row.
12799 *
12800 * Expands the row at @path. This will also expand all parent rows of
12801 * @path as necessary.
12802 *
12803 * Since: 2.2
12804 **/
12805void
12806ctk_tree_view_expand_to_path (CtkTreeView *tree_view,
12807 CtkTreePath *path)
12808{
12809 gint i, depth;
12810 gint *indices;
12811 CtkTreePath *tmp;
12812
12813 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
12814 g_return_if_fail (path != NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return;
} } while (0)
;
12815
12816 depth = ctk_tree_path_get_depth (path);
12817 indices = ctk_tree_path_get_indices (path);
12818
12819 tmp = ctk_tree_path_new ();
12820 g_return_if_fail (tmp != NULL)do { if ((tmp != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "tmp != NULL"); return; }
} while (0)
;
12821
12822 for (i = 0; i < depth; i++)
12823 {
12824 ctk_tree_path_append_index (tmp, indices[i]);
12825 ctk_tree_view_expand_row (tree_view, tmp, FALSE(0));
12826 }
12827
12828 ctk_tree_path_free (tmp);
12829}
12830
12831/* FIXME the bool return values for expand_row and collapse_row are
12832 * not analagous; they should be TRUE if the row had children and
12833 * was not already in the requested state.
12834 */
12835
12836
12837static gboolean
12838ctk_tree_view_real_expand_row (CtkTreeView *tree_view,
12839 CtkTreePath *path,
12840 CtkRBTree *tree,
12841 CtkRBNode *node,
12842 gboolean open_all,
12843 gboolean animate)
12844{
12845 CtkTreeIter iter;
12846 CtkTreeIter temp;
12847 gboolean expand;
12848
12849 if (animate)
12850 animate = ctk_settings_get_enable_animations (ctk_widget_get_settings (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
));
12851
12852 remove_auto_expand_timeout (tree_view);
12853
12854 if (node->children && !open_all)
12855 return FALSE(0);
12856
12857 if (! CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
)
12858 return FALSE(0);
12859
12860 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
12861 if (! ctk_tree_model_iter_has_child (tree_view->priv->model, &iter))
12862 return FALSE(0);
12863
12864
12865 if (node->children && open_all)
12866 {
12867 gboolean retval = FALSE(0);
12868 CtkTreePath *tmp_path = ctk_tree_path_copy (path);
12869
12870 ctk_tree_path_append_index (tmp_path, 0);
12871 tree = node->children;
12872 node = _ctk_rbtree_first (tree);
12873 /* try to expand the children */
12874 do
12875 {
12876 gboolean t;
12877 t = ctk_tree_view_real_expand_row (tree_view, tmp_path, tree, node,
12878 TRUE(!(0)), animate);
12879 if (t)
12880 retval = TRUE(!(0));
12881
12882 ctk_tree_path_next (tmp_path);
12883 node = _ctk_rbtree_next (tree, node);
12884 }
12885 while (node != NULL((void*)0));
12886
12887 ctk_tree_path_free (tmp_path);
12888
12889 return retval;
12890 }
12891
12892 g_signal_emit (tree_view, tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
12893
12894 if (!ctk_tree_model_iter_has_child (tree_view->priv->model, &iter))
12895 return FALSE(0);
12896
12897 if (expand)
12898 return FALSE(0);
12899
12900 node->children = _ctk_rbtree_new ();
12901 node->children->parent_tree = tree;
12902 node->children->parent_node = node;
12903
12904 ctk_tree_model_iter_children (tree_view->priv->model, &temp, &iter);
12905
12906 ctk_tree_view_build_tree (tree_view,
12907 node->children,
12908 &temp,
12909 ctk_tree_path_get_depth (path) + 1,
12910 open_all);
12911
12912 _ctk_tree_view_accessible_add (tree_view, node->children, NULL((void*)0));
12913 _ctk_tree_view_accessible_add_state (tree_view,
12914 tree, node,
12915 CTK_CELL_RENDERER_EXPANDED);
12916
12917 install_presize_handler (tree_view);
12918
12919 g_signal_emit (tree_view, tree_view_signals[ROW_EXPANDED], 0, &iter, path);
12920 if (open_all && node->children)
12921 {
12922 _ctk_rbtree_traverse (node->children,
12923 node->children->root,
12924 G_PRE_ORDER,
12925 ctk_tree_view_expand_all_emission_helper,
12926 tree_view);
12927 }
12928 return TRUE(!(0));
12929}
12930
12931
12932/**
12933 * ctk_tree_view_expand_row:
12934 * @tree_view: a #CtkTreeView
12935 * @path: path to a row
12936 * @open_all: whether to recursively expand, or just expand immediate children
12937 *
12938 * Opens the row so its children are visible.
12939 *
12940 * Returns: %TRUE if the row existed and had children
12941 **/
12942gboolean
12943ctk_tree_view_expand_row (CtkTreeView *tree_view,
12944 CtkTreePath *path,
12945 gboolean open_all)
12946{
12947 CtkRBTree *tree;
12948 CtkRBNode *node;
12949
12950 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
12951 g_return_val_if_fail (tree_view->priv->model != NULL, FALSE)do { if ((tree_view->priv->model != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "tree_view->priv->model != NULL"); return ((0)); } }
while (0)
;
12952 g_return_val_if_fail (path != NULL, FALSE)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
(0)); } } while (0)
;
12953
12954 if (_ctk_tree_view_find_node (tree_view,
12955 path,
12956 &tree,
12957 &node))
12958 return FALSE(0);
12959
12960 if (tree != NULL((void*)0))
12961 return ctk_tree_view_real_expand_row (tree_view, path, tree, node, open_all, FALSE(0));
12962 else
12963 return FALSE(0);
12964}
12965
12966static gboolean
12967ctk_tree_view_real_collapse_row (CtkTreeView *tree_view,
12968 CtkTreePath *path,
12969 CtkRBTree *tree,
12970 CtkRBNode *node,
12971 gboolean animate)
12972{
12973 CtkTreeIter iter;
12974 CtkTreeIter children;
12975 gboolean collapse;
12976 GList *list;
12977 gboolean selection_changed, cursor_changed;
12978
12979 if (animate)
12980 animate = ctk_settings_get_enable_animations (ctk_widget_get_settings (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
));
12981
12982 remove_auto_expand_timeout (tree_view);
12983
12984 if (node->children == NULL((void*)0))
12985 return FALSE(0);
12986 ctk_tree_model_get_iter (tree_view->priv->model, &iter, path);
12987
12988 g_signal_emit (tree_view, tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
12989
12990 if (collapse)
12991 return FALSE(0);
12992
12993 /* if the prelighted node is a child of us, we want to unprelight it. We have
12994 * a chance to prelight the correct node below */
12995
12996 if (tree_view->priv->prelight_tree)
12997 {
12998 CtkRBTree *parent_tree;
12999 CtkRBNode *parent_node;
13000
13001 parent_tree = tree_view->priv->prelight_tree->parent_tree;
13002 parent_node = tree_view->priv->prelight_tree->parent_node;
13003 while (parent_tree)
13004 {
13005 if (parent_tree == tree && parent_node == node)
13006 {
13007 ensure_unprelighted (tree_view);
13008 break;
13009 }
13010 parent_node = parent_tree->parent_node;
13011 parent_tree = parent_tree->parent_tree;
13012 }
13013 }
13014
13015 TREE_VIEW_INTERNAL_ASSERT (ctk_tree_model_iter_children (tree_view->priv->model, &children, &iter), FALSE)do{ if (!(ctk_tree_model_iter_children (tree_view->priv->
model, &children, &iter))) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL
, "%s (%s): assertion `%s' failed.\n" "There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "13015", ((const char
*) (__func__)), "ctk_tree_model_iter_children (tree_view->priv->model, &children, &iter)"
); return (0); }; }while (0)
;
13016
13017 for (list = tree_view->priv->columns; list; list = list->next)
13018 {
13019 CtkTreeViewColumn *column = list->data;
13020
13021 if (ctk_tree_view_column_get_visible (column) == FALSE(0))
13022 continue;
13023 if (ctk_tree_view_column_get_sizing (column) == CTK_TREE_VIEW_COLUMN_AUTOSIZE)
13024 _ctk_tree_view_column_cell_set_dirty (column, TRUE(!(0)));
13025 }
13026
13027 if (tree_view->priv->destroy_count_func)
13028 {
13029 CtkTreePath *child_path;
13030 gint child_count = 0;
13031 child_path = ctk_tree_path_copy (path);
13032 ctk_tree_path_down (child_path);
13033 if (node->children)
13034 _ctk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
13035 tree_view->priv->destroy_count_func (tree_view, child_path, child_count, tree_view->priv->destroy_count_data);
13036 ctk_tree_path_free (child_path);
13037 }
13038
13039 if (tree_view->priv->cursor_node)
13040 {
13041 cursor_changed = (node->children == tree_view->priv->cursor_tree)
13042 || _ctk_rbtree_contains (node->children, tree_view->priv->cursor_tree);
13043 }
13044 else
13045 cursor_changed = FALSE(0);
13046
13047 if (ctk_tree_row_reference_valid (tree_view->priv->anchor))
13048 {
13049 CtkTreePath *anchor_path = ctk_tree_row_reference_get_path (tree_view->priv->anchor);
13050 if (ctk_tree_path_is_ancestor (path, anchor_path))
13051 {
13052 ctk_tree_row_reference_free (tree_view->priv->anchor);
13053 tree_view->priv->anchor = NULL((void*)0);
13054 }
13055 ctk_tree_path_free (anchor_path);
13056 }
13057
13058 selection_changed = ctk_tree_view_unref_and_check_selection_tree (tree_view, node->children);
13059
13060 /* Stop a pending double click */
13061 ctk_event_controller_reset (CTK_EVENT_CONTROLLER (tree_view->priv->multipress_gesture)((((CtkEventController*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_view->priv->multipress_gesture)
), ((ctk_event_controller_get_type ()))))))
);
13062
13063 _ctk_tree_view_accessible_remove (tree_view, node->children, NULL((void*)0));
13064 _ctk_tree_view_accessible_remove_state (tree_view,
13065 tree, node,
13066 CTK_CELL_RENDERER_EXPANDED);
13067
13068 _ctk_rbtree_remove (node->children);
13069
13070 if (cursor_changed)
13071 ctk_tree_view_real_set_cursor (tree_view, path, CLEAR_AND_SELECT | CURSOR_INVALID);
13072 if (selection_changed)
13073 g_signal_emit_by_name (tree_view->priv->selection, "changed");
13074
13075 if (ctk_widget_get_mapped (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
13076 {
13077 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
13078 }
13079
13080 g_signal_emit (tree_view, tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
13081
13082 if (ctk_widget_get_mapped (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
13083 update_prelight (tree_view,
13084 tree_view->priv->event_last_x,
13085 tree_view->priv->event_last_y);
13086
13087 return TRUE(!(0));
13088}
13089
13090/**
13091 * ctk_tree_view_collapse_row:
13092 * @tree_view: a #CtkTreeView
13093 * @path: path to a row in the @tree_view
13094 *
13095 * Collapses a row (hides its child rows, if they exist).
13096 *
13097 * Returns: %TRUE if the row was collapsed.
13098 **/
13099gboolean
13100ctk_tree_view_collapse_row (CtkTreeView *tree_view,
13101 CtkTreePath *path)
13102{
13103 CtkRBTree *tree;
13104 CtkRBNode *node;
13105
13106 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
13107 g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE)do { if ((tree_view->priv->tree != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "tree_view->priv->tree != NULL"); return ((0)); } } while
(0)
;
13108 g_return_val_if_fail (path != NULL, FALSE)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
(0)); } } while (0)
;
13109
13110 if (_ctk_tree_view_find_node (tree_view,
13111 path,
13112 &tree,
13113 &node))
13114 return FALSE(0);
13115
13116 if (tree == NULL((void*)0) || node->children == NULL((void*)0))
13117 return FALSE(0);
13118
13119 return ctk_tree_view_real_collapse_row (tree_view, path, tree, node, FALSE(0));
13120}
13121
13122static void
13123ctk_tree_view_map_expanded_rows_helper (CtkTreeView *tree_view,
13124 CtkRBTree *tree,
13125 CtkTreePath *path,
13126 CtkTreeViewMappingFunc func,
13127 gpointer user_data)
13128{
13129 CtkRBNode *node;
13130
13131 if (tree == NULL((void*)0) || tree->root == NULL((void*)0))
13132 return;
13133
13134 node = _ctk_rbtree_first (tree);
13135
13136 while (node)
13137 {
13138 if (node->children)
13139 {
13140 (* func) (tree_view, path, user_data);
13141 ctk_tree_path_down (path);
13142 ctk_tree_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
13143 ctk_tree_path_up (path);
13144 }
13145 ctk_tree_path_next (path);
13146 node = _ctk_rbtree_next (tree, node);
13147 }
13148}
13149
13150/**
13151 * ctk_tree_view_map_expanded_rows:
13152 * @tree_view: A #CtkTreeView
13153 * @func: (scope call): A function to be called
13154 * @data: User data to be passed to the function.
13155 *
13156 * Calls @func on all expanded rows.
13157 **/
13158void
13159ctk_tree_view_map_expanded_rows (CtkTreeView *tree_view,
13160 CtkTreeViewMappingFunc func,
13161 gpointer user_data)
13162{
13163 CtkTreePath *path;
13164
13165 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13166 g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "func != NULL"); return;
} } while (0)
;
13167
13168 path = ctk_tree_path_new_first ();
13169
13170 ctk_tree_view_map_expanded_rows_helper (tree_view,
13171 tree_view->priv->tree,
13172 path, func, user_data);
13173
13174 ctk_tree_path_free (path);
13175}
13176
13177/**
13178 * ctk_tree_view_row_expanded:
13179 * @tree_view: A #CtkTreeView.
13180 * @path: A #CtkTreePath to test expansion state.
13181 *
13182 * Returns %TRUE if the node pointed to by @path is expanded in @tree_view.
13183 *
13184 * Returns: %TRUE if #path is expanded.
13185 **/
13186gboolean
13187ctk_tree_view_row_expanded (CtkTreeView *tree_view,
13188 CtkTreePath *path)
13189{
13190 CtkRBTree *tree;
13191 CtkRBNode *node;
13192
13193 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
13194 g_return_val_if_fail (path != NULL, FALSE)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
(0)); } } while (0)
;
13195
13196 _ctk_tree_view_find_node (tree_view, path, &tree, &node);
13197
13198 if (node == NULL((void*)0))
13199 return FALSE(0);
13200
13201 return (node->children != NULL((void*)0));
13202}
13203
13204/**
13205 * ctk_tree_view_get_reorderable:
13206 * @tree_view: a #CtkTreeView
13207 *
13208 * Retrieves whether the user can reorder the tree via drag-and-drop. See
13209 * ctk_tree_view_set_reorderable().
13210 *
13211 * Returns: %TRUE if the tree can be reordered.
13212 **/
13213gboolean
13214ctk_tree_view_get_reorderable (CtkTreeView *tree_view)
13215{
13216 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
13217
13218 return tree_view->priv->reorderable;
13219}
13220
13221/**
13222 * ctk_tree_view_set_reorderable:
13223 * @tree_view: A #CtkTreeView.
13224 * @reorderable: %TRUE, if the tree can be reordered.
13225 *
13226 * This function is a convenience function to allow you to reorder
13227 * models that support the #CtkTreeDragSourceIface and the
13228 * #CtkTreeDragDestIface. Both #CtkTreeStore and #CtkListStore support
13229 * these. If @reorderable is %TRUE, then the user can reorder the
13230 * model by dragging and dropping rows. The developer can listen to
13231 * these changes by connecting to the model’s #CtkTreeModel::row-inserted
13232 * and #CtkTreeModel::row-deleted signals. The reordering is implemented
13233 * by setting up the tree view as a drag source and destination.
13234 * Therefore, drag and drop can not be used in a reorderable view for any
13235 * other purpose.
13236 *
13237 * This function does not give you any degree of control over the order -- any
13238 * reordering is allowed. If more control is needed, you should probably
13239 * handle drag and drop manually.
13240 **/
13241void
13242ctk_tree_view_set_reorderable (CtkTreeView *tree_view,
13243 gboolean reorderable)
13244{
13245 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13246
13247 reorderable = reorderable != FALSE(0);
13248
13249 if (tree_view->priv->reorderable == reorderable)
13250 return;
13251
13252 if (reorderable)
13253 {
13254 const CtkTargetEntry row_targets[] = {
13255 { "CTK_TREE_MODEL_ROW", CTK_TARGET_SAME_WIDGET, 0 }
13256 };
13257
13258 ctk_tree_view_enable_model_drag_source (tree_view,
13259 CDK_BUTTON1_MASK,
13260 row_targets,
13261 G_N_ELEMENTS (row_targets)(sizeof (row_targets) / sizeof ((row_targets)[0])),
13262 CDK_ACTION_MOVE);
13263 ctk_tree_view_enable_model_drag_dest (tree_view,
13264 row_targets,
13265 G_N_ELEMENTS (row_targets)(sizeof (row_targets) / sizeof ((row_targets)[0])),
13266 CDK_ACTION_MOVE);
13267 }
13268 else
13269 {
13270 ctk_tree_view_unset_rows_drag_source (tree_view);
13271 ctk_tree_view_unset_rows_drag_dest (tree_view);
13272 }
13273
13274 tree_view->priv->reorderable = reorderable;
13275
13276 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_REORDERABLE]);
13277}
13278
13279static void
13280ctk_tree_view_real_set_cursor (CtkTreeView *tree_view,
13281 CtkTreePath *path,
13282 SetCursorFlags flags)
13283{
13284 if (!(flags & CURSOR_INVALID) && tree_view->priv->cursor_node)
13285 {
13286 _ctk_tree_view_accessible_remove_state (tree_view,
13287 tree_view->priv->cursor_tree,
13288 tree_view->priv->cursor_node,
13289 CTK_CELL_RENDERER_FOCUSED);
13290 _ctk_tree_view_queue_draw_node (tree_view,
13291 tree_view->priv->cursor_tree,
13292 tree_view->priv->cursor_node,
13293 NULL((void*)0));
13294 }
13295
13296 /* One cannot set the cursor on a separator. Also, if
13297 * _ctk_tree_view_find_node returns TRUE, it ran out of tree
13298 * before finding the tree and node belonging to path. The
13299 * path maps to a non-existing path and we will silently bail out.
13300 * We unset tree and node to avoid further processing.
13301 */
13302 if (path == NULL((void*)0) ||
13303 row_is_separator (tree_view, NULL((void*)0), path)
13304 || _ctk_tree_view_find_node (tree_view,
13305 path,
13306 &tree_view->priv->cursor_tree,
13307 &tree_view->priv->cursor_node))
13308 {
13309 tree_view->priv->cursor_tree = NULL((void*)0);
13310 tree_view->priv->cursor_node = NULL((void*)0);
13311 }
13312
13313 if (tree_view->priv->cursor_node != NULL((void*)0))
13314 {
13315 CtkRBTree *new_tree = NULL((void*)0);
13316 CtkRBNode *new_node = NULL((void*)0);
13317
13318 if ((flags & CLEAR_AND_SELECT) && !tree_view->priv->modify_selection_pressed)
13319 {
13320 CtkTreeSelectMode mode = 0;
13321
13322 if (tree_view->priv->extend_selection_pressed)
13323 mode |= CTK_TREE_SELECT_MODE_EXTEND;
13324
13325 _ctk_tree_selection_internal_select_node (tree_view->priv->selection,
13326 tree_view->priv->cursor_node,
13327 tree_view->priv->cursor_tree,
13328 path,
13329 mode,
13330 FALSE(0));
13331 }
13332
13333 /* We have to re-find tree and node here again, somebody might have
13334 * cleared the node or the whole tree in the CtkTreeSelection::changed
13335 * callback. If the nodes differ we bail out here.
13336 */
13337 _ctk_tree_view_find_node (tree_view, path, &new_tree, &new_node);
13338
13339 if (tree_view->priv->cursor_node == NULL((void*)0) ||
13340 tree_view->priv->cursor_node != new_node)
13341 return;
13342
13343 if (flags & CLAMP_NODE)
13344 {
13345 ctk_tree_view_clamp_node_visible (tree_view,
13346 tree_view->priv->cursor_tree,
13347 tree_view->priv->cursor_node);
13348 _ctk_tree_view_queue_draw_node (tree_view,
13349 tree_view->priv->cursor_tree,
13350 tree_view->priv->cursor_node,
13351 NULL((void*)0));
13352 }
13353
13354 _ctk_tree_view_accessible_add_state (tree_view,
13355 tree_view->priv->cursor_tree,
13356 tree_view->priv->cursor_node,
13357 CTK_CELL_RENDERER_FOCUSED);
13358 }
13359
13360 if (!ctk_widget_in_destruction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
13361 g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
13362}
13363
13364/**
13365 * ctk_tree_view_get_cursor:
13366 * @tree_view: A #CtkTreeView
13367 * @path: (out) (transfer full) (optional) (nullable): A pointer to be
13368 * filled with the current cursor path, or %NULL
13369 * @focus_column: (out) (transfer none) (optional) (nullable): A
13370 * pointer to be filled with the current focus column, or %NULL
13371 *
13372 * Fills in @path and @focus_column with the current path and focus column. If
13373 * the cursor isn’t currently set, then *@path will be %NULL. If no column
13374 * currently has focus, then *@focus_column will be %NULL.
13375 *
13376 * The returned #CtkTreePath must be freed with ctk_tree_path_free() when
13377 * you are done with it.
13378 **/
13379void
13380ctk_tree_view_get_cursor (CtkTreeView *tree_view,
13381 CtkTreePath **path,
13382 CtkTreeViewColumn **focus_column)
13383{
13384 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13385
13386 if (path)
13387 {
13388 if (tree_view->priv->cursor_node)
13389 *path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
13390 tree_view->priv->cursor_node);
13391 else
13392 *path = NULL((void*)0);
13393 }
13394
13395 if (focus_column)
13396 {
13397 *focus_column = tree_view->priv->focus_column;
13398 }
13399}
13400
13401/**
13402 * ctk_tree_view_set_cursor:
13403 * @tree_view: A #CtkTreeView
13404 * @path: A #CtkTreePath
13405 * @focus_column: (allow-none): A #CtkTreeViewColumn, or %NULL
13406 * @start_editing: %TRUE if the specified cell should start being edited.
13407 *
13408 * Sets the current keyboard focus to be at @path, and selects it. This is
13409 * useful when you want to focus the user’s attention on a particular row. If
13410 * @focus_column is not %NULL, then focus is given to the column specified by
13411 * it. Additionally, if @focus_column is specified, and @start_editing is
13412 * %TRUE, then editing should be started in the specified cell.
13413 * This function is often followed by @ctk_widget_grab_focus (@tree_view)
13414 * in order to give keyboard focus to the widget. Please note that editing
13415 * can only happen when the widget is realized.
13416 *
13417 * If @path is invalid for @model, the current cursor (if any) will be unset
13418 * and the function will return without failing.
13419 **/
13420void
13421ctk_tree_view_set_cursor (CtkTreeView *tree_view,
13422 CtkTreePath *path,
13423 CtkTreeViewColumn *focus_column,
13424 gboolean start_editing)
13425{
13426 ctk_tree_view_set_cursor_on_cell (tree_view, path, focus_column,
13427 NULL((void*)0), start_editing);
13428}
13429
13430/**
13431 * ctk_tree_view_set_cursor_on_cell:
13432 * @tree_view: A #CtkTreeView
13433 * @path: A #CtkTreePath
13434 * @focus_column: (allow-none): A #CtkTreeViewColumn, or %NULL
13435 * @focus_cell: (allow-none): A #CtkCellRenderer, or %NULL
13436 * @start_editing: %TRUE if the specified cell should start being edited.
13437 *
13438 * Sets the current keyboard focus to be at @path, and selects it. This is
13439 * useful when you want to focus the user’s attention on a particular row. If
13440 * @focus_column is not %NULL, then focus is given to the column specified by
13441 * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
13442 * contains 2 or more editable or activatable cells, then focus is given to
13443 * the cell specified by @focus_cell. Additionally, if @focus_column is
13444 * specified, and @start_editing is %TRUE, then editing should be started in
13445 * the specified cell. This function is often followed by
13446 * @ctk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
13447 * widget. Please note that editing can only happen when the widget is
13448 * realized.
13449 *
13450 * If @path is invalid for @model, the current cursor (if any) will be unset
13451 * and the function will return without failing.
13452 *
13453 * Since: 2.2
13454 **/
13455void
13456ctk_tree_view_set_cursor_on_cell (CtkTreeView *tree_view,
13457 CtkTreePath *path,
13458 CtkTreeViewColumn *focus_column,
13459 CtkCellRenderer *focus_cell,
13460 gboolean start_editing)
13461{
13462 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13463 g_return_if_fail (path != NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return;
} } while (0)
;
13464 g_return_if_fail (focus_column == NULL || CTK_IS_TREE_VIEW_COLUMN (focus_column))do { if ((focus_column == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((focus_column)); GType __t = ((ctk_tree_view_column_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "focus_column == NULL || CTK_IS_TREE_VIEW_COLUMN (focus_column)"
); return; } } while (0)
;
13465
13466 if (!tree_view->priv->model)
13467 return;
13468
13469 if (focus_cell)
13470 {
13471 g_return_if_fail (focus_column)do { if ((focus_column)) { } else { g_return_if_fail_warning (
"Ctk", ((const char*) (__func__)), "focus_column"); return; }
} while (0)
;
13472 g_return_if_fail (CTK_IS_CELL_RENDERER (focus_cell))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((focus_cell)); GType __t = ((ctk_cell_renderer_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CELL_RENDERER (focus_cell)"); return
; } } while (0)
;
13473 }
13474
13475 /* cancel the current editing, if it exists */
13476 if (tree_view->priv->edited_column &&
13477 ctk_cell_area_get_edit_widget
13478 (ctk_cell_layout_get_area (CTK_CELL_LAYOUT (tree_view->priv->edited_column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->edited_column)), ((ctk_cell_layout_get_type
()))))))
)))
13479 ctk_tree_view_stop_editing (tree_view, TRUE(!(0)));
13480
13481 ctk_tree_view_real_set_cursor (tree_view, path, CLEAR_AND_SELECT | CLAMP_NODE);
13482
13483 if (focus_column &&
13484 ctk_tree_view_column_get_visible (focus_column))
13485 {
13486 GList *list;
13487 gboolean column_in_tree = FALSE(0);
13488
13489 for (list = tree_view->priv->columns; list; list = list->next)
13490 if (list->data == focus_column)
13491 {
13492 column_in_tree = TRUE(!(0));
13493 break;
13494 }
13495 g_return_if_fail (column_in_tree)do { if ((column_in_tree)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "column_in_tree"); return
; } } while (0)
;
13496 _ctk_tree_view_set_focus_column (tree_view, focus_column);
13497 if (focus_cell)
13498 ctk_tree_view_column_focus_cell (focus_column, focus_cell);
13499 if (start_editing)
13500 ctk_tree_view_start_editing (tree_view, path, TRUE(!(0)));
13501 }
13502}
13503
13504/**
13505 * ctk_tree_view_get_bin_window:
13506 * @tree_view: A #CtkTreeView
13507 *
13508 * Returns the window that @tree_view renders to.
13509 * This is used primarily to compare to `event->window`
13510 * to confirm that the event on @tree_view is on the right window.
13511 *
13512 * Returns: (nullable) (transfer none): A #CdkWindow, or %NULL when @tree_view
13513 * hasn’t been realized yet.
13514 **/
13515CdkWindow *
13516ctk_tree_view_get_bin_window (CtkTreeView *tree_view)
13517{
13518 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
13519
13520 return tree_view->priv->bin_window;
13521}
13522
13523/**
13524 * ctk_tree_view_get_path_at_pos:
13525 * @tree_view: A #CtkTreeView.
13526 * @x: The x position to be identified (relative to bin_window).
13527 * @y: The y position to be identified (relative to bin_window).
13528 * @path: (out) (optional) (nullable): A pointer to a #CtkTreePath
13529 * pointer to be filled in, or %NULL
13530 * @column: (out) (transfer none) (optional) (nullable): A pointer to
13531 * a #CtkTreeViewColumn pointer to be filled in, or %NULL
13532 * @cell_x: (out) (optional): A pointer where the X coordinate
13533 * relative to the cell can be placed, or %NULL
13534 * @cell_y: (out) (optional): A pointer where the Y coordinate
13535 * relative to the cell can be placed, or %NULL
13536 *
13537 * Finds the path at the point (@x, @y), relative to bin_window coordinates
13538 * (please see ctk_tree_view_get_bin_window()).
13539 * That is, @x and @y are relative to an events coordinates. @x and @y must
13540 * come from an event on the @tree_view only where `event->window ==
13541 * ctk_tree_view_get_bin_window ()`. It is primarily for
13542 * things like popup menus. If @path is non-%NULL, then it will be filled
13543 * with the #CtkTreePath at that point. This path should be freed with
13544 * ctk_tree_path_free(). If @column is non-%NULL, then it will be filled
13545 * with the column at that point. @cell_x and @cell_y return the coordinates
13546 * relative to the cell background (i.e. the @background_area passed to
13547 * ctk_cell_renderer_render()). This function is only meaningful if
13548 * @tree_view is realized. Therefore this function will always return %FALSE
13549 * if @tree_view is not realized or does not have a model.
13550 *
13551 * For converting widget coordinates (eg. the ones you get from
13552 * CtkWidget::query-tooltip), please see
13553 * ctk_tree_view_convert_widget_to_bin_window_coords().
13554 *
13555 * Returns: %TRUE if a row exists at that coordinate.
13556 **/
13557gboolean
13558ctk_tree_view_get_path_at_pos (CtkTreeView *tree_view,
13559 gint x,
13560 gint y,
13561 CtkTreePath **path,
13562 CtkTreeViewColumn **column,
13563 gint *cell_x,
13564 gint *cell_y)
13565{
13566 CtkRBTree *tree;
13567 CtkRBNode *node;
13568 gint y_offset;
13569
13570 g_return_val_if_fail (tree_view != NULL, FALSE)do { if ((tree_view != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "tree_view != NULL"); return
((0)); } } while (0)
;
13571
13572 if (path)
13573 *path = NULL((void*)0);
13574 if (column)
13575 *column = NULL((void*)0);
13576
13577 if (tree_view->priv->bin_window == NULL((void*)0))
13578 return FALSE(0);
13579
13580 if (tree_view->priv->tree == NULL((void*)0))
13581 return FALSE(0);
13582
13583 if (x > ctk_adjustment_get_upper (tree_view->priv->hadjustment))
13584 return FALSE(0);
13585
13586 if (x < 0 || y < 0)
13587 return FALSE(0);
13588
13589 if (column || cell_x)
13590 {
13591 CtkTreeViewColumn *tmp_column;
13592 CtkTreeViewColumn *last_column = NULL((void*)0);
13593 GList *list;
13594 gint remaining_x = x;
13595 gboolean found = FALSE(0);
13596 gboolean rtl;
13597 gint width;
13598
13599 rtl = (ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL);
13600 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
13601 list;
13602 list = (rtl ? list->prev : list->next))
13603 {
13604 tmp_column = list->data;
13605
13606 if (ctk_tree_view_column_get_visible (tmp_column) == FALSE(0))
13607 continue;
13608
13609 last_column = tmp_column;
13610 width = ctk_tree_view_column_get_width (tmp_column);
13611 if (remaining_x < width)
13612 {
13613 found = TRUE(!(0));
13614
13615 if (column)
13616 *column = tmp_column;
13617
13618 if (cell_x)
13619 *cell_x = remaining_x;
13620
13621 break;
13622 }
13623 remaining_x -= width;
13624 }
13625
13626 /* If found is FALSE and there is a last_column, then it the remainder
13627 * space is in that area
13628 */
13629 if (!found)
13630 {
13631 if (last_column)
13632 {
13633 if (column)
13634 *column = last_column;
13635
13636 if (cell_x)
13637 *cell_x = ctk_tree_view_column_get_width (last_column) + remaining_x;
13638 }
13639 else
13640 {
13641 return FALSE(0);
13642 }
13643 }
13644 }
13645
13646 y_offset = _ctk_rbtree_find_offset (tree_view->priv->tree,
13647 TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y)((y) + tree_view->priv->dy),
13648 &tree, &node);
13649
13650 if (tree == NULL((void*)0))
13651 return FALSE(0);
13652
13653 if (cell_y)
13654 *cell_y = y_offset;
13655
13656 if (path)
13657 *path = _ctk_tree_path_new_from_rbtree (tree, node);
13658
13659 return TRUE(!(0));
13660}
13661
13662
13663static inline gint
13664ctk_tree_view_get_cell_area_height (CtkTreeView *tree_view,
13665 CtkRBNode *node,
13666 gint vertical_separator)
13667{
13668 int expander_size = ctk_tree_view_get_expander_size (tree_view);
13669 int height;
13670
13671 /* The "cell" areas are the cell_area passed in to ctk_cell_renderer_render(),
13672 * i.e. just the cells, no spacing.
13673 *
13674 * The cell area height is at least expander_size - vertical_separator.
13675 * For regular nodes, the height is then at least expander_size. We should
13676 * be able to enforce the expander_size minimum here, because this
13677 * function will not be called for irregular (e.g. separator) rows.
13678 */
13679 height = ctk_tree_view_get_row_height (tree_view, node);
13680 if (height < expander_size)
13681 height = expander_size;
13682
13683 return height - vertical_separator;
13684}
13685
13686static inline gint
13687ctk_tree_view_get_cell_area_y_offset (CtkTreeView *tree_view,
13688 CtkRBTree *tree,
13689 CtkRBNode *node,
13690 gint vertical_separator)
13691{
13692 int offset;
13693
13694 offset = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
13695 offset += vertical_separator / 2;
13696
13697 return offset;
13698}
13699
13700/**
13701 * ctk_tree_view_get_cell_area:
13702 * @tree_view: a #CtkTreeView
13703 * @path: (allow-none): a #CtkTreePath for the row, or %NULL to get only horizontal coordinates
13704 * @column: (allow-none): a #CtkTreeViewColumn for the column, or %NULL to get only vertical coordinates
13705 * @rect: (out): rectangle to fill with cell rect
13706 *
13707 * Fills the bounding rectangle in bin_window coordinates for the cell at the
13708 * row specified by @path and the column specified by @column. If @path is
13709 * %NULL, or points to a path not currently displayed, the @y and @height fields
13710 * of the rectangle will be filled with 0. If @column is %NULL, the @x and @width
13711 * fields will be filled with 0. The sum of all cell rects does not cover the
13712 * entire tree; there are extra pixels in between rows, for example. The
13713 * returned rectangle is equivalent to the @cell_area passed to
13714 * ctk_cell_renderer_render(). This function is only valid if @tree_view is
13715 * realized.
13716 **/
13717void
13718ctk_tree_view_get_cell_area (CtkTreeView *tree_view,
13719 CtkTreePath *path,
13720 CtkTreeViewColumn *column,
13721 CdkRectangle *rect)
13722{
13723 CtkRBTree *tree = NULL((void*)0);
13724 CtkRBNode *node = NULL((void*)0);
13725 gint vertical_separator;
13726 gint horizontal_separator;
13727
13728 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13729 g_return_if_fail (column == NULL || CTK_IS_TREE_VIEW_COLUMN (column))do { if ((column == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((column)); GType __t = ((ctk_tree_view_column_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "column == NULL || CTK_IS_TREE_VIEW_COLUMN (column)"
); return; } } while (0)
;
13730 g_return_if_fail (rect != NULL)do { if ((rect != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "rect != NULL"); return;
} } while (0)
;
13731 g_return_if_fail (!column || ctk_tree_view_column_get_tree_view (column) == (CtkWidget *) tree_view)do { if ((!column || ctk_tree_view_column_get_tree_view (column
) == (CtkWidget *) tree_view)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "!column || ctk_tree_view_column_get_tree_view (column) == (CtkWidget *) tree_view"
); return; } } while (0)
;
13732 g_return_if_fail (ctk_widget_get_realized (CTK_WIDGET (tree_view)))do { if ((ctk_widget_get_realized (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((tree_view)), ((ctk_widget_get_type ())))
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "ctk_widget_get_realized (CTK_WIDGET (tree_view))"
); return; } } while (0)
;
13733
13734 ctk_widget_style_get (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
13735 "vertical-separator", &vertical_separator,
13736 "horizontal-separator", &horizontal_separator,
13737 NULL((void*)0));
13738
13739 rect->x = 0;
13740 rect->y = 0;
13741 rect->width = 0;
13742 rect->height = 0;
13743
13744 if (column)
13745 {
13746 rect->x = ctk_tree_view_column_get_x_offset (column) + horizontal_separator/2;
13747 rect->width = ctk_tree_view_column_get_width (column) - horizontal_separator;
13748 }
13749
13750 if (path)
13751 {
13752 gboolean ret = _ctk_tree_view_find_node (tree_view, path, &tree, &node);
13753
13754 /* Get vertical coords */
13755 if ((!ret && tree == NULL((void*)0)) || ret)
13756 return;
13757
13758 if (row_is_separator (tree_view, NULL((void*)0), path))
13759 {
13760 /* There isn't really a "cell area" for separator, so we
13761 * return the y, height values for background area instead.
13762 */
13763 rect->y = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
13764 rect->height = ctk_tree_view_get_row_height (tree_view, node);
13765 }
13766 else
13767 {
13768 rect->y = ctk_tree_view_get_cell_area_y_offset (tree_view, tree, node,
13769 vertical_separator);
13770 rect->height = ctk_tree_view_get_cell_area_height (tree_view, node,
13771 vertical_separator);
13772 }
13773
13774 if (column &&
13775 ctk_tree_view_is_expander_column (tree_view, column))
13776 {
13777 gint depth = ctk_tree_path_get_depth (path);
13778 gboolean rtl;
13779
13780 rtl = ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL;
13781
13782 if (!rtl)
13783 rect->x += (depth - 1) * tree_view->priv->level_indentation;
13784 rect->width -= (depth - 1) * tree_view->priv->level_indentation;
13785
13786 if (ctk_tree_view_draw_expanders (tree_view))
13787 {
13788 int expander_size = ctk_tree_view_get_expander_size (tree_view);
13789 if (!rtl)
13790 rect->x += depth * expander_size;
13791 rect->width -= depth * expander_size;
13792 }
13793
13794 rect->width = MAX (rect->width, 0)(((rect->width) > (0)) ? (rect->width) : (0));
13795 }
13796 }
13797}
13798
13799static inline gint
13800ctk_tree_view_get_row_height (CtkTreeView *tree_view,
13801 CtkRBNode *node)
13802{
13803 int expander_size = ctk_tree_view_get_expander_size (tree_view);
13804 int height;
13805
13806 /* The "background" areas of all rows/cells add up to cover the entire tree.
13807 * The background includes all inter-row and inter-cell spacing.
13808 *
13809 * If the row pointed at by node does not have a height set, we default
13810 * to expander_size, which is the minimum height for regular nodes.
13811 * Non-regular nodes (e.g. separators) can have a height set smaller
13812 * than expander_size and should not be overruled here.
13813 */
13814 height = CTK_RBNODE_GET_HEIGHT (node)(node->offset-(node->left->offset+node->right->
offset+(node->children?node->children->root->offset
:0)))
;
13815 if (height <= 0)
13816 height = expander_size;
13817
13818 return height;
13819}
13820
13821static inline gint
13822ctk_tree_view_get_row_y_offset (CtkTreeView *tree_view,
13823 CtkRBTree *tree,
13824 CtkRBNode *node)
13825{
13826 int offset;
13827
13828 offset = _ctk_rbtree_node_find_offset (tree, node);
13829
13830 return RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, offset)((offset) - tree_view->priv->dy);
13831}
13832
13833/**
13834 * ctk_tree_view_get_background_area:
13835 * @tree_view: a #CtkTreeView
13836 * @path: (allow-none): a #CtkTreePath for the row, or %NULL to get only horizontal coordinates
13837 * @column: (allow-none): a #CtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
13838 * @rect: (out): rectangle to fill with cell background rect
13839 *
13840 * Fills the bounding rectangle in bin_window coordinates for the cell at the
13841 * row specified by @path and the column specified by @column. If @path is
13842 * %NULL, or points to a node not found in the tree, the @y and @height fields of
13843 * the rectangle will be filled with 0. If @column is %NULL, the @x and @width
13844 * fields will be filled with 0. The returned rectangle is equivalent to the
13845 * @background_area passed to ctk_cell_renderer_render(). These background
13846 * areas tile to cover the entire bin window. Contrast with the @cell_area,
13847 * returned by ctk_tree_view_get_cell_area(), which returns only the cell
13848 * itself, excluding surrounding borders and the tree expander area.
13849 *
13850 **/
13851void
13852ctk_tree_view_get_background_area (CtkTreeView *tree_view,
13853 CtkTreePath *path,
13854 CtkTreeViewColumn *column,
13855 CdkRectangle *rect)
13856{
13857 CtkRBTree *tree = NULL((void*)0);
13858 CtkRBNode *node = NULL((void*)0);
13859
13860 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13861 g_return_if_fail (column == NULL || CTK_IS_TREE_VIEW_COLUMN (column))do { if ((column == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((column)); GType __t = ((ctk_tree_view_column_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "column == NULL || CTK_IS_TREE_VIEW_COLUMN (column)"
); return; } } while (0)
;
13862 g_return_if_fail (rect != NULL)do { if ((rect != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "rect != NULL"); return;
} } while (0)
;
13863
13864 rect->x = 0;
13865 rect->y = 0;
13866 rect->width = 0;
13867 rect->height = 0;
13868
13869 if (path)
13870 {
13871 /* Get vertical coords */
13872
13873 if (!_ctk_tree_view_find_node (tree_view, path, &tree, &node) &&
13874 tree == NULL((void*)0))
13875 return;
13876
13877 rect->y = ctk_tree_view_get_row_y_offset (tree_view, tree, node);
13878 rect->height = ctk_tree_view_get_row_height (tree_view, node);
13879 }
13880
13881 if (column)
13882 {
13883 gint x2 = 0;
13884
13885 ctk_tree_view_get_background_xrange (tree_view, tree, column, &rect->x, &x2);
13886 rect->width = x2 - rect->x;
13887 }
13888}
13889
13890/**
13891 * ctk_tree_view_get_visible_rect:
13892 * @tree_view: a #CtkTreeView
13893 * @visible_rect: (out): rectangle to fill
13894 *
13895 * Fills @visible_rect with the currently-visible region of the
13896 * buffer, in tree coordinates. Convert to bin_window coordinates with
13897 * ctk_tree_view_convert_tree_to_bin_window_coords().
13898 * Tree coordinates start at 0,0 for row 0 of the tree, and cover the entire
13899 * scrollable area of the tree.
13900 **/
13901void
13902ctk_tree_view_get_visible_rect (CtkTreeView *tree_view,
13903 CdkRectangle *visible_rect)
13904{
13905 CtkAllocation allocation;
13906 CtkWidget *widget;
13907
13908 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13909
13910 widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
13911
13912 if (visible_rect)
13913 {
13914 ctk_widget_get_allocation (widget, &allocation);
13915 visible_rect->x = ctk_adjustment_get_value (tree_view->priv->hadjustment);
13916 visible_rect->y = ctk_adjustment_get_value (tree_view->priv->vadjustment);
13917 visible_rect->width = allocation.width;
13918 visible_rect->height = allocation.height - ctk_tree_view_get_effective_header_height (tree_view);
13919 }
13920}
13921
13922/**
13923 * ctk_tree_view_convert_widget_to_tree_coords:
13924 * @tree_view: a #CtkTreeView
13925 * @wx: X coordinate relative to the widget
13926 * @wy: Y coordinate relative to the widget
13927 * @tx: (out): return location for tree X coordinate
13928 * @ty: (out): return location for tree Y coordinate
13929 *
13930 * Converts widget coordinates to coordinates for the
13931 * tree (the full scrollable area of the tree).
13932 *
13933 * Since: 2.12
13934 **/
13935void
13936ctk_tree_view_convert_widget_to_tree_coords (CtkTreeView *tree_view,
13937 gint wx,
13938 gint wy,
13939 gint *tx,
13940 gint *ty)
13941{
13942 gint x, y;
13943
13944 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13945
13946 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view,
13947 wx, wy,
13948 &x, &y);
13949 ctk_tree_view_convert_bin_window_to_tree_coords (tree_view,
13950 x, y,
13951 tx, ty);
13952}
13953
13954/**
13955 * ctk_tree_view_convert_tree_to_widget_coords:
13956 * @tree_view: a #CtkTreeView
13957 * @tx: X coordinate relative to the tree
13958 * @ty: Y coordinate relative to the tree
13959 * @wx: (out): return location for widget X coordinate
13960 * @wy: (out): return location for widget Y coordinate
13961 *
13962 * Converts tree coordinates (coordinates in full scrollable area of the tree)
13963 * to widget coordinates.
13964 *
13965 * Since: 2.12
13966 **/
13967void
13968ctk_tree_view_convert_tree_to_widget_coords (CtkTreeView *tree_view,
13969 gint tx,
13970 gint ty,
13971 gint *wx,
13972 gint *wy)
13973{
13974 gint x, y;
13975
13976 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
13977
13978 ctk_tree_view_convert_tree_to_bin_window_coords (tree_view,
13979 tx, ty,
13980 &x, &y);
13981 ctk_tree_view_convert_bin_window_to_widget_coords (tree_view,
13982 x, y,
13983 wx, wy);
13984}
13985
13986/**
13987 * ctk_tree_view_convert_widget_to_bin_window_coords:
13988 * @tree_view: a #CtkTreeView
13989 * @wx: X coordinate relative to the widget
13990 * @wy: Y coordinate relative to the widget
13991 * @bx: (out): return location for bin_window X coordinate
13992 * @by: (out): return location for bin_window Y coordinate
13993 *
13994 * Converts widget coordinates to coordinates for the bin_window
13995 * (see ctk_tree_view_get_bin_window()).
13996 *
13997 * Since: 2.12
13998 **/
13999void
14000ctk_tree_view_convert_widget_to_bin_window_coords (CtkTreeView *tree_view,
14001 gint wx,
14002 gint wy,
14003 gint *bx,
14004 gint *by)
14005{
14006 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14007
14008 if (bx)
14009 *bx = wx + ctk_adjustment_get_value (tree_view->priv->hadjustment);
14010 if (by)
14011 *by = wy - ctk_tree_view_get_effective_header_height (tree_view);
14012}
14013
14014/**
14015 * ctk_tree_view_convert_bin_window_to_widget_coords:
14016 * @tree_view: a #CtkTreeView
14017 * @bx: bin_window X coordinate
14018 * @by: bin_window Y coordinate
14019 * @wx: (out): return location for widget X coordinate
14020 * @wy: (out): return location for widget Y coordinate
14021 *
14022 * Converts bin_window coordinates (see ctk_tree_view_get_bin_window())
14023 * to widget relative coordinates.
14024 *
14025 * Since: 2.12
14026 **/
14027void
14028ctk_tree_view_convert_bin_window_to_widget_coords (CtkTreeView *tree_view,
14029 gint bx,
14030 gint by,
14031 gint *wx,
14032 gint *wy)
14033{
14034 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14035
14036 if (wx)
14037 *wx = bx - ctk_adjustment_get_value (tree_view->priv->hadjustment);
14038 if (wy)
14039 *wy = by + ctk_tree_view_get_effective_header_height (tree_view);
14040}
14041
14042/**
14043 * ctk_tree_view_convert_tree_to_bin_window_coords:
14044 * @tree_view: a #CtkTreeView
14045 * @tx: tree X coordinate
14046 * @ty: tree Y coordinate
14047 * @bx: (out): return location for X coordinate relative to bin_window
14048 * @by: (out): return location for Y coordinate relative to bin_window
14049 *
14050 * Converts tree coordinates (coordinates in full scrollable area of the tree)
14051 * to bin_window coordinates.
14052 *
14053 * Since: 2.12
14054 **/
14055void
14056ctk_tree_view_convert_tree_to_bin_window_coords (CtkTreeView *tree_view,
14057 gint tx,
14058 gint ty,
14059 gint *bx,
14060 gint *by)
14061{
14062 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14063
14064 if (bx)
14065 *bx = tx;
14066 if (by)
14067 *by = ty - tree_view->priv->dy;
14068}
14069
14070/**
14071 * ctk_tree_view_convert_bin_window_to_tree_coords:
14072 * @tree_view: a #CtkTreeView
14073 * @bx: X coordinate relative to bin_window
14074 * @by: Y coordinate relative to bin_window
14075 * @tx: (out): return location for tree X coordinate
14076 * @ty: (out): return location for tree Y coordinate
14077 *
14078 * Converts bin_window coordinates to coordinates for the
14079 * tree (the full scrollable area of the tree).
14080 *
14081 * Since: 2.12
14082 **/
14083void
14084ctk_tree_view_convert_bin_window_to_tree_coords (CtkTreeView *tree_view,
14085 gint bx,
14086 gint by,
14087 gint *tx,
14088 gint *ty)
14089{
14090 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14091
14092 if (tx)
14093 *tx = bx;
14094 if (ty)
14095 *ty = by + tree_view->priv->dy;
14096}
14097
14098
14099
14100/**
14101 * ctk_tree_view_get_visible_range:
14102 * @tree_view: A #CtkTreeView
14103 * @start_path: (out) (allow-none): Return location for start of region,
14104 * or %NULL.
14105 * @end_path: (out) (allow-none): Return location for end of region, or %NULL.
14106 *
14107 * Sets @start_path and @end_path to be the first and last visible path.
14108 * Note that there may be invisible paths in between.
14109 *
14110 * The paths should be freed with ctk_tree_path_free() after use.
14111 *
14112 * Returns: %TRUE, if valid paths were placed in @start_path and @end_path.
14113 *
14114 * Since: 2.8
14115 **/
14116gboolean
14117ctk_tree_view_get_visible_range (CtkTreeView *tree_view,
14118 CtkTreePath **start_path,
14119 CtkTreePath **end_path)
14120{
14121 CtkRBTree *tree;
14122 CtkRBNode *node;
14123 gboolean retval;
14124
14125 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
14126
14127 if (!tree_view->priv->tree)
14128 return FALSE(0);
14129
14130 retval = TRUE(!(0));
14131
14132 if (start_path)
14133 {
14134 _ctk_rbtree_find_offset (tree_view->priv->tree,
14135 TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0)((0) + tree_view->priv->dy),
14136 &tree, &node);
14137 if (node)
14138 *start_path = _ctk_tree_path_new_from_rbtree (tree, node);
14139 else
14140 retval = FALSE(0);
14141 }
14142
14143 if (end_path)
14144 {
14145 gint y;
14146
14147 if (ctk_tree_view_get_height (tree_view) < ctk_adjustment_get_page_size (tree_view->priv->vadjustment))
14148 y = ctk_tree_view_get_height (tree_view) - 1;
14149 else
14150 y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, ctk_adjustment_get_page_size (tree_view->priv->vadjustment))((ctk_adjustment_get_page_size (tree_view->priv->vadjustment
)) + tree_view->priv->dy)
- 1;
14151
14152 _ctk_rbtree_find_offset (tree_view->priv->tree, y, &tree, &node);
14153 if (node)
14154 *end_path = _ctk_tree_path_new_from_rbtree (tree, node);
14155 else
14156 retval = FALSE(0);
14157 }
14158
14159 return retval;
14160}
14161
14162/**
14163 * ctk_tree_view_is_blank_at_pos:
14164 * @tree_view: A #CtkTreeView
14165 * @x: The x position to be identified (relative to bin_window)
14166 * @y: The y position to be identified (relative to bin_window)
14167 * @path: (out) (optional) (nullable): A pointer to a #CtkTreePath pointer to
14168 * be filled in, or %NULL
14169 * @column: (out) (transfer none) (optional) (nullable): A pointer to a
14170 * #CtkTreeViewColumn pointer to be filled in, or %NULL
14171 * @cell_x: (out) (optional): A pointer where the X coordinate relative to the
14172 * cell can be placed, or %NULL
14173 * @cell_y: (out) (optional): A pointer where the Y coordinate relative to the
14174 * cell can be placed, or %NULL
14175 *
14176 * Determine whether the point (@x, @y) in @tree_view is blank, that is no
14177 * cell content nor an expander arrow is drawn at the location. If so, the
14178 * location can be considered as the background. You might wish to take
14179 * special action on clicks on the background, such as clearing a current
14180 * selection, having a custom context menu or starting rubber banding.
14181 *
14182 * The @x and @y coordinate that are provided must be relative to bin_window
14183 * coordinates. That is, @x and @y must come from an event on @tree_view
14184 * where `event->window == ctk_tree_view_get_bin_window ()`.
14185 *
14186 * For converting widget coordinates (eg. the ones you get from
14187 * CtkWidget::query-tooltip), please see
14188 * ctk_tree_view_convert_widget_to_bin_window_coords().
14189 *
14190 * The @path, @column, @cell_x and @cell_y arguments will be filled in
14191 * likewise as for ctk_tree_view_get_path_at_pos(). Please see
14192 * ctk_tree_view_get_path_at_pos() for more information.
14193 *
14194 * Returns: %TRUE if the area at the given coordinates is blank,
14195 * %FALSE otherwise.
14196 *
14197 * Since: 3.0
14198 */
14199gboolean
14200ctk_tree_view_is_blank_at_pos (CtkTreeView *tree_view,
14201 gint x,
14202 gint y,
14203 CtkTreePath **path,
14204 CtkTreeViewColumn **column,
14205 gint *cell_x,
14206 gint *cell_y)
14207{
14208 CtkRBTree *tree;
14209 CtkRBNode *node;
14210 CtkTreeIter iter;
14211 CtkTreePath *real_path;
14212 CtkTreeViewColumn *real_column;
14213 CdkRectangle cell_area, background_area;
14214
14215 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
14216
14217 if (!ctk_tree_view_get_path_at_pos (tree_view, x, y,
14218 &real_path, &real_column,
14219 cell_x, cell_y))
14220 /* If there's no path here, it is blank */
14221 return TRUE(!(0));
14222
14223 if (path)
14224 *path = real_path;
14225
14226 if (column)
14227 *column = real_column;
14228
14229 ctk_tree_model_get_iter (tree_view->priv->model, &iter, real_path);
14230 _ctk_tree_view_find_node (tree_view, real_path, &tree, &node);
14231
14232 /* Check if there's an expander arrow at (x, y) */
14233 if (real_column == tree_view->priv->expander_column
14234 && ctk_tree_view_draw_expanders (tree_view))
14235 {
14236 gboolean over_arrow;
14237
14238 over_arrow = coords_are_over_arrow (tree_view, tree, node, x, y);
14239
14240 if (over_arrow)
14241 {
14242 if (!path)
14243 ctk_tree_path_free (real_path);
14244 return FALSE(0);
14245 }
14246 }
14247
14248 /* Otherwise, have the column see if there's a cell at (x, y) */
14249 ctk_tree_view_column_cell_set_cell_data (real_column,
14250 tree_view->priv->model,
14251 &iter,
14252 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
14253 node->children ? TRUE(!(0)) : FALSE(0));
14254
14255 ctk_tree_view_get_background_area (tree_view, real_path, real_column,
14256 &background_area);
14257 ctk_tree_view_get_cell_area (tree_view, real_path, real_column,
14258 &cell_area);
14259
14260 if (!path)
14261 ctk_tree_path_free (real_path);
14262
14263 return _ctk_tree_view_column_is_blank_at_pos (real_column,
14264 &cell_area,
14265 &background_area,
14266 x, y);
14267}
14268
14269static void
14270unset_reorderable (CtkTreeView *tree_view)
14271{
14272 if (tree_view->priv->reorderable)
14273 {
14274 tree_view->priv->reorderable = FALSE(0);
14275 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_REORDERABLE]);
14276 }
14277}
14278
14279/**
14280 * ctk_tree_view_enable_model_drag_source:
14281 * @tree_view: a #CtkTreeView
14282 * @start_button_mask: Mask of allowed buttons to start drag
14283 * @targets: (array length=n_targets): the table of targets that the drag will support
14284 * @n_targets: the number of items in @targets
14285 * @actions: the bitmask of possible actions for a drag from this
14286 * widget
14287 *
14288 * Turns @tree_view into a drag source for automatic DND. Calling this
14289 * method sets #CtkTreeView:reorderable to %FALSE.
14290 **/
14291void
14292ctk_tree_view_enable_model_drag_source (CtkTreeView *tree_view,
14293 CdkModifierType start_button_mask,
14294 const CtkTargetEntry *targets,
14295 gint n_targets,
14296 CdkDragAction actions)
14297{
14298 TreeViewDragInfo *di;
14299
14300 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14301
14302 ctk_drag_source_set (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
14303 0,
14304 targets,
14305 n_targets,
14306 actions);
14307
14308 di = ensure_info (tree_view);
14309
14310 di->start_button_mask = start_button_mask;
14311 di->source_actions = actions;
14312 di->source_set = TRUE(!(0));
14313
14314 unset_reorderable (tree_view);
14315}
14316
14317/**
14318 * ctk_tree_view_enable_model_drag_dest:
14319 * @tree_view: a #CtkTreeView
14320 * @targets: (array length=n_targets): the table of targets that
14321 * the drag will support
14322 * @n_targets: the number of items in @targets
14323 * @actions: the bitmask of possible actions for a drag from this
14324 * widget
14325 *
14326 * Turns @tree_view into a drop destination for automatic DND. Calling
14327 * this method sets #CtkTreeView:reorderable to %FALSE.
14328 **/
14329void
14330ctk_tree_view_enable_model_drag_dest (CtkTreeView *tree_view,
14331 const CtkTargetEntry *targets,
14332 gint n_targets,
14333 CdkDragAction actions)
14334{
14335 TreeViewDragInfo *di;
14336
14337 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14338
14339 ctk_drag_dest_set (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
14340 0,
14341 targets,
14342 n_targets,
14343 actions);
14344
14345 di = ensure_info (tree_view);
14346 di->dest_set = TRUE(!(0));
14347
14348 unset_reorderable (tree_view);
14349}
14350
14351/**
14352 * ctk_tree_view_unset_rows_drag_source:
14353 * @tree_view: a #CtkTreeView
14354 *
14355 * Undoes the effect of
14356 * ctk_tree_view_enable_model_drag_source(). Calling this method sets
14357 * #CtkTreeView:reorderable to %FALSE.
14358 **/
14359void
14360ctk_tree_view_unset_rows_drag_source (CtkTreeView *tree_view)
14361{
14362 TreeViewDragInfo *di;
14363
14364 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14365
14366 di = get_info (tree_view);
14367
14368 if (di)
14369 {
14370 if (di->source_set)
14371 {
14372 ctk_drag_source_unset (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
14373 di->source_set = FALSE(0);
14374 }
14375
14376 if (!di->dest_set && !di->source_set)
14377 remove_info (tree_view);
14378 }
14379
14380 unset_reorderable (tree_view);
14381}
14382
14383/**
14384 * ctk_tree_view_unset_rows_drag_dest:
14385 * @tree_view: a #CtkTreeView
14386 *
14387 * Undoes the effect of
14388 * ctk_tree_view_enable_model_drag_dest(). Calling this method sets
14389 * #CtkTreeView:reorderable to %FALSE.
14390 **/
14391void
14392ctk_tree_view_unset_rows_drag_dest (CtkTreeView *tree_view)
14393{
14394 TreeViewDragInfo *di;
14395
14396 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14397
14398 di = get_info (tree_view);
14399
14400 if (di)
14401 {
14402 if (di->dest_set)
14403 {
14404 ctk_drag_dest_unset (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
14405 di->dest_set = FALSE(0);
14406 }
14407
14408 if (!di->dest_set && !di->source_set)
14409 remove_info (tree_view);
14410 }
14411
14412 unset_reorderable (tree_view);
14413}
14414
14415/**
14416 * ctk_tree_view_set_drag_dest_row:
14417 * @tree_view: a #CtkTreeView
14418 * @path: (allow-none): The path of the row to highlight, or %NULL
14419 * @pos: Specifies whether to drop before, after or into the row
14420 *
14421 * Sets the row that is highlighted for feedback.
14422 * If @path is %NULL, an existing highlight is removed.
14423 */
14424void
14425ctk_tree_view_set_drag_dest_row (CtkTreeView *tree_view,
14426 CtkTreePath *path,
14427 CtkTreeViewDropPosition pos)
14428{
14429 CtkTreePath *current_dest;
14430
14431 /* Note; this function is exported to allow a custom DND
14432 * implementation, so it can't touch TreeViewDragInfo
14433 */
14434
14435 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14436
14437 current_dest = NULL((void*)0);
14438
14439 if (tree_view->priv->drag_dest_row)
14440 {
14441 current_dest = ctk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
14442 ctk_tree_row_reference_free (tree_view->priv->drag_dest_row);
14443 }
14444
14445 /* special case a drop on an empty model */
14446 tree_view->priv->empty_view_drop = 0;
14447
14448 if (pos == CTK_TREE_VIEW_DROP_BEFORE && path
14449 && ctk_tree_path_get_depth (path) == 1
14450 && ctk_tree_path_get_indices (path)[0] == 0)
14451 {
14452 gint n_children;
14453
14454 n_children = ctk_tree_model_iter_n_children (tree_view->priv->model,
14455 NULL((void*)0));
14456
14457 if (!n_children)
14458 tree_view->priv->empty_view_drop = 1;
14459 }
14460
14461 tree_view->priv->drag_dest_pos = pos;
14462
14463 if (path)
14464 {
14465 tree_view->priv->drag_dest_row =
14466 ctk_tree_row_reference_new_proxy (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view->priv->model, path);
14467 ctk_tree_view_queue_draw_path (tree_view, path, NULL((void*)0));
14468 }
14469 else
14470 tree_view->priv->drag_dest_row = NULL((void*)0);
14471
14472 if (current_dest)
14473 {
14474 CtkRBTree *tree, *new_tree;
14475 CtkRBNode *node, *new_node;
14476
14477 _ctk_tree_view_find_node (tree_view, current_dest, &tree, &node);
14478 _ctk_tree_view_queue_draw_node (tree_view, tree, node, NULL((void*)0));
14479
14480 if (tree && node)
14481 {
14482 _ctk_rbtree_next_full (tree, node, &new_tree, &new_node);
14483 if (new_tree && new_node)
14484 _ctk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL((void*)0));
14485
14486 _ctk_rbtree_prev_full (tree, node, &new_tree, &new_node);
14487 if (new_tree && new_node)
14488 _ctk_tree_view_queue_draw_node (tree_view, new_tree, new_node, NULL((void*)0));
14489 }
14490 ctk_tree_path_free (current_dest);
14491 }
14492}
14493
14494/**
14495 * ctk_tree_view_get_drag_dest_row:
14496 * @tree_view: a #CtkTreeView
14497 * @path: (out) (optional) (nullable): Return location for the path of the highlighted row, or %NULL.
14498 * @pos: (out) (optional): Return location for the drop position, or %NULL
14499 *
14500 * Gets information about the row that is highlighted for feedback.
14501 **/
14502void
14503ctk_tree_view_get_drag_dest_row (CtkTreeView *tree_view,
14504 CtkTreePath **path,
14505 CtkTreeViewDropPosition *pos)
14506{
14507 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14508
14509 if (path)
14510 {
14511 if (tree_view->priv->drag_dest_row)
14512 *path = ctk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
14513 else
14514 {
14515 if (tree_view->priv->empty_view_drop)
14516 *path = ctk_tree_path_new_from_indices (0, -1);
14517 else
14518 *path = NULL((void*)0);
14519 }
14520 }
14521
14522 if (pos)
14523 *pos = tree_view->priv->drag_dest_pos;
14524}
14525
14526/**
14527 * ctk_tree_view_get_dest_row_at_pos:
14528 * @tree_view: a #CtkTreeView
14529 * @drag_x: the position to determine the destination row for
14530 * @drag_y: the position to determine the destination row for
14531 * @path: (out) (optional) (nullable): Return location for the path of
14532 * the highlighted row, or %NULL.
14533 * @pos: (out) (optional): Return location for the drop position, or
14534 * %NULL
14535 *
14536 * Determines the destination row for a given position. @drag_x and
14537 * @drag_y are expected to be in widget coordinates. This function is only
14538 * meaningful if @tree_view is realized. Therefore this function will always
14539 * return %FALSE if @tree_view is not realized or does not have a model.
14540 *
14541 * Returns: whether there is a row at the given position, %TRUE if this
14542 * is indeed the case.
14543 **/
14544gboolean
14545ctk_tree_view_get_dest_row_at_pos (CtkTreeView *tree_view,
14546 gint drag_x,
14547 gint drag_y,
14548 CtkTreePath **path,
14549 CtkTreeViewDropPosition *pos)
14550{
14551 gint cell_y;
14552 gint bin_x, bin_y;
14553 gdouble offset_into_row;
14554 gdouble fourth;
14555 CdkRectangle cell;
14556 CtkTreeViewColumn *column = NULL((void*)0);
14557 CtkTreePath *tmp_path = NULL((void*)0);
14558
14559 /* Note; this function is exported to allow a custom DND
14560 * implementation, so it can't touch TreeViewDragInfo
14561 */
14562
14563 g_return_val_if_fail (tree_view != NULL, FALSE)do { if ((tree_view != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "tree_view != NULL"); return
((0)); } } while (0)
;
14564 g_return_val_if_fail (drag_x >= 0, FALSE)do { if ((drag_x >= 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "drag_x >= 0"); return
((0)); } } while (0)
;
14565 g_return_val_if_fail (drag_y >= 0, FALSE)do { if ((drag_y >= 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "drag_y >= 0"); return
((0)); } } while (0)
;
14566
14567 if (path)
14568 *path = NULL((void*)0);
14569
14570 if (tree_view->priv->bin_window == NULL((void*)0))
14571 return FALSE(0);
14572
14573 if (tree_view->priv->tree == NULL((void*)0))
14574 return FALSE(0);
14575
14576 /* If in the top fourth of a row, we drop before that row; if
14577 * in the bottom fourth, drop after that row; if in the middle,
14578 * and the row has children, drop into the row.
14579 */
14580 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, drag_x, drag_y,
14581 &bin_x, &bin_y);
14582
14583 if (!ctk_tree_view_get_path_at_pos (tree_view,
14584 bin_x,
14585 bin_y,
14586 &tmp_path,
14587 &column,
14588 NULL((void*)0),
14589 &cell_y))
14590 return FALSE(0);
14591
14592 ctk_tree_view_get_background_area (tree_view, tmp_path, column,
14593 &cell);
14594
14595 offset_into_row = cell_y;
14596
14597 if (path)
14598 *path = tmp_path;
14599 else
14600 ctk_tree_path_free (tmp_path);
14601
14602 tmp_path = NULL((void*)0);
14603
14604 fourth = cell.height / 4.0;
14605
14606 if (pos)
14607 {
14608 if (offset_into_row < fourth)
14609 {
14610 *pos = CTK_TREE_VIEW_DROP_BEFORE;
14611 }
14612 else if (offset_into_row < (cell.height / 2.0))
14613 {
14614 *pos = CTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
14615 }
14616 else if (offset_into_row < cell.height - fourth)
14617 {
14618 *pos = CTK_TREE_VIEW_DROP_INTO_OR_AFTER;
14619 }
14620 else
14621 {
14622 *pos = CTK_TREE_VIEW_DROP_AFTER;
14623 }
14624 }
14625
14626 return TRUE(!(0));
14627}
14628
14629
14630
14631/* KEEP IN SYNC WITH CTK_TREE_VIEW_BIN_EXPOSE */
14632/**
14633 * ctk_tree_view_create_row_drag_icon:
14634 * @tree_view: a #CtkTreeView
14635 * @path: a #CtkTreePath in @tree_view
14636 *
14637 * Creates a #cairo_surface_t representation of the row at @path.
14638 * This image is used for a drag icon.
14639 *
14640 * Returns: (transfer full): a newly-allocated surface of the drag icon.
14641 **/
14642cairo_surface_t *
14643ctk_tree_view_create_row_drag_icon (CtkTreeView *tree_view,
14644 CtkTreePath *path)
14645{
14646 CtkTreeIter iter;
14647 CtkRBTree *tree;
14648 CtkRBNode *node;
14649 CtkStyleContext *context;
14650 gint cell_offset;
14651 GList *list;
14652 CdkRectangle background_area;
14653 CtkWidget *widget;
14654 gint depth;
14655 /* start drawing inside the black outline */
14656 gint x = 1, y = 1;
14657 cairo_surface_t *surface;
14658 gint bin_window_width;
14659 gboolean is_separator = FALSE(0);
14660 gboolean rtl;
14661 cairo_t *cr;
14662
14663 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
14664 g_return_val_if_fail (path != NULL, NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
((void*)0)); } } while (0)
;
14665
14666 widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
14667
14668 if (!ctk_widget_get_realized (widget))
14669 return NULL((void*)0);
14670
14671 depth = ctk_tree_path_get_depth (path);
14672
14673 _ctk_tree_view_find_node (tree_view,
14674 path,
14675 &tree,
14676 &node);
14677
14678 if (tree == NULL((void*)0))
14679 return NULL((void*)0);
14680
14681 if (!ctk_tree_model_get_iter (tree_view->priv->model,
14682 &iter,
14683 path))
14684 return NULL((void*)0);
14685
14686 context = ctk_widget_get_style_context (widget);
14687
14688 is_separator = row_is_separator (tree_view, &iter, NULL((void*)0));
14689
14690 cell_offset = x;
14691
14692 background_area.y = y;
14693 background_area.height = ctk_tree_view_get_row_height (tree_view, node);
14694
14695 bin_window_width = cdk_window_get_width (tree_view->priv->bin_window);
14696
14697 surface = cdk_window_create_similar_surface (tree_view->priv->bin_window,
14698 CAIRO_CONTENT_COLOR,
14699 bin_window_width + 2,
14700 background_area.height + 2);
14701
14702 cr = cairo_create (surface);
14703
14704 ctk_render_background (context, cr, 0, 0,
14705 bin_window_width + 2,
14706 background_area.height + 2);
14707
14708 rtl = ctk_widget_get_direction (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL;
14709
14710 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
14711 list;
14712 list = (rtl ? list->prev : list->next))
14713 {
14714 CtkTreeViewColumn *column = list->data;
14715 CdkRectangle cell_area;
14716 gint vertical_separator;
14717
14718 if (!ctk_tree_view_column_get_visible (column))
14719 continue;
14720
14721 ctk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, &iter,
14722 CTK_RBNODE_FLAG_SET (node, CTK_RBNODE_IS_PARENT)(node?(((node->flags&CTK_RBNODE_IS_PARENT)==CTK_RBNODE_IS_PARENT
)?(!(0)):(0)):(0))
,
14723 node->children?TRUE(!(0)):FALSE(0));
14724
14725 background_area.x = cell_offset;
14726 background_area.width = ctk_tree_view_column_get_width (column);
14727
14728 ctk_widget_style_get (widget,
14729 "vertical-separator", &vertical_separator,
14730 NULL((void*)0));
14731
14732 cell_area = background_area;
14733
14734 cell_area.y += vertical_separator / 2;
14735 cell_area.height -= vertical_separator;
14736
14737 if (ctk_tree_view_is_expander_column (tree_view, column))
14738 {
14739 if (!rtl)
14740 cell_area.x += (depth - 1) * tree_view->priv->level_indentation;
14741 cell_area.width -= (depth - 1) * tree_view->priv->level_indentation;
14742
14743 if (ctk_tree_view_draw_expanders (tree_view))
14744 {
14745 int expander_size = ctk_tree_view_get_expander_size (tree_view);
14746 if (!rtl)
14747 cell_area.x += depth * expander_size;
14748 cell_area.width -= depth * expander_size;
14749 }
14750 }
14751
14752 if (ctk_tree_view_column_cell_is_visible (column))
14753 {
14754 if (is_separator)
14755 {
14756 ctk_style_context_save (context);
14757 ctk_style_context_add_class (context, CTK_STYLE_CLASS_SEPARATOR"separator");
14758
14759 ctk_render_line (context, cr,
14760 cell_area.x,
14761 cell_area.y + cell_area.height / 2,
14762 cell_area.x + cell_area.width,
14763 cell_area.y + cell_area.height / 2);
14764
14765 ctk_style_context_restore (context);
14766 }
14767 else
14768 {
14769 _ctk_tree_view_column_cell_render (column,
14770 cr,
14771 &background_area,
14772 &cell_area,
14773 0, FALSE(0));
14774 }
14775 }
14776 cell_offset += ctk_tree_view_column_get_width (column);
14777 }
14778
14779 cairo_set_source_rgb (cr, 0, 0, 0);
14780 cairo_rectangle (cr,
14781 0.5, 0.5,
14782 bin_window_width + 1,
14783 background_area.height + 1);
14784 cairo_set_line_width (cr, 1.0);
14785 cairo_stroke (cr);
14786
14787 cairo_destroy (cr);
14788
14789 cairo_surface_set_device_offset (surface, 2, 2);
14790
14791 return surface;
14792}
14793
14794
14795/**
14796 * ctk_tree_view_set_destroy_count_func:
14797 * @tree_view: A #CtkTreeView
14798 * @func: (allow-none): Function to be called when a view row is destroyed, or %NULL
14799 * @data: (allow-none): User data to be passed to @func, or %NULL
14800 * @destroy: (allow-none): Destroy notifier for @data, or %NULL
14801 *
14802 * This function should almost never be used. It is meant for private use by
14803 * ATK for determining the number of visible children that are removed when the
14804 * user collapses a row, or a row is deleted.
14805 *
14806 * Deprecated: 3.4: Accessibility does not need the function anymore.
14807 **/
14808void
14809ctk_tree_view_set_destroy_count_func (CtkTreeView *tree_view,
14810 CtkTreeDestroyCountFunc func,
14811 gpointer data,
14812 GDestroyNotify destroy)
14813{
14814 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14815
14816 if (tree_view->priv->destroy_count_destroy)
14817 tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
14818
14819 tree_view->priv->destroy_count_func = func;
14820 tree_view->priv->destroy_count_data = data;
14821 tree_view->priv->destroy_count_destroy = destroy;
14822}
14823
14824
14825/*
14826 * Interactive search
14827 */
14828
14829/**
14830 * ctk_tree_view_set_enable_search:
14831 * @tree_view: A #CtkTreeView
14832 * @enable_search: %TRUE, if the user can search interactively
14833 *
14834 * If @enable_search is set, then the user can type in text to search through
14835 * the tree interactively (this is sometimes called "typeahead find").
14836 *
14837 * Note that even if this is %FALSE, the user can still initiate a search
14838 * using the “start-interactive-search” key binding.
14839 */
14840void
14841ctk_tree_view_set_enable_search (CtkTreeView *tree_view,
14842 gboolean enable_search)
14843{
14844 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14845
14846 enable_search = !!enable_search;
14847
14848 if (tree_view->priv->enable_search != enable_search)
14849 {
14850 tree_view->priv->enable_search = enable_search;
14851 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_ENABLE_SEARCH]);
14852 }
14853}
14854
14855/**
14856 * ctk_tree_view_get_enable_search:
14857 * @tree_view: A #CtkTreeView
14858 *
14859 * Returns whether or not the tree allows to start interactive searching
14860 * by typing in text.
14861 *
14862 * Returns: whether or not to let the user search interactively
14863 */
14864gboolean
14865ctk_tree_view_get_enable_search (CtkTreeView *tree_view)
14866{
14867 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
14868
14869 return tree_view->priv->enable_search;
14870}
14871
14872
14873/**
14874 * ctk_tree_view_get_search_column:
14875 * @tree_view: A #CtkTreeView
14876 *
14877 * Gets the column searched on by the interactive search code.
14878 *
14879 * Returns: the column the interactive search code searches in.
14880 */
14881gint
14882ctk_tree_view_get_search_column (CtkTreeView *tree_view)
14883{
14884 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (-1); } } while (
0)
;
14885
14886 return (tree_view->priv->search_column);
14887}
14888
14889/**
14890 * ctk_tree_view_set_search_column:
14891 * @tree_view: A #CtkTreeView
14892 * @column: the column of the model to search in, or -1 to disable searching
14893 *
14894 * Sets @column as the column where the interactive search code should
14895 * search in for the current model.
14896 *
14897 * If the search column is set, users can use the “start-interactive-search”
14898 * key binding to bring up search popup. The enable-search property controls
14899 * whether simply typing text will also start an interactive search.
14900 *
14901 * Note that @column refers to a column of the current model. The search
14902 * column is reset to -1 when the model is changed.
14903 */
14904void
14905ctk_tree_view_set_search_column (CtkTreeView *tree_view,
14906 gint column)
14907{
14908 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14909 g_return_if_fail (column >= -1)do { if ((column >= -1)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "column >= -1"); return
; } } while (0)
;
14910
14911 if (tree_view->priv->search_column == column)
14912 return;
14913
14914 tree_view->priv->search_column = column;
14915 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_SEARCH_COLUMN]);
14916}
14917
14918/**
14919 * ctk_tree_view_get_search_equal_func: (skip)
14920 * @tree_view: A #CtkTreeView
14921 *
14922 * Returns the compare function currently in use.
14923 *
14924 * Returns: the currently used compare function for the search code.
14925 */
14926
14927CtkTreeViewSearchEqualFunc
14928ctk_tree_view_get_search_equal_func (CtkTreeView *tree_view)
14929{
14930 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
14931
14932 return tree_view->priv->search_equal_func;
14933}
14934
14935/**
14936 * ctk_tree_view_set_search_equal_func:
14937 * @tree_view: A #CtkTreeView
14938 * @search_equal_func: the compare function to use during the search
14939 * @search_user_data: (allow-none): user data to pass to @search_equal_func, or %NULL
14940 * @search_destroy: (allow-none): Destroy notifier for @search_user_data, or %NULL
14941 *
14942 * Sets the compare function for the interactive search capabilities; note
14943 * that somewhat like strcmp() returning 0 for equality
14944 * #CtkTreeViewSearchEqualFunc returns %FALSE on matches.
14945 **/
14946void
14947ctk_tree_view_set_search_equal_func (CtkTreeView *tree_view,
14948 CtkTreeViewSearchEqualFunc search_equal_func,
14949 gpointer search_user_data,
14950 GDestroyNotify search_destroy)
14951{
14952 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
14953 g_return_if_fail (search_equal_func != NULL)do { if ((search_equal_func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "search_equal_func != NULL"
); return; } } while (0)
;
14954
14955 if (tree_view->priv->search_destroy)
14956 tree_view->priv->search_destroy (tree_view->priv->search_user_data);
14957
14958 tree_view->priv->search_equal_func = search_equal_func;
14959 tree_view->priv->search_user_data = search_user_data;
14960 tree_view->priv->search_destroy = search_destroy;
14961 if (tree_view->priv->search_equal_func == NULL((void*)0))
14962 tree_view->priv->search_equal_func = ctk_tree_view_search_equal_func;
14963}
14964
14965/**
14966 * ctk_tree_view_get_search_entry:
14967 * @tree_view: A #CtkTreeView
14968 *
14969 * Returns the #CtkEntry which is currently in use as interactive search
14970 * entry for @tree_view. In case the built-in entry is being used, %NULL
14971 * will be returned.
14972 *
14973 * Returns: (transfer none): the entry currently in use as search entry.
14974 *
14975 * Since: 2.10
14976 */
14977CtkEntry *
14978ctk_tree_view_get_search_entry (CtkTreeView *tree_view)
14979{
14980 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
14981
14982 if (tree_view->priv->search_custom_entry_set)
14983 return CTK_ENTRY (tree_view->priv->search_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_entry_get_type
()))))))
;
14984
14985 return NULL((void*)0);
14986}
14987
14988/**
14989 * ctk_tree_view_set_search_entry:
14990 * @tree_view: A #CtkTreeView
14991 * @entry: (allow-none): the entry the interactive search code of @tree_view should use or %NULL
14992 *
14993 * Sets the entry which the interactive search code will use for this
14994 * @tree_view. This is useful when you want to provide a search entry
14995 * in our interface at all time at a fixed position. Passing %NULL for
14996 * @entry will make the interactive search code use the built-in popup
14997 * entry again.
14998 *
14999 * Since: 2.10
15000 */
15001void
15002ctk_tree_view_set_search_entry (CtkTreeView *tree_view,
15003 CtkEntry *entry)
15004{
15005 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
15006 g_return_if_fail (entry == NULL || CTK_IS_ENTRY (entry))do { if ((entry == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((entry)); GType __t = ((ctk_entry_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "entry == NULL || CTK_IS_ENTRY (entry)")
; return; } } while (0)
;
15007
15008 if (tree_view->priv->search_custom_entry_set)
15009 {
15010 if (tree_view->priv->search_entry_changed_id)
15011 {
15012 g_signal_handler_disconnect (tree_view->priv->search_entry,
15013 tree_view->priv->search_entry_changed_id);
15014 tree_view->priv->search_entry_changed_id = 0;
15015 }
15016 g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view))
15017 G_CALLBACK (ctk_tree_view_search_key_press_event),g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view))
15018 tree_view)g_signal_handlers_disconnect_matched ((tree_view->priv->
search_entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view))
;
15019
15020 g_object_unref (tree_view->priv->search_entry);
15021 }
15022 else if (tree_view->priv->search_window)
15023 {
15024 ctk_tree_view_destroy_search_window (tree_view);
15025 }
15026
15027 if (entry)
15028 {
15029 tree_view->priv->search_entry = CTK_WIDGET (g_object_ref (entry))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((__typeof__ (entry)) (g_object_ref) (entry)))), ((ctk_widget_get_type
()))))))
;
15030 tree_view->priv->search_custom_entry_set = TRUE(!(0));
15031
15032 if (tree_view->priv->search_entry_changed_id == 0)
15033 {
15034 tree_view->priv->search_entry_changed_id =
15035 g_signal_connect (tree_view->priv->search_entry, "changed",g_signal_connect_data ((tree_view->priv->search_entry),
("changed"), (((GCallback) (ctk_tree_view_search_init))), (tree_view
), ((void*)0), (GConnectFlags) 0)
15036 G_CALLBACK (ctk_tree_view_search_init),g_signal_connect_data ((tree_view->priv->search_entry),
("changed"), (((GCallback) (ctk_tree_view_search_init))), (tree_view
), ((void*)0), (GConnectFlags) 0)
15037 tree_view)g_signal_connect_data ((tree_view->priv->search_entry),
("changed"), (((GCallback) (ctk_tree_view_search_init))), (tree_view
), ((void*)0), (GConnectFlags) 0)
;
15038 }
15039
15040 g_signal_connect (tree_view->priv->search_entry, "key-press-event",g_signal_connect_data ((tree_view->priv->search_entry),
("key-press-event"), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
15041 G_CALLBACK (ctk_tree_view_search_key_press_event),g_signal_connect_data ((tree_view->priv->search_entry),
("key-press-event"), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
15042 tree_view)g_signal_connect_data ((tree_view->priv->search_entry),
("key-press-event"), (((GCallback) (ctk_tree_view_search_key_press_event
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
15043
15044 ctk_tree_view_search_init (tree_view->priv->search_entry, tree_view);
15045 }
15046 else
15047 {
15048 tree_view->priv->search_entry = NULL((void*)0);
15049 tree_view->priv->search_custom_entry_set = FALSE(0);
15050 }
15051}
15052
15053/**
15054 * ctk_tree_view_set_search_position_func:
15055 * @tree_view: A #CtkTreeView
15056 * @func: (allow-none): the function to use to position the search dialog, or %NULL
15057 * to use the default search position function
15058 * @data: (allow-none): user data to pass to @func, or %NULL
15059 * @destroy: (allow-none): Destroy notifier for @data, or %NULL
15060 *
15061 * Sets the function to use when positioning the search dialog.
15062 *
15063 * Since: 2.10
15064 **/
15065void
15066ctk_tree_view_set_search_position_func (CtkTreeView *tree_view,
15067 CtkTreeViewSearchPositionFunc func,
15068 gpointer user_data,
15069 GDestroyNotify destroy)
15070{
15071 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
15072
15073 if (tree_view->priv->search_position_destroy)
15074 tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
15075
15076 tree_view->priv->search_position_func = func;
15077 tree_view->priv->search_position_user_data = user_data;
15078 tree_view->priv->search_position_destroy = destroy;
15079 if (tree_view->priv->search_position_func == NULL((void*)0))
15080 tree_view->priv->search_position_func = ctk_tree_view_search_position_func;
15081}
15082
15083/**
15084 * ctk_tree_view_get_search_position_func: (skip)
15085 * @tree_view: A #CtkTreeView
15086 *
15087 * Returns the positioning function currently in use.
15088 *
15089 * Returns: the currently used function for positioning the search dialog.
15090 *
15091 * Since: 2.10
15092 */
15093CtkTreeViewSearchPositionFunc
15094ctk_tree_view_get_search_position_func (CtkTreeView *tree_view)
15095{
15096 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
15097
15098 return tree_view->priv->search_position_func;
15099}
15100
15101
15102static void
15103ctk_tree_view_search_window_hide (CtkWidget *search_window,
15104 CtkTreeView *tree_view,
15105 CdkDevice *device)
15106{
15107 if (tree_view->priv->disable_popdown)
15108 return;
15109
15110 if (tree_view->priv->search_entry_changed_id)
15111 {
15112 g_signal_handler_disconnect (tree_view->priv->search_entry,
15113 tree_view->priv->search_entry_changed_id);
15114 tree_view->priv->search_entry_changed_id = 0;
15115 }
15116 if (tree_view->priv->typeselect_flush_timeout)
15117 {
15118 g_source_remove (tree_view->priv->typeselect_flush_timeout);
15119 tree_view->priv->typeselect_flush_timeout = 0;
15120 }
15121
15122 if (ctk_widget_get_visible (search_window))
15123 {
15124 /* send focus-in event */
15125 send_focus_change (CTK_WIDGET (tree_view->priv->search_entry)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_widget_get_type
()))))))
, device, FALSE(0));
15126 ctk_widget_hide (search_window);
15127 ctk_entry_set_text (CTK_ENTRY (tree_view->priv->search_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_entry_get_type
()))))))
, "");
15128 send_focus_change (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, device, TRUE(!(0)));
15129 }
15130}
15131
15132static void
15133ctk_tree_view_search_position_func (CtkTreeView *tree_view,
15134 CtkWidget *search_window,
15135 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
15136{
15137 gint x, y;
15138 gint tree_x, tree_y;
15139 gint tree_width, tree_height;
15140 CdkDisplay *display;
15141 CdkMonitor *monitor;
15142 CdkRectangle workarea;
15143 CdkWindow *tree_window = ctk_widget_get_window (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
15144 CtkRequisition requisition;
15145
15146 ctk_widget_realize (search_window);
15147
15148 display = ctk_widget_get_display (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
15149 monitor = cdk_display_get_monitor_at_window (display, tree_window);
15150 cdk_monitor_get_workarea (monitor, &workarea);
15151
15152 cdk_window_get_origin (tree_window, &tree_x, &tree_y);
15153 tree_width = cdk_window_get_width (tree_window);
15154 tree_height = cdk_window_get_height (tree_window);
15155 ctk_widget_get_preferred_size (search_window, &requisition, NULL((void*)0));
15156
15157 if (tree_x + tree_width > workarea.x + workarea.width)
15158 x = workarea.x + workarea.width - requisition.width;
15159 else if (tree_x + tree_width - requisition.width < workarea.x)
15160 x = workarea.x;
15161 else
15162 x = tree_x + tree_width - requisition.width;
15163
15164 if (tree_y + tree_height + requisition.height > workarea.y + workarea.height)
15165 y = workarea.y + workarea.height - requisition.height;
15166 else if (tree_y + tree_height < workarea.y) /* isn't really possible ... */
15167 y = workarea.y;
15168 else
15169 y = tree_y + tree_height;
15170
15171 ctk_window_move (CTK_WINDOW (search_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((search_window)), ((ctk_window_get_type ()))))))
, x, y);
15172}
15173
15174static void
15175ctk_tree_view_search_disable_popdown (CtkEntry *entry G_GNUC_UNUSED__attribute__ ((__unused__)),
15176 CtkMenu *menu,
15177 gpointer data)
15178{
15179 CtkTreeView *tree_view = (CtkTreeView *)data;
15180
15181 tree_view->priv->disable_popdown = 1;
15182 g_signal_connect (menu, "hide",g_signal_connect_data ((menu), ("hide"), (((GCallback) (ctk_tree_view_search_enable_popdown
))), (data), ((void*)0), (GConnectFlags) 0)
15183 G_CALLBACK (ctk_tree_view_search_enable_popdown), data)g_signal_connect_data ((menu), ("hide"), (((GCallback) (ctk_tree_view_search_enable_popdown
))), (data), ((void*)0), (GConnectFlags) 0)
;
15184}
15185
15186/* Because we're visible but offscreen, we just set a flag in the preedit
15187 * callback.
15188 */
15189static void
15190ctk_tree_view_search_preedit_changed (CtkIMContext *im_context G_GNUC_UNUSED__attribute__ ((__unused__)),
15191 CtkTreeView *tree_view)
15192{
15193 tree_view->priv->imcontext_changed = 1;
15194 if (tree_view->priv->typeselect_flush_timeout)
15195 {
15196 g_source_remove (tree_view->priv->typeselect_flush_timeout);
15197 tree_view->priv->typeselect_flush_timeout =
15198 cdk_threads_add_timeout (CTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT5000,
15199 (GSourceFunc) ctk_tree_view_search_entry_flush_timeout,
15200 tree_view);
15201 g_source_set_name_by_id (tree_view->priv->typeselect_flush_timeout, "[ctk+] ctk_tree_view_search_entry_flush_timeout");
15202 }
15203
15204}
15205
15206static void
15207ctk_tree_view_search_commit (CtkIMContext *im_context G_GNUC_UNUSED__attribute__ ((__unused__)),
15208 gchar *buf G_GNUC_UNUSED__attribute__ ((__unused__)),
15209 CtkTreeView *tree_view)
15210{
15211 tree_view->priv->imcontext_changed = 1;
15212}
15213
15214static void
15215ctk_tree_view_search_activate (CtkEntry *entry G_GNUC_UNUSED__attribute__ ((__unused__)),
15216 CtkTreeView *tree_view)
15217{
15218 CtkTreePath *path;
15219
15220 ctk_tree_view_search_window_hide (tree_view->priv->search_window,
15221 tree_view,
15222 ctk_get_current_event_device ());
15223
15224 /* If we have a row selected and it's the cursor row, we activate
15225 * the row XXX */
15226 if (tree_view->priv->cursor_node &&
15227 CTK_RBNODE_FLAG_SET (tree_view->priv->cursor_node, CTK_RBNODE_IS_SELECTED)(tree_view->priv->cursor_node?(((tree_view->priv->
cursor_node->flags&CTK_RBNODE_IS_SELECTED)==CTK_RBNODE_IS_SELECTED
)?(!(0)):(0)):(0))
)
15228 {
15229 path = _ctk_tree_path_new_from_rbtree (tree_view->priv->cursor_tree,
15230 tree_view->priv->cursor_node);
15231
15232 ctk_tree_view_row_activated (tree_view, path, tree_view->priv->focus_column);
15233
15234 ctk_tree_path_free (path);
15235 }
15236}
15237
15238static gboolean
15239ctk_tree_view_real_search_enable_popdown (gpointer data)
15240{
15241 CtkTreeView *tree_view = (CtkTreeView *)data;
15242
15243 tree_view->priv->disable_popdown = 0;
15244
15245 return FALSE(0);
15246}
15247
15248static void
15249ctk_tree_view_search_enable_popdown (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
15250 gpointer data)
15251{
15252 guint id;
15253 id = cdk_threads_add_timeout_full (G_PRIORITY_HIGH-100, 200, ctk_tree_view_real_search_enable_popdown, g_object_ref (data)((__typeof__ (data)) (g_object_ref) (data)), g_object_unref);
15254 g_source_set_name_by_id (id, "[ctk+] ctk_tree_view_real_search_enable_popdown");
15255}
15256
15257static gboolean
15258ctk_tree_view_search_delete_event (CtkWidget *widget,
15259 CdkEventAny *event G_GNUC_UNUSED__attribute__ ((__unused__)),
15260 CtkTreeView *tree_view)
15261{
15262 g_return_val_if_fail (CTK_IS_WIDGET (widget), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return ((0)); } } while (0)
;
15263
15264 ctk_tree_view_search_window_hide (widget, tree_view, NULL((void*)0));
15265
15266 return TRUE(!(0));
15267}
15268
15269static gboolean
15270ctk_tree_view_search_button_press_event (CtkWidget *widget,
15271 CdkEventButton *event,
15272 CtkTreeView *tree_view)
15273{
15274 CdkDevice *keyb_device;
15275
15276 g_return_val_if_fail (CTK_IS_WIDGET (widget), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return ((0)); } } while (0)
;
15277
15278 keyb_device = cdk_device_get_associated_device (event->device);
15279 ctk_tree_view_search_window_hide (widget, tree_view, keyb_device);
15280
15281 return TRUE(!(0));
15282}
15283
15284static gboolean
15285ctk_tree_view_search_scroll_event (CtkWidget *widget,
15286 CdkEventScroll *event,
15287 CtkTreeView *tree_view)
15288{
15289 gboolean retval = FALSE(0);
15290
15291 if (event->direction == CDK_SCROLL_UP)
15292 {
15293 ctk_tree_view_search_move (widget, tree_view, TRUE(!(0)));
15294 retval = TRUE(!(0));
15295 }
15296 else if (event->direction == CDK_SCROLL_DOWN)
15297 {
15298 ctk_tree_view_search_move (widget, tree_view, FALSE(0));
15299 retval = TRUE(!(0));
15300 }
15301
15302 /* renew the flush timeout */
15303 if (retval && tree_view->priv->typeselect_flush_timeout
15304 && !tree_view->priv->search_custom_entry_set)
15305 {
15306 g_source_remove (tree_view->priv->typeselect_flush_timeout);
15307 tree_view->priv->typeselect_flush_timeout =
15308 cdk_threads_add_timeout (CTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT5000,
15309 (GSourceFunc) ctk_tree_view_search_entry_flush_timeout,
15310 tree_view);
15311 g_source_set_name_by_id (tree_view->priv->typeselect_flush_timeout, "[ctk+] ctk_tree_view_search_entry_flush_timeout");
15312 }
15313
15314 return retval;
15315}
15316
15317static gboolean
15318ctk_tree_view_search_key_press_event (CtkWidget *widget,
15319 CdkEventKey *event,
15320 CtkTreeView *tree_view)
15321{
15322 CdkModifierType default_accel;
15323 gboolean retval = FALSE(0);
15324
15325 g_return_val_if_fail (CTK_IS_WIDGET (widget), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return ((0)); } } while (0)
;
15326 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
15327
15328 /* close window and cancel the search */
15329 if (!tree_view->priv->search_custom_entry_set
15330 && ctk_tree_view_search_key_cancels_search (event->keyval))
15331 {
15332 ctk_tree_view_search_window_hide (widget, tree_view,
15333 cdk_event_get_device ((CdkEvent *) event));
15334 return TRUE(!(0));
15335 }
15336
15337 default_accel = ctk_widget_get_modifier_mask (widget,
15338 CDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR);
15339
15340 /* select previous matching iter */
15341 if (event->keyval == CDK_KEY_Up0xff52 || event->keyval == CDK_KEY_KP_Up0xff97)
15342 {
15343 if (!ctk_tree_view_search_move (widget, tree_view, TRUE(!(0))))
15344 ctk_widget_error_bell (widget);
15345
15346 retval = TRUE(!(0));
15347 }
15348
15349 if (((event->state & (default_accel | CDK_SHIFT_MASK)) == (default_accel | CDK_SHIFT_MASK))
15350 && (event->keyval == CDK_KEY_g0x067 || event->keyval == CDK_KEY_G0x047))
15351 {
15352 if (!ctk_tree_view_search_move (widget, tree_view, TRUE(!(0))))
15353 ctk_widget_error_bell (widget);
15354
15355 retval = TRUE(!(0));
15356 }
15357
15358 /* select next matching iter */
15359 if (event->keyval == CDK_KEY_Down0xff54 || event->keyval == CDK_KEY_KP_Down0xff99)
15360 {
15361 if (!ctk_tree_view_search_move (widget, tree_view, FALSE(0)))
15362 ctk_widget_error_bell (widget);
15363
15364 retval = TRUE(!(0));
15365 }
15366
15367 if (((event->state & (default_accel | CDK_SHIFT_MASK)) == default_accel)
15368 && (event->keyval == CDK_KEY_g0x067 || event->keyval == CDK_KEY_G0x047))
15369 {
15370 if (!ctk_tree_view_search_move (widget, tree_view, FALSE(0)))
15371 ctk_widget_error_bell (widget);
15372
15373 retval = TRUE(!(0));
15374 }
15375
15376 /* renew the flush timeout */
15377 if (retval && tree_view->priv->typeselect_flush_timeout
15378 && !tree_view->priv->search_custom_entry_set)
15379 {
15380 g_source_remove (tree_view->priv->typeselect_flush_timeout);
15381 tree_view->priv->typeselect_flush_timeout =
15382 cdk_threads_add_timeout (CTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT5000,
15383 (GSourceFunc) ctk_tree_view_search_entry_flush_timeout,
15384 tree_view);
15385 g_source_set_name_by_id (tree_view->priv->typeselect_flush_timeout, "[ctk+] ctk_tree_view_search_entry_flush_timeout");
15386 }
15387
15388 return retval;
15389}
15390
15391/* this function returns FALSE if there is a search string but
15392 * nothing was found, and TRUE otherwise.
15393 */
15394static gboolean
15395ctk_tree_view_search_move (CtkWidget *window G_GNUC_UNUSED__attribute__ ((__unused__)),
15396 CtkTreeView *tree_view,
15397 gboolean up)
15398{
15399 gboolean ret;
15400 gint len;
15401 gint count = 0;
15402 const gchar *text;
15403 CtkTreeIter iter;
15404 CtkTreeModel *model;
15405 CtkTreeSelection *selection;
15406
15407 text = ctk_entry_get_text (CTK_ENTRY (tree_view->priv->search_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view->priv->search_entry)), ((ctk_entry_get_type
()))))))
);
15408
15409 g_return_val_if_fail (text != NULL, FALSE)do { if ((text != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "text != NULL"); return (
(0)); } } while (0)
;
15410
15411 len = strlen (text);
15412
15413 if (up && tree_view->priv->selected_iter == 1)
15414 return len < 1;
15415
15416 if (len < 1)
15417 return TRUE(!(0));
15418
15419 model = ctk_tree_view_get_model (tree_view);
15420 selection = ctk_tree_view_get_selection (tree_view);
15421
15422 /* search */
15423 ctk_tree_selection_unselect_all (selection);
15424 if (!ctk_tree_model_get_iter_first (model, &iter))
15425 return TRUE(!(0));
15426
15427 ret = ctk_tree_view_search_iter (model, selection, &iter, text,
15428 &count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
15429
15430 if (ret)
15431 {
15432 /* found */
15433 tree_view->priv->selected_iter += up?(-1):(1);
15434 return TRUE(!(0));
15435 }
15436 else
15437 {
15438 /* return to old iter */
15439 count = 0;
15440 ctk_tree_model_get_iter_first (model, &iter);
15441 ctk_tree_view_search_iter (model, selection,
15442 &iter, text,
15443 &count, tree_view->priv->selected_iter);
15444 return FALSE(0);
15445 }
15446}
15447
15448static gboolean
15449ctk_tree_view_search_equal_func (CtkTreeModel *model,
15450 gint column,
15451 const gchar *key,
15452 CtkTreeIter *iter,
15453 gpointer search_data G_GNUC_UNUSED__attribute__ ((__unused__)))
15454{
15455 gboolean retval = TRUE(!(0));
15456 const gchar *str;
15457 gchar *normalized_string;
15458 gchar *normalized_key;
15459 gchar *case_normalized_string = NULL((void*)0);
15460 gchar *case_normalized_key = NULL((void*)0);
15461 GValue value = G_VALUE_INIT{ 0, { { 0 } } };
15462 GValue transformed = G_VALUE_INIT{ 0, { { 0 } } };
15463
15464 ctk_tree_model_get_value (model, iter, column, &value);
15465
15466 g_value_init (&transformed, G_TYPE_STRING((GType) ((16) << (2))));
15467
15468 if (!g_value_transform (&value, &transformed))
15469 {
15470 g_value_unset (&value);
15471 return TRUE(!(0));
15472 }
15473
15474 g_value_unset (&value);
15475
15476 str = g_value_get_string (&transformed);
15477 if (!str)
15478 {
15479 g_value_unset (&transformed);
15480 return TRUE(!(0));
15481 }
15482
15483 normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
15484 normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
15485
15486 if (normalized_string && normalized_key)
15487 {
15488 case_normalized_string = g_utf8_casefold (normalized_string, -1);
15489 case_normalized_key = g_utf8_casefold (normalized_key, -1);
15490
15491 if (strncmp (case_normalized_key, case_normalized_string, strlen (case_normalized_key)) == 0)
15492 retval = FALSE(0);
15493 }
15494
15495 g_value_unset (&transformed);
15496 g_free (normalized_key);
15497 g_free (normalized_string);
15498 g_free (case_normalized_key);
15499 g_free (case_normalized_string);
15500
15501 return retval;
15502}
15503
15504static gboolean
15505ctk_tree_view_search_iter (CtkTreeModel *model,
15506 CtkTreeSelection *selection,
15507 CtkTreeIter *iter,
15508 const gchar *text,
15509 gint *count,
15510 gint n)
15511{
15512 CtkRBTree *tree = NULL((void*)0);
15513 CtkRBNode *node = NULL((void*)0);
15514 CtkTreePath *path;
15515
15516 CtkTreeView *tree_view = ctk_tree_selection_get_tree_view (selection);
15517
15518 path = ctk_tree_model_get_path (model, iter);
15519 _ctk_tree_view_find_node (tree_view, path, &tree, &node);
15520
15521 do
15522 {
15523 if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter, tree_view->priv->search_user_data))
15524 {
15525 (*count)++;
15526 if (*count == n)
15527 {
15528 ctk_tree_view_scroll_to_cell (tree_view, path, NULL((void*)0),
15529 TRUE(!(0)), 0.5, 0.0);
15530 ctk_tree_selection_select_iter (selection, iter);
15531 ctk_tree_view_real_set_cursor (tree_view, path, CLAMP_NODE);
15532
15533 if (path)
15534 ctk_tree_path_free (path);
15535
15536 return TRUE(!(0));
15537 }
15538 }
15539
15540 if (node->children)
15541 {
15542 gboolean has_child;
15543 CtkTreeIter tmp;
15544
15545 tree = node->children;
15546 node = _ctk_rbtree_first (tree);
15547
15548 tmp = *iter;
15549 has_child = ctk_tree_model_iter_children (model, iter, &tmp);
15550 ctk_tree_path_down (path);
15551
15552 /* sanity check */
15553 TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE)do{ if (!(has_child)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "15553", ((const char
*) (__func__)), "has_child"); return (0); }; }while (0)
;
15554 }
15555 else
15556 {
15557 gboolean done = FALSE(0);
15558
15559 do
15560 {
15561 node = _ctk_rbtree_next (tree, node);
15562
15563 if (node)
15564 {
15565 gboolean has_next;
15566
15567 has_next = ctk_tree_model_iter_next (model, iter);
15568
15569 done = TRUE(!(0));
15570 ctk_tree_path_next (path);
15571
15572 /* sanity check */
15573 TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE)do{ if (!(has_next)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "15573", ((const char
*) (__func__)), "has_next"); return (0); }; }while (0)
;
15574 }
15575 else
15576 {
15577 gboolean has_parent;
15578 CtkTreeIter tmp_iter = *iter;
15579
15580 node = tree->parent_node;
15581 tree = tree->parent_tree;
15582
15583 if (!tree)
15584 {
15585 if (path)
15586 ctk_tree_path_free (path);
15587
15588 /* we've run out of tree, done with this func */
15589 return FALSE(0);
15590 }
15591
15592 has_parent = ctk_tree_model_iter_parent (model,
15593 iter,
15594 &tmp_iter);
15595 ctk_tree_path_up (path);
15596
15597 /* sanity check */
15598 TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE)do{ if (!(has_parent)) { g_log ("Ctk", G_LOG_LEVEL_CRITICAL, "%s (%s): assertion `%s' failed.\n"
"There is a disparity between the internal view of the CtkTreeView,\n"
"and the CtkTreeModel. This generally means that the model has changed\n"
"without letting the view know. Any display from now on is likely to\n"
"be incorrect.\n", "ctktreeview.c" ":" "15598", ((const char
*) (__func__)), "has_parent"); return (0); }; }while (0)
;
15599 }
15600 }
15601 while (!done);
15602 }
15603 }
15604 while (1);
15605
15606 return FALSE(0);
15607}
15608
15609static void
15610ctk_tree_view_search_init (CtkWidget *entry,
15611 CtkTreeView *tree_view)
15612{
15613 gint ret;
15614 gint count = 0;
15615 const gchar *text;
15616 CtkTreeIter iter;
15617 CtkTreeModel *model;
15618 CtkTreeSelection *selection;
15619
15620 g_return_if_fail (CTK_IS_ENTRY (entry))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((entry)); GType __t = ((ctk_entry_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_ENTRY (entry)"); return; } } while (0)
;
15621 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
15622
15623 text = ctk_entry_get_text (CTK_ENTRY (entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((entry)), ((ctk_entry_get_type ()))))))
);
15624
15625 model = ctk_tree_view_get_model (tree_view);
15626 selection = ctk_tree_view_get_selection (tree_view);
15627
15628 /* search */
15629 ctk_tree_selection_unselect_all (selection);
15630 if (tree_view->priv->typeselect_flush_timeout
15631 && !tree_view->priv->search_custom_entry_set)
15632 {
15633 g_source_remove (tree_view->priv->typeselect_flush_timeout);
15634 tree_view->priv->typeselect_flush_timeout =
15635 cdk_threads_add_timeout (CTK_TREE_VIEW_SEARCH_DIALOG_TIMEOUT5000,
15636 (GSourceFunc) ctk_tree_view_search_entry_flush_timeout,
15637 tree_view);
15638 g_source_set_name_by_id (tree_view->priv->typeselect_flush_timeout, "[ctk+] ctk_tree_view_search_entry_flush_timeout");
15639 }
15640
15641 if (*text == '\0')
15642 return;
15643
15644 if (!ctk_tree_model_get_iter_first (model, &iter))
15645 return;
15646
15647 ret = ctk_tree_view_search_iter (model, selection,
15648 &iter, text,
15649 &count, 1);
15650
15651 if (ret)
15652 tree_view->priv->selected_iter = 1;
15653}
15654
15655void
15656_ctk_tree_view_remove_editable (CtkTreeView *tree_view,
15657 CtkTreeViewColumn *column,
15658 CtkCellEditable *cell_editable)
15659{
15660 if (tree_view->priv->edited_column == NULL((void*)0))
15661 return;
15662
15663 g_return_if_fail (column == tree_view->priv->edited_column)do { if ((column == tree_view->priv->edited_column)) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "column == tree_view->priv->edited_column"); return
; } } while (0)
;
15664
15665 tree_view->priv->edited_column = NULL((void*)0);
15666
15667 if (ctk_widget_has_focus (CTK_WIDGET (cell_editable)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cell_editable)), ((ctk_widget_get_type ()))))))
))
15668 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
15669
15670 ctk_container_remove (CTK_CONTAINER (tree_view)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_container_get_type ()))))))
,
15671 CTK_WIDGET (cell_editable)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cell_editable)), ((ctk_widget_get_type ()))))))
);
15672
15673 /* FIXME should only redraw a single node */
15674 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
15675}
15676
15677static gboolean
15678ctk_tree_view_start_editing (CtkTreeView *tree_view,
15679 CtkTreePath *cursor_path,
15680 gboolean edit_only)
15681{
15682 CtkTreeIter iter;
15683 CdkRectangle cell_area;
15684 CtkTreeViewColumn *focus_column;
15685 guint flags = 0; /* can be 0, as the flags are primarily for rendering */
15686 gint retval = FALSE(0);
15687 CtkRBTree *cursor_tree;
15688 CtkRBNode *cursor_node;
15689
15690 g_assert (tree_view->priv->focus_column)do { if (tree_view->priv->focus_column) ; else g_assertion_message_expr
("Ctk", "ctktreeview.c", 15690, ((const char*) (__func__)), "tree_view->priv->focus_column"
); } while (0)
;
15691 focus_column = tree_view->priv->focus_column;
15692
15693 if (!ctk_widget_get_realized (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
))
15694 return FALSE(0);
15695
15696 if (_ctk_tree_view_find_node (tree_view, cursor_path, &cursor_tree, &cursor_node) ||
15697 cursor_node == NULL((void*)0))
15698 return FALSE(0);
15699
15700 ctk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
15701
15702 validate_row (tree_view, cursor_tree, cursor_node, &iter, cursor_path);
15703
15704 ctk_tree_view_column_cell_set_cell_data (focus_column,
15705 tree_view->priv->model,
15706 &iter,
15707 CTK_RBNODE_FLAG_SET (cursor_node, CTK_RBNODE_IS_PARENT)(cursor_node?(((cursor_node->flags&CTK_RBNODE_IS_PARENT
)==CTK_RBNODE_IS_PARENT)?(!(0)):(0)):(0))
,
15708 cursor_node->children ? TRUE(!(0)) : FALSE(0));
15709 ctk_tree_view_get_cell_area (tree_view,
15710 cursor_path,
15711 focus_column,
15712 &cell_area);
15713
15714 if (ctk_cell_area_activate (ctk_cell_layout_get_area (CTK_CELL_LAYOUT (focus_column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((focus_column)), ((ctk_cell_layout_get_type ()))))))
),
15715 _ctk_tree_view_column_get_context (focus_column),
15716 CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
,
15717 &cell_area,
15718 flags, edit_only))
15719 retval = TRUE(!(0));
15720
15721 return retval;
15722}
15723
15724void
15725_ctk_tree_view_add_editable (CtkTreeView *tree_view,
15726 CtkTreeViewColumn *column,
15727 CtkTreePath *path,
15728 CtkCellEditable *cell_editable,
15729 CdkRectangle *cell_area)
15730{
15731 CdkRectangle full_area;
15732 CtkBorder border;
15733
15734 tree_view->priv->edited_column = column;
15735
15736 ctk_tree_view_real_set_cursor (tree_view, path, CLAMP_NODE);
15737
15738 tree_view->priv->draw_keyfocus = TRUE(!(0));
15739
15740 ctk_tree_view_get_cell_area (tree_view, path, column, &full_area);
15741 border.left = cell_area->x - full_area.x;
15742 border.top = cell_area->y - full_area.y;
15743 border.right = (full_area.x + full_area.width) - (cell_area->x + cell_area->width);
15744 border.bottom = (full_area.y + full_area.height) - (cell_area->y + cell_area->height);
15745
15746 ctk_tree_view_put (tree_view,
15747 CTK_WIDGET (cell_editable)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cell_editable)), ((ctk_widget_get_type ()))))))
,
15748 path,
15749 column,
15750 &border);
15751}
15752
15753static void
15754ctk_tree_view_stop_editing (CtkTreeView *tree_view,
15755 gboolean cancel_editing)
15756{
15757 CtkTreeViewColumn *column;
15758
15759 if (tree_view->priv->edited_column == NULL((void*)0))
15760 return;
15761
15762 /*
15763 * This is very evil. We need to do this, because
15764 * ctk_cell_editable_editing_done may trigger ctk_tree_view_row_changed
15765 * later on. If ctk_tree_view_row_changed notices
15766 * tree_view->priv->edited_column != NULL, it'll call
15767 * ctk_tree_view_stop_editing again. Bad things will happen then.
15768 *
15769 * Please read that again if you intend to modify anything here.
15770 */
15771
15772 column = tree_view->priv->edited_column;
15773 ctk_cell_area_stop_editing (ctk_cell_layout_get_area (CTK_CELL_LAYOUT (column)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((column)), ((ctk_cell_layout_get_type ()))))))
), cancel_editing);
15774 tree_view->priv->edited_column = NULL((void*)0);
15775}
15776
15777
15778/**
15779 * ctk_tree_view_set_hover_selection:
15780 * @tree_view: a #CtkTreeView
15781 * @hover: %TRUE to enable hover selection mode
15782 *
15783 * Enables or disables the hover selection mode of @tree_view.
15784 * Hover selection makes the selected row follow the pointer.
15785 * Currently, this works only for the selection modes
15786 * %CTK_SELECTION_SINGLE and %CTK_SELECTION_BROWSE.
15787 *
15788 * Since: 2.6
15789 **/
15790void
15791ctk_tree_view_set_hover_selection (CtkTreeView *tree_view,
15792 gboolean hover)
15793{
15794 hover = hover != FALSE(0);
15795
15796 if (hover != tree_view->priv->hover_selection)
15797 {
15798 tree_view->priv->hover_selection = hover;
15799
15800 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_HOVER_SELECTION]);
15801 }
15802}
15803
15804/**
15805 * ctk_tree_view_get_hover_selection:
15806 * @tree_view: a #CtkTreeView
15807 *
15808 * Returns whether hover selection mode is turned on for @tree_view.
15809 *
15810 * Returns: %TRUE if @tree_view is in hover selection mode
15811 *
15812 * Since: 2.6
15813 **/
15814gboolean
15815ctk_tree_view_get_hover_selection (CtkTreeView *tree_view)
15816{
15817 return tree_view->priv->hover_selection;
15818}
15819
15820/**
15821 * ctk_tree_view_set_hover_expand:
15822 * @tree_view: a #CtkTreeView
15823 * @expand: %TRUE to enable hover selection mode
15824 *
15825 * Enables or disables the hover expansion mode of @tree_view.
15826 * Hover expansion makes rows expand or collapse if the pointer
15827 * moves over them.
15828 *
15829 * Since: 2.6
15830 **/
15831void
15832ctk_tree_view_set_hover_expand (CtkTreeView *tree_view,
15833 gboolean expand)
15834{
15835 expand = expand != FALSE(0);
15836
15837 if (expand != tree_view->priv->hover_expand)
15838 {
15839 tree_view->priv->hover_expand = expand;
15840
15841 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_HOVER_EXPAND]);
15842 }
15843}
15844
15845/**
15846 * ctk_tree_view_get_hover_expand:
15847 * @tree_view: a #CtkTreeView
15848 *
15849 * Returns whether hover expansion mode is turned on for @tree_view.
15850 *
15851 * Returns: %TRUE if @tree_view is in hover expansion mode
15852 *
15853 * Since: 2.6
15854 **/
15855gboolean
15856ctk_tree_view_get_hover_expand (CtkTreeView *tree_view)
15857{
15858 return tree_view->priv->hover_expand;
15859}
15860
15861/**
15862 * ctk_tree_view_set_rubber_banding:
15863 * @tree_view: a #CtkTreeView
15864 * @enable: %TRUE to enable rubber banding
15865 *
15866 * Enables or disables rubber banding in @tree_view. If the selection mode
15867 * is #CTK_SELECTION_MULTIPLE, rubber banding will allow the user to select
15868 * multiple rows by dragging the mouse.
15869 *
15870 * Since: 2.10
15871 **/
15872void
15873ctk_tree_view_set_rubber_banding (CtkTreeView *tree_view,
15874 gboolean enable)
15875{
15876 enable = enable != FALSE(0);
15877
15878 if (enable != tree_view->priv->rubber_banding_enable)
15879 {
15880 tree_view->priv->rubber_banding_enable = enable;
15881
15882 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_RUBBER_BANDING]);
15883 }
15884}
15885
15886/**
15887 * ctk_tree_view_get_rubber_banding:
15888 * @tree_view: a #CtkTreeView
15889 *
15890 * Returns whether rubber banding is turned on for @tree_view. If the
15891 * selection mode is #CTK_SELECTION_MULTIPLE, rubber banding will allow the
15892 * user to select multiple rows by dragging the mouse.
15893 *
15894 * Returns: %TRUE if rubber banding in @tree_view is enabled.
15895 *
15896 * Since: 2.10
15897 **/
15898gboolean
15899ctk_tree_view_get_rubber_banding (CtkTreeView *tree_view)
15900{
15901 return tree_view->priv->rubber_banding_enable;
15902}
15903
15904/**
15905 * ctk_tree_view_is_rubber_banding_active:
15906 * @tree_view: a #CtkTreeView
15907 *
15908 * Returns whether a rubber banding operation is currently being done
15909 * in @tree_view.
15910 *
15911 * Returns: %TRUE if a rubber banding operation is currently being
15912 * done in @tree_view.
15913 *
15914 * Since: 2.12
15915 **/
15916gboolean
15917ctk_tree_view_is_rubber_banding_active (CtkTreeView *tree_view)
15918{
15919 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
15920
15921 if (tree_view->priv->rubber_banding_enable
15922 && tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
15923 return TRUE(!(0));
15924
15925 return FALSE(0);
15926}
15927
15928/**
15929 * ctk_tree_view_get_row_separator_func: (skip)
15930 * @tree_view: a #CtkTreeView
15931 *
15932 * Returns the current row separator function.
15933 *
15934 * Returns: the current row separator function.
15935 *
15936 * Since: 2.6
15937 **/
15938CtkTreeViewRowSeparatorFunc
15939ctk_tree_view_get_row_separator_func (CtkTreeView *tree_view)
15940{
15941 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (((void*)0)); } }
while (0)
;
15942
15943 return tree_view->priv->row_separator_func;
15944}
15945
15946/**
15947 * ctk_tree_view_set_row_separator_func:
15948 * @tree_view: a #CtkTreeView
15949 * @func: (allow-none): a #CtkTreeViewRowSeparatorFunc
15950 * @data: (allow-none): user data to pass to @func, or %NULL
15951 * @destroy: (allow-none): destroy notifier for @data, or %NULL
15952 *
15953 * Sets the row separator function, which is used to determine
15954 * whether a row should be drawn as a separator. If the row separator
15955 * function is %NULL, no separators are drawn. This is the default value.
15956 *
15957 * Since: 2.6
15958 **/
15959void
15960ctk_tree_view_set_row_separator_func (CtkTreeView *tree_view,
15961 CtkTreeViewRowSeparatorFunc func,
15962 gpointer data,
15963 GDestroyNotify destroy)
15964{
15965 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
15966
15967 if (tree_view->priv->row_separator_destroy)
15968 tree_view->priv->row_separator_destroy (tree_view->priv->row_separator_data);
15969
15970 tree_view->priv->row_separator_func = func;
15971 tree_view->priv->row_separator_data = data;
15972 tree_view->priv->row_separator_destroy = destroy;
15973
15974 /* Have the tree recalculate heights */
15975 _ctk_rbtree_mark_invalid (tree_view->priv->tree);
15976 ctk_widget_queue_resize (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
15977}
15978
15979/**
15980 * ctk_tree_view_get_grid_lines:
15981 * @tree_view: a #CtkTreeView
15982 *
15983 * Returns which grid lines are enabled in @tree_view.
15984 *
15985 * Returns: a #CtkTreeViewGridLines value indicating which grid lines
15986 * are enabled.
15987 *
15988 * Since: 2.10
15989 */
15990CtkTreeViewGridLines
15991ctk_tree_view_get_grid_lines (CtkTreeView *tree_view)
15992{
15993 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (0); } } while (0
)
;
15994
15995 return tree_view->priv->grid_lines;
15996}
15997
15998/**
15999 * ctk_tree_view_set_grid_lines:
16000 * @tree_view: a #CtkTreeView
16001 * @grid_lines: a #CtkTreeViewGridLines value indicating which grid lines to
16002 * enable.
16003 *
16004 * Sets which grid lines to draw in @tree_view.
16005 *
16006 * Since: 2.10
16007 */
16008void
16009ctk_tree_view_set_grid_lines (CtkTreeView *tree_view,
16010 CtkTreeViewGridLines grid_lines)
16011{
16012 CtkTreeViewPrivate *priv;
16013 CtkWidget *widget;
16014 CtkTreeViewGridLines old_grid_lines;
16015
16016 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
16017
16018 priv = tree_view->priv;
16019 widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
16020
16021 old_grid_lines = priv->grid_lines;
16022 priv->grid_lines = grid_lines;
16023
16024 if (ctk_widget_get_realized (widget))
16025 {
16026 if (grid_lines == CTK_TREE_VIEW_GRID_LINES_NONE &&
16027 priv->grid_line_width)
16028 {
16029 priv->grid_line_width = 0;
16030 }
16031
16032 if (grid_lines != CTK_TREE_VIEW_GRID_LINES_NONE &&
16033 !priv->grid_line_width)
16034 {
16035 gint8 *dash_list;
16036
16037 ctk_widget_style_get (widget,
16038 "grid-line-width", &priv->grid_line_width,
16039 "grid-line-pattern", (gchar *)&dash_list,
16040 NULL((void*)0));
16041
16042 if (dash_list)
16043 {
16044 priv->grid_line_dashes[0] = dash_list[0];
16045 if (dash_list[0])
16046 priv->grid_line_dashes[1] = dash_list[1];
16047
16048 g_free (dash_list);
16049 }
16050 else
16051 {
16052 priv->grid_line_dashes[0] = 1;
16053 priv->grid_line_dashes[1] = 1;
16054 }
16055 }
16056 }
16057
16058 if (old_grid_lines != grid_lines)
16059 {
16060 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
16061
16062 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_ENABLE_GRID_LINES]);
16063 }
16064}
16065
16066/**
16067 * ctk_tree_view_get_enable_tree_lines:
16068 * @tree_view: a #CtkTreeView.
16069 *
16070 * Returns whether or not tree lines are drawn in @tree_view.
16071 *
16072 * Returns: %TRUE if tree lines are drawn in @tree_view, %FALSE
16073 * otherwise.
16074 *
16075 * Since: 2.10
16076 */
16077gboolean
16078ctk_tree_view_get_enable_tree_lines (CtkTreeView *tree_view)
16079{
16080 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
16081
16082 return tree_view->priv->tree_lines_enabled;
16083}
16084
16085/**
16086 * ctk_tree_view_set_enable_tree_lines:
16087 * @tree_view: a #CtkTreeView
16088 * @enabled: %TRUE to enable tree line drawing, %FALSE otherwise.
16089 *
16090 * Sets whether to draw lines interconnecting the expanders in @tree_view.
16091 * This does not have any visible effects for lists.
16092 *
16093 * Since: 2.10
16094 */
16095void
16096ctk_tree_view_set_enable_tree_lines (CtkTreeView *tree_view,
16097 gboolean enabled)
16098{
16099 CtkTreeViewPrivate *priv;
16100 CtkWidget *widget;
16101 gboolean was_enabled;
16102
16103 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
16104
16105 enabled = enabled != FALSE(0);
16106
16107 priv = tree_view->priv;
16108 widget = CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
;
16109
16110 was_enabled = priv->tree_lines_enabled;
16111
16112 priv->tree_lines_enabled = enabled;
16113
16114 if (ctk_widget_get_realized (widget))
16115 {
16116 if (!enabled && priv->tree_line_width)
16117 {
16118 priv->tree_line_width = 0;
16119 }
16120
16121 if (enabled && !priv->tree_line_width)
16122 {
16123 gint8 *dash_list;
16124 ctk_widget_style_get (widget,
16125 "tree-line-width", &priv->tree_line_width,
16126 "tree-line-pattern", (gchar *)&dash_list,
16127 NULL((void*)0));
16128
16129 if (dash_list)
16130 {
16131 priv->tree_line_dashes[0] = dash_list[0];
16132 if (dash_list[0])
16133 priv->tree_line_dashes[1] = dash_list[1];
16134
16135 g_free (dash_list);
16136 }
16137 else
16138 {
16139 priv->tree_line_dashes[0] = 1;
16140 priv->tree_line_dashes[1] = 1;
16141 }
16142 }
16143 }
16144
16145 if (was_enabled != enabled)
16146 {
16147 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
16148
16149 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_ENABLE_TREE_LINES]);
16150 }
16151}
16152
16153
16154/**
16155 * ctk_tree_view_set_show_expanders:
16156 * @tree_view: a #CtkTreeView
16157 * @enabled: %TRUE to enable expander drawing, %FALSE otherwise.
16158 *
16159 * Sets whether to draw and enable expanders and indent child rows in
16160 * @tree_view. When disabled there will be no expanders visible in trees
16161 * and there will be no way to expand and collapse rows by default. Also
16162 * note that hiding the expanders will disable the default indentation. You
16163 * can set a custom indentation in this case using
16164 * ctk_tree_view_set_level_indentation().
16165 * This does not have any visible effects for lists.
16166 *
16167 * Since: 2.12
16168 */
16169void
16170ctk_tree_view_set_show_expanders (CtkTreeView *tree_view,
16171 gboolean enabled)
16172{
16173 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
16174
16175 enabled = enabled != FALSE(0);
16176 if (tree_view->priv->show_expanders != enabled)
16177 {
16178 tree_view->priv->show_expanders = enabled;
16179 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
16180 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_SHOW_EXPANDERS]);
16181 }
16182}
16183
16184/**
16185 * ctk_tree_view_get_show_expanders:
16186 * @tree_view: a #CtkTreeView.
16187 *
16188 * Returns whether or not expanders are drawn in @tree_view.
16189 *
16190 * Returns: %TRUE if expanders are drawn in @tree_view, %FALSE
16191 * otherwise.
16192 *
16193 * Since: 2.12
16194 */
16195gboolean
16196ctk_tree_view_get_show_expanders (CtkTreeView *tree_view)
16197{
16198 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
16199
16200 return tree_view->priv->show_expanders;
16201}
16202
16203/**
16204 * ctk_tree_view_set_level_indentation:
16205 * @tree_view: a #CtkTreeView
16206 * @indentation: the amount, in pixels, of extra indentation in @tree_view.
16207 *
16208 * Sets the amount of extra indentation for child levels to use in @tree_view
16209 * in addition to the default indentation. The value should be specified in
16210 * pixels, a value of 0 disables this feature and in this case only the default
16211 * indentation will be used.
16212 * This does not have any visible effects for lists.
16213 *
16214 * Since: 2.12
16215 */
16216void
16217ctk_tree_view_set_level_indentation (CtkTreeView *tree_view,
16218 gint indentation)
16219{
16220 tree_view->priv->level_indentation = indentation;
16221
16222 ctk_widget_queue_draw (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
16223}
16224
16225/**
16226 * ctk_tree_view_get_level_indentation:
16227 * @tree_view: a #CtkTreeView.
16228 *
16229 * Returns the amount, in pixels, of extra indentation for child levels
16230 * in @tree_view.
16231 *
16232 * Returns: the amount of extra indentation for child levels in
16233 * @tree_view. A return value of 0 means that this feature is disabled.
16234 *
16235 * Since: 2.12
16236 */
16237gint
16238ctk_tree_view_get_level_indentation (CtkTreeView *tree_view)
16239{
16240 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (0); } } while (0
)
;
16241
16242 return tree_view->priv->level_indentation;
16243}
16244
16245/**
16246 * ctk_tree_view_set_tooltip_row:
16247 * @tree_view: a #CtkTreeView
16248 * @tooltip: a #CtkTooltip
16249 * @path: a #CtkTreePath
16250 *
16251 * Sets the tip area of @tooltip to be the area covered by the row at @path.
16252 * See also ctk_tree_view_set_tooltip_column() for a simpler alternative.
16253 * See also ctk_tooltip_set_tip_area().
16254 *
16255 * Since: 2.12
16256 */
16257void
16258ctk_tree_view_set_tooltip_row (CtkTreeView *tree_view,
16259 CtkTooltip *tooltip,
16260 CtkTreePath *path)
16261{
16262 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
16263 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
16264
16265 ctk_tree_view_set_tooltip_cell (tree_view, tooltip, path, NULL((void*)0), NULL((void*)0));
16266}
16267
16268/**
16269 * ctk_tree_view_set_tooltip_cell:
16270 * @tree_view: a #CtkTreeView
16271 * @tooltip: a #CtkTooltip
16272 * @path: (allow-none): a #CtkTreePath or %NULL
16273 * @column: (allow-none): a #CtkTreeViewColumn or %NULL
16274 * @cell: (allow-none): a #CtkCellRenderer or %NULL
16275 *
16276 * Sets the tip area of @tooltip to the area @path, @column and @cell have
16277 * in common. For example if @path is %NULL and @column is set, the tip
16278 * area will be set to the full area covered by @column. See also
16279 * ctk_tooltip_set_tip_area().
16280 *
16281 * Note that if @path is not specified and @cell is set and part of a column
16282 * containing the expander, the tooltip might not show and hide at the correct
16283 * position. In such cases @path must be set to the current node under the
16284 * mouse cursor for this function to operate correctly.
16285 *
16286 * See also ctk_tree_view_set_tooltip_column() for a simpler alternative.
16287 *
16288 * Since: 2.12
16289 */
16290void
16291ctk_tree_view_set_tooltip_cell (CtkTreeView *tree_view,
16292 CtkTooltip *tooltip,
16293 CtkTreePath *path,
16294 CtkTreeViewColumn *column,
16295 CtkCellRenderer *cell)
16296{
16297 CtkAllocation allocation;
16298 CdkRectangle rect;
16299
16300 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
16301 g_return_if_fail (CTK_IS_TOOLTIP (tooltip))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tooltip)); GType __t = ((ctk_tooltip_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TOOLTIP (tooltip)"); return; } } while (0)
;
16302 g_return_if_fail (column == NULL || CTK_IS_TREE_VIEW_COLUMN (column))do { if ((column == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((column)); GType __t = ((ctk_tree_view_column_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "column == NULL || CTK_IS_TREE_VIEW_COLUMN (column)"
); return; } } while (0)
;
16303 g_return_if_fail (cell == NULL || CTK_IS_CELL_RENDERER (cell))do { if ((cell == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((cell)); GType __t = ((ctk_cell_renderer_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "cell == NULL || CTK_IS_CELL_RENDERER (cell)"
); return; } } while (0)
;
16304
16305 /* Determine x values. */
16306 if (column && cell)
16307 {
16308 CdkRectangle tmp;
16309 gint start, width;
16310
16311 /* We always pass in path here, whether it is NULL or not.
16312 * For cells in expander columns path must be specified so that
16313 * we can correctly account for the indentation. This also means
16314 * that the tooltip is constrained vertically by the "Determine y
16315 * values" code below; this is not a real problem since cells actually
16316 * don't stretch vertically in constrast to columns.
16317 */
16318 ctk_tree_view_get_cell_area (tree_view, path, column, &tmp);
16319 ctk_tree_view_column_cell_get_position (column, cell, &start, &width);
16320
16321 ctk_tree_view_convert_bin_window_to_widget_coords (tree_view,
16322 tmp.x + start, 0,
16323 &rect.x, NULL((void*)0));
16324 rect.width = width;
16325 }
16326 else if (column)
16327 {
16328 CdkRectangle tmp;
16329
16330 ctk_tree_view_get_background_area (tree_view, NULL((void*)0), column, &tmp);
16331 ctk_tree_view_convert_bin_window_to_widget_coords (tree_view,
16332 tmp.x, 0,
16333 &rect.x, NULL((void*)0));
16334 rect.width = tmp.width;
16335 }
16336 else
16337 {
16338 ctk_widget_get_allocation (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, &allocation);
16339 rect.x = 0;
16340 rect.width = allocation.width;
16341 }
16342
16343 /* Determine y values. */
16344 if (path)
16345 {
16346 CdkRectangle tmp;
16347
16348 ctk_tree_view_get_background_area (tree_view, path, NULL((void*)0), &tmp);
16349 ctk_tree_view_convert_bin_window_to_widget_coords (tree_view,
16350 0, tmp.y,
16351 NULL((void*)0), &rect.y);
16352 rect.height = tmp.height;
16353 }
16354 else
16355 {
16356 rect.y = 0;
16357 rect.height = ctk_adjustment_get_page_size (tree_view->priv->vadjustment);
16358 }
16359
16360 ctk_tooltip_set_tip_area (tooltip, &rect);
16361}
16362
16363/**
16364 * ctk_tree_view_get_tooltip_context:
16365 * @tree_view: a #CtkTreeView
16366 * @x: (inout): the x coordinate (relative to widget coordinates)
16367 * @y: (inout): the y coordinate (relative to widget coordinates)
16368 * @keyboard_tip: whether this is a keyboard tooltip or not
16369 * @model: (out) (optional) (nullable) (transfer none): a pointer to
16370 * receive a #CtkTreeModel or %NULL
16371 * @path: (out) (optional): a pointer to receive a #CtkTreePath or %NULL
16372 * @iter: (out) (optional): a pointer to receive a #CtkTreeIter or %NULL
16373 *
16374 * This function is supposed to be used in a #CtkWidget::query-tooltip
16375 * signal handler for #CtkTreeView. The @x, @y and @keyboard_tip values
16376 * which are received in the signal handler, should be passed to this
16377 * function without modification.
16378 *
16379 * The return value indicates whether there is a tree view row at the given
16380 * coordinates (%TRUE) or not (%FALSE) for mouse tooltips. For keyboard
16381 * tooltips the row returned will be the cursor row. When %TRUE, then any of
16382 * @model, @path and @iter which have been provided will be set to point to
16383 * that row and the corresponding model. @x and @y will always be converted
16384 * to be relative to @tree_view’s bin_window if @keyboard_tooltip is %FALSE.
16385 *
16386 * Returns: whether or not the given tooltip context points to a row.
16387 *
16388 * Since: 2.12
16389 */
16390gboolean
16391ctk_tree_view_get_tooltip_context (CtkTreeView *tree_view,
16392 gint *x,
16393 gint *y,
16394 gboolean keyboard_tip,
16395 CtkTreeModel **model,
16396 CtkTreePath **path,
16397 CtkTreeIter *iter)
16398{
16399 CtkTreePath *tmppath = NULL((void*)0);
16400
16401 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return ((0)); } } while (
0)
;
16402 g_return_val_if_fail (x != NULL, FALSE)do { if ((x != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "x != NULL"); return ((0
)); } } while (0)
;
16403 g_return_val_if_fail (y != NULL, FALSE)do { if ((y != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "y != NULL"); return ((0
)); } } while (0)
;
16404
16405 if (keyboard_tip)
16406 {
16407 ctk_tree_view_get_cursor (tree_view, &tmppath, NULL((void*)0));
16408
16409 if (!tmppath)
16410 return FALSE(0);
16411 }
16412 else
16413 {
16414 ctk_tree_view_convert_widget_to_bin_window_coords (tree_view, *x, *y,
16415 x, y);
16416
16417 if (!ctk_tree_view_get_path_at_pos (tree_view, *x, *y,
16418 &tmppath, NULL((void*)0), NULL((void*)0), NULL((void*)0)))
16419 return FALSE(0);
16420 }
16421
16422 if (model)
16423 *model = ctk_tree_view_get_model (tree_view);
16424
16425 if (iter)
16426 ctk_tree_model_get_iter (ctk_tree_view_get_model (tree_view),
16427 iter, tmppath);
16428
16429 if (path)
16430 *path = tmppath;
16431 else
16432 ctk_tree_path_free (tmppath);
16433
16434 return TRUE(!(0));
16435}
16436
16437static gboolean
16438ctk_tree_view_set_tooltip_query_cb (CtkWidget *widget,
16439 gint x,
16440 gint y,
16441 gboolean keyboard_tip,
16442 CtkTooltip *tooltip,
16443 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
16444{
16445 GValue value = G_VALUE_INIT{ 0, { { 0 } } };
16446 GValue transformed = G_VALUE_INIT{ 0, { { 0 } } };
16447 CtkTreeIter iter;
16448 CtkTreePath *path;
16449 CtkTreeModel *model;
16450 CtkTreeView *tree_view = CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
;
16451 const char *transformed_str = NULL((void*)0);
16452
16453 if (!ctk_tree_view_get_tooltip_context (CTK_TREE_VIEW (widget)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_tree_view_get_type ()))))))
,
16454 &x, &y,
16455 keyboard_tip,
16456 &model, &path, &iter))
16457 return FALSE(0);
16458
16459 ctk_tree_model_get_value (model, &iter,
16460 tree_view->priv->tooltip_column, &value);
16461
16462 g_value_init (&transformed, G_TYPE_STRING((GType) ((16) << (2))));
16463
16464 if (!g_value_transform (&value, &transformed))
16465 {
16466 g_value_unset (&value);
16467 ctk_tree_path_free (path);
16468
16469 return FALSE(0);
16470 }
16471
16472 g_value_unset (&value);
16473
16474 transformed_str = g_value_get_string (&transformed);
16475 if (transformed_str == NULL((void*)0) || *transformed_str == '\0')
16476 {
16477 g_value_unset (&transformed);
16478 ctk_tree_path_free (path);
16479
16480 return FALSE(0);
16481 }
16482
16483 ctk_tooltip_set_markup (tooltip, transformed_str);
16484 ctk_tree_view_set_tooltip_row (tree_view, tooltip, path);
16485
16486 ctk_tree_path_free (path);
16487 g_value_unset (&transformed);
16488
16489 return TRUE(!(0));
16490}
16491
16492/**
16493 * ctk_tree_view_set_tooltip_column:
16494 * @tree_view: a #CtkTreeView
16495 * @column: an integer, which is a valid column number for @tree_view’s model
16496 *
16497 * If you only plan to have simple (text-only) tooltips on full rows, you
16498 * can use this function to have #CtkTreeView handle these automatically
16499 * for you. @column should be set to the column in @tree_view’s model
16500 * containing the tooltip texts, or -1 to disable this feature.
16501 *
16502 * When enabled, #CtkWidget:has-tooltip will be set to %TRUE and
16503 * @tree_view will connect a #CtkWidget::query-tooltip signal handler.
16504 *
16505 * Note that the signal handler sets the text with ctk_tooltip_set_markup(),
16506 * so &, <, etc have to be escaped in the text.
16507 *
16508 * Since: 2.12
16509 */
16510void
16511ctk_tree_view_set_tooltip_column (CtkTreeView *tree_view,
16512 gint column)
16513{
16514 g_return_if_fail (CTK_IS_TREE_VIEW (tree_view))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return; } } while (0)
;
16515
16516 if (column == tree_view->priv->tooltip_column)
16517 return;
16518
16519 if (column == -1)
16520 {
16521 g_signal_handlers_disconnect_by_func (tree_view,g_signal_handlers_disconnect_matched ((tree_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tree_view_set_tooltip_query_cb), (((void*)0)))
16522 ctk_tree_view_set_tooltip_query_cb,g_signal_handlers_disconnect_matched ((tree_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tree_view_set_tooltip_query_cb), (((void*)0)))
16523 NULL)g_signal_handlers_disconnect_matched ((tree_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (ctk_tree_view_set_tooltip_query_cb), (((void*)0)))
;
16524 ctk_widget_set_has_tooltip (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, FALSE(0));
16525 }
16526 else
16527 {
16528 if (tree_view->priv->tooltip_column == -1)
16529 {
16530 g_signal_connect (tree_view, "query-tooltip",g_signal_connect_data ((tree_view), ("query-tooltip"), (((GCallback
) (ctk_tree_view_set_tooltip_query_cb))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
16531 G_CALLBACK (ctk_tree_view_set_tooltip_query_cb), NULL)g_signal_connect_data ((tree_view), ("query-tooltip"), (((GCallback
) (ctk_tree_view_set_tooltip_query_cb))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
;
16532 ctk_widget_set_has_tooltip (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
, TRUE(!(0)));
16533 }
16534 }
16535
16536 tree_view->priv->tooltip_column = column;
16537 g_object_notify_by_pspec (G_OBJECT (tree_view)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), (((GType) ((20) << (2))))))))
, tree_view_props[PROP_TOOLTIP_COLUMN]);
16538}
16539
16540/**
16541 * ctk_tree_view_get_tooltip_column:
16542 * @tree_view: a #CtkTreeView
16543 *
16544 * Returns the column of @tree_view’s model which is being used for
16545 * displaying tooltips on @tree_view’s rows.
16546 *
16547 * Returns: the index of the tooltip column that is currently being
16548 * used, or -1 if this is disabled.
16549 *
16550 * Since: 2.12
16551 */
16552gint
16553ctk_tree_view_get_tooltip_column (CtkTreeView *tree_view)
16554{
16555 g_return_val_if_fail (CTK_IS_TREE_VIEW (tree_view), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((ctk_tree_view_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_TREE_VIEW (tree_view)"); return (0); } } while (0
)
;
16556
16557 return tree_view->priv->tooltip_column;
16558}
16559
16560static gboolean
16561ctk_tree_view_get_border (CtkScrollable *scrollable,
16562 CtkBorder *border)
16563{
16564 border->top = _ctk_tree_view_get_header_height (CTK_TREE_VIEW (scrollable)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((scrollable)), ((ctk_tree_view_get_type ()))))))
);
16565
16566 return TRUE(!(0));
16567}
16568
16569static void
16570ctk_tree_view_scrollable_init (CtkScrollableInterface *iface)
16571{
16572 iface->get_border = ctk_tree_view_get_border;
16573}