1 /* gtktreeviewcolumn.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 #include "config.h"
19
20 #include "gtktreeviewcolumn.h"
21
22 #include "gtkbox.h"
23 #include "gtkbutton.h"
24 #include "gtkcellareabox.h"
25 #include "gtkcellareacontext.h"
26 #include "gtkcelllayout.h"
27 #include "gtkdragsourceprivate.h"
28 #include "gtkframe.h"
29 #include "gtkimage.h"
30 #include "gtkintl.h"
31 #include "gtklabel.h"
32 #include "gtkmarshalers.h"
33 #include "gtkprivate.h"
34 #include "gtktreeprivate.h"
35 #include "gtktreeview.h"
36 #include "gtktypebuiltins.h"
37 #include "gtkwidgetprivate.h"
38 #include "gtkgesturedrag.h"
39 #include "gtkeventcontrollerfocus.h"
40 #include "gtkeventcontrollerkey.h"
41 #include "gtkbuiltiniconprivate.h"
42
43 #include <string.h>
44
45
46 /**
47 * GtkTreeViewColumn:
48 *
49 * A visible column in a GtkTreeView widget
50 *
51 * The GtkTreeViewColumn object represents a visible column in a `GtkTreeView` widget.
52 * It allows to set properties of the column header, and functions as a holding pen
53 * for the cell renderers which determine how the data in the column is displayed.
54 *
55 * Please refer to the [tree widget conceptual overview][TreeWidget]
56 * for an overview of all the objects and data types related to the tree widget and
57 * how they work together, and to the `GtkTreeView` documentation for specifics about
58 * the CSS node structure for treeviews and their headers.
59 */
60
61
62 /* Type methods */
63 static void gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface);
64
65 /* GObject methods */
66 static void gtk_tree_view_column_set_property (GObject *object,
67 guint prop_id,
68 const GValue *value,
69 GParamSpec *pspec);
70 static void gtk_tree_view_column_get_property (GObject *object,
71 guint prop_id,
72 GValue *value,
73 GParamSpec *pspec);
74 static void gtk_tree_view_column_finalize (GObject *object);
75 static void gtk_tree_view_column_dispose (GObject *object);
76 static void gtk_tree_view_column_constructed (GObject *object);
77
78 /* GtkCellLayout implementation */
79 static void gtk_tree_view_column_ensure_cell_area (GtkTreeViewColumn *column,
80 GtkCellArea *cell_area);
81
82 static GtkCellArea *gtk_tree_view_column_cell_layout_get_area (GtkCellLayout *cell_layout);
83
84 /* Button handling code */
85 static void gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column);
86 static void gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column);
87
88 /* Button signal handlers */
89 static void column_button_drag_begin (GtkGestureDrag *gesture,
90 double x,
91 double y,
92 GtkTreeViewColumn *column);
93 static void column_button_drag_update (GtkGestureDrag *gesture,
94 double offset_x,
95 double offset_y,
96 GtkTreeViewColumn *column);
97
98 static void gtk_tree_view_column_button_clicked (GtkWidget *widget,
99 gpointer data);
100 static gboolean gtk_tree_view_column_mnemonic_activate (GtkWidget *widget,
101 gboolean group_cycling,
102 gpointer data);
103
104 /* Property handlers */
105 static void gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
106 GtkTreeViewColumn *tree_column);
107
108 /* GtkCellArea/GtkCellAreaContext callbacks */
109 static void gtk_tree_view_column_context_changed (GtkCellAreaContext *context,
110 GParamSpec *pspec,
111 GtkTreeViewColumn *tree_column);
112 static void gtk_tree_view_column_add_editable_callback (GtkCellArea *area,
113 GtkCellRenderer *renderer,
114 GtkCellEditable *edit_widget,
115 GdkRectangle *cell_area,
116 const char *path_string,
117 gpointer user_data);
118 static void gtk_tree_view_column_remove_editable_callback (GtkCellArea *area,
119 GtkCellRenderer *renderer,
120 GtkCellEditable *edit_widget,
121 gpointer user_data);
122
123 /* Internal functions */
124 static void gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
125 gpointer data);
126 static void gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column);
127 static void gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
128 GtkCellRenderer *cell_renderer,
129 va_list args);
130
131 /* GtkBuildable implementation */
132 static void gtk_tree_view_column_buildable_init (GtkBuildableIface *iface);
133
134 typedef struct _GtkTreeViewColumnClass GtkTreeViewColumnClass;
135 typedef struct _GtkTreeViewColumnPrivate GtkTreeViewColumnPrivate;
136
137 struct _GtkTreeViewColumn
138 {
139 GInitiallyUnowned parent_instance;
140
141 GtkTreeViewColumnPrivate *priv;
142 };
143
144 struct _GtkTreeViewColumnClass
145 {
146 GInitiallyUnownedClass parent_class;
147
148 void (*clicked) (GtkTreeViewColumn *tree_column);
149 };
150
151
152 struct _GtkTreeViewColumnPrivate
153 {
154 GtkWidget *tree_view;
155 GtkWidget *button;
156 GtkWidget *child;
157 GtkWidget *arrow;
158 GtkWidget *frame;
159 gulong property_changed_signal;
160 float xalign;
161
162 /* Sizing fields */
163 /* see gtk+/doc/tree-column-sizing.txt for more information on them */
164 GtkTreeViewColumnSizing column_type;
165 int padding;
166 int x_offset;
167 int width;
168 int fixed_width;
169 int min_width;
170 int max_width;
171
172 /* dragging columns */
173 int drag_x;
174 int drag_y;
175
176 char *title;
177
178 /* Sorting */
179 gulong sort_clicked_signal;
180 gulong sort_column_changed_signal;
181 int sort_column_id;
182 GtkSortType sort_order;
183
184 /* Cell area */
185 GtkCellArea *cell_area;
186 GtkCellAreaContext *cell_area_context;
187 gulong add_editable_signal;
188 gulong remove_editable_signal;
189 gulong context_changed_signal;
190
191 /* Flags */
192 guint visible : 1;
193 guint resizable : 1;
194 guint clickable : 1;
195 guint dirty : 1;
196 guint show_sort_indicator : 1;
197 guint maybe_reordered : 1;
198 guint reorderable : 1;
199 guint expand : 1;
200 };
201
202 enum
203 {
204 PROP_0,
205 PROP_VISIBLE,
206 PROP_RESIZABLE,
207 PROP_X_OFFSET,
208 PROP_WIDTH,
209 PROP_SPACING,
210 PROP_SIZING,
211 PROP_FIXED_WIDTH,
212 PROP_MIN_WIDTH,
213 PROP_MAX_WIDTH,
214 PROP_TITLE,
215 PROP_EXPAND,
216 PROP_CLICKABLE,
217 PROP_WIDGET,
218 PROP_ALIGNMENT,
219 PROP_REORDERABLE,
220 PROP_SORT_INDICATOR,
221 PROP_SORT_ORDER,
222 PROP_SORT_COLUMN_ID,
223 PROP_CELL_AREA,
224 LAST_PROP
225 };
226
227 enum
228 {
229 CLICKED,
230 LAST_SIGNAL
231 };
232
233 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
234 static GParamSpec *tree_column_props[LAST_PROP] = { NULL, };
235
G_DEFINE_TYPE_WITH_CODE(GtkTreeViewColumn,gtk_tree_view_column,G_TYPE_INITIALLY_UNOWNED,G_ADD_PRIVATE (GtkTreeViewColumn)G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,gtk_tree_view_column_cell_layout_init)G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,gtk_tree_view_column_buildable_init))236 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, G_TYPE_INITIALLY_UNOWNED,
237 G_ADD_PRIVATE (GtkTreeViewColumn)
238 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
239 gtk_tree_view_column_cell_layout_init)
240 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
241 gtk_tree_view_column_buildable_init))
242
243
244 static void
245 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
246 {
247 GObjectClass *object_class;
248
249 object_class = (GObjectClass*) class;
250
251 class->clicked = NULL;
252
253 object_class->constructed = gtk_tree_view_column_constructed;
254 object_class->finalize = gtk_tree_view_column_finalize;
255 object_class->dispose = gtk_tree_view_column_dispose;
256 object_class->set_property = gtk_tree_view_column_set_property;
257 object_class->get_property = gtk_tree_view_column_get_property;
258
259 /**
260 * GtkTreeViewColumn::clicked:
261 * @column: the `GtkTreeViewColumn` that emitted the signal
262 *
263 * Emitted when the column's header has been clicked.
264 */
265 tree_column_signals[CLICKED] =
266 g_signal_new (I_("clicked"),
267 G_OBJECT_CLASS_TYPE (object_class),
268 G_SIGNAL_RUN_LAST,
269 G_STRUCT_OFFSET (GtkTreeViewColumnClass, clicked),
270 NULL, NULL,
271 NULL,
272 G_TYPE_NONE, 0);
273
274 tree_column_props[PROP_VISIBLE] =
275 g_param_spec_boolean ("visible",
276 P_("Visible"),
277 P_("Whether to display the column"),
278 TRUE,
279 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
280
281 tree_column_props[PROP_RESIZABLE] =
282 g_param_spec_boolean ("resizable",
283 P_("Resizable"),
284 P_("Column is user-resizable"),
285 FALSE,
286 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
287
288 tree_column_props[PROP_X_OFFSET] =
289 g_param_spec_int ("x-offset",
290 P_("X position"),
291 P_("Current X position of the column"),
292 -G_MAXINT, G_MAXINT,
293 0,
294 GTK_PARAM_READABLE);
295
296 tree_column_props[PROP_WIDTH] =
297 g_param_spec_int ("width",
298 P_("Width"),
299 P_("Current width of the column"),
300 0, G_MAXINT,
301 0,
302 GTK_PARAM_READABLE);
303
304 tree_column_props[PROP_SPACING] =
305 g_param_spec_int ("spacing",
306 P_("Spacing"),
307 P_("Space which is inserted between cells"),
308 0, G_MAXINT,
309 0,
310 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
311
312 tree_column_props[PROP_SIZING] =
313 g_param_spec_enum ("sizing",
314 P_("Sizing"),
315 P_("Resize mode of the column"),
316 GTK_TYPE_TREE_VIEW_COLUMN_SIZING,
317 GTK_TREE_VIEW_COLUMN_GROW_ONLY,
318 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
319
320 tree_column_props[PROP_FIXED_WIDTH] =
321 g_param_spec_int ("fixed-width",
322 P_("Fixed Width"),
323 P_("Current fixed width of the column"),
324 -1, G_MAXINT,
325 -1,
326 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
327
328 tree_column_props[PROP_MIN_WIDTH] =
329 g_param_spec_int ("min-width",
330 P_("Minimum Width"),
331 P_("Minimum allowed width of the column"),
332 -1, G_MAXINT,
333 -1,
334 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
335
336 tree_column_props[PROP_MAX_WIDTH] =
337 g_param_spec_int ("max-width",
338 P_("Maximum Width"),
339 P_("Maximum allowed width of the column"),
340 -1, G_MAXINT,
341 -1,
342 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
343
344 tree_column_props[PROP_TITLE] =
345 g_param_spec_string ("title",
346 P_("Title"),
347 P_("Title to appear in column header"),
348 "",
349 GTK_PARAM_READWRITE);
350
351 tree_column_props[PROP_EXPAND] =
352 g_param_spec_boolean ("expand",
353 P_("Expand"),
354 P_("Column gets share of extra width allocated to the widget"),
355 FALSE,
356 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
357
358 tree_column_props[PROP_CLICKABLE] =
359 g_param_spec_boolean ("clickable",
360 P_("Clickable"),
361 P_("Whether the header can be clicked"),
362 FALSE,
363 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
364
365 tree_column_props[PROP_WIDGET] =
366 g_param_spec_object ("widget",
367 P_("Widget"),
368 P_("Widget to put in column header button instead of column title"),
369 GTK_TYPE_WIDGET,
370 GTK_PARAM_READWRITE);
371
372 tree_column_props[PROP_ALIGNMENT] =
373 g_param_spec_float ("alignment",
374 P_("Alignment"),
375 P_("X Alignment of the column header text or widget"),
376 0.0, 1.0, 0.0,
377 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
378
379 tree_column_props[PROP_REORDERABLE] =
380 g_param_spec_boolean ("reorderable",
381 P_("Reorderable"),
382 P_("Whether the column can be reordered around the headers"),
383 FALSE,
384 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
385
386 tree_column_props[PROP_SORT_INDICATOR] =
387 g_param_spec_boolean ("sort-indicator",
388 P_("Sort indicator"),
389 P_("Whether to show a sort indicator"),
390 FALSE,
391 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
392
393 tree_column_props[PROP_SORT_ORDER] =
394 g_param_spec_enum ("sort-order",
395 P_("Sort order"),
396 P_("Sort direction the sort indicator should indicate"),
397 GTK_TYPE_SORT_TYPE,
398 GTK_SORT_ASCENDING,
399 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
400
401 /**
402 * GtkTreeViewColumn:sort-column-id:
403 *
404 * Logical sort column ID this column sorts on when selected for sorting. Setting the sort column ID makes the column header
405 * clickable. Set to -1 to make the column unsortable.
406 **/
407 tree_column_props[PROP_SORT_COLUMN_ID] =
408 g_param_spec_int ("sort-column-id",
409 P_("Sort column ID"),
410 P_("Logical sort column ID this column sorts on when selected for sorting"),
411 -1, G_MAXINT,
412 -1,
413 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
414
415 /**
416 * GtkTreeViewColumn:cell-area:
417 *
418 * The `GtkCellArea` used to layout cell renderers for this column.
419 *
420 * If no area is specified when creating the tree view column with gtk_tree_view_column_new_with_area()
421 * a horizontally oriented `GtkCellAreaBox` will be used.
422 */
423 tree_column_props[PROP_CELL_AREA] =
424 g_param_spec_object ("cell-area",
425 P_("Cell Area"),
426 P_("The GtkCellArea used to layout cells"),
427 GTK_TYPE_CELL_AREA,
428 GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
429
430 g_object_class_install_properties (object_class, LAST_PROP, tree_column_props);
431 }
432
433 static void
gtk_tree_view_column_custom_tag_end(GtkBuildable * buildable,GtkBuilder * builder,GObject * child,const char * tagname,gpointer data)434 gtk_tree_view_column_custom_tag_end (GtkBuildable *buildable,
435 GtkBuilder *builder,
436 GObject *child,
437 const char *tagname,
438 gpointer data)
439 {
440 /* Just ignore the boolean return from here */
441 _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname, data);
442 }
443
444 static void
gtk_tree_view_column_buildable_init(GtkBuildableIface * iface)445 gtk_tree_view_column_buildable_init (GtkBuildableIface *iface)
446 {
447 iface->add_child = _gtk_cell_layout_buildable_add_child;
448 iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
449 iface->custom_tag_end = gtk_tree_view_column_custom_tag_end;
450 }
451
452 static void
gtk_tree_view_column_cell_layout_init(GtkCellLayoutIface * iface)453 gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface)
454 {
455 iface->get_area = gtk_tree_view_column_cell_layout_get_area;
456 }
457
458 static void
gtk_tree_view_column_init(GtkTreeViewColumn * tree_column)459 gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
460 {
461 GtkTreeViewColumnPrivate *priv;
462
463 tree_column->priv = gtk_tree_view_column_get_instance_private (tree_column);
464 priv = tree_column->priv;
465
466 priv->button = NULL;
467 priv->xalign = 0.0;
468 priv->width = 0;
469 priv->padding = 0;
470 priv->min_width = -1;
471 priv->max_width = -1;
472 priv->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY;
473 priv->visible = TRUE;
474 priv->resizable = FALSE;
475 priv->expand = FALSE;
476 priv->clickable = FALSE;
477 priv->dirty = TRUE;
478 priv->sort_order = GTK_SORT_ASCENDING;
479 priv->show_sort_indicator = FALSE;
480 priv->property_changed_signal = 0;
481 priv->sort_clicked_signal = 0;
482 priv->sort_column_changed_signal = 0;
483 priv->sort_column_id = -1;
484 priv->reorderable = FALSE;
485 priv->maybe_reordered = FALSE;
486 priv->fixed_width = -1;
487 priv->title = g_strdup ("");
488
489 gtk_tree_view_column_create_button (tree_column);
490 }
491
492 static void
gtk_tree_view_column_constructed(GObject * object)493 gtk_tree_view_column_constructed (GObject *object)
494 {
495 GtkTreeViewColumn *tree_column = GTK_TREE_VIEW_COLUMN (object);
496
497 G_OBJECT_CLASS (gtk_tree_view_column_parent_class)->constructed (object);
498
499 gtk_tree_view_column_ensure_cell_area (tree_column, NULL);
500 }
501
502 static void
gtk_tree_view_column_dispose(GObject * object)503 gtk_tree_view_column_dispose (GObject *object)
504 {
505 GtkTreeViewColumn *tree_column = (GtkTreeViewColumn *) object;
506 GtkTreeViewColumnPrivate *priv = tree_column->priv;
507
508 /* Remove this column from its treeview,
509 * in case this column is destroyed before its treeview.
510 */
511 if (priv->tree_view)
512 gtk_tree_view_remove_column (GTK_TREE_VIEW (priv->tree_view), tree_column);
513
514 if (priv->cell_area_context)
515 {
516 g_signal_handler_disconnect (priv->cell_area_context,
517 priv->context_changed_signal);
518
519 g_object_unref (priv->cell_area_context);
520
521 priv->cell_area_context = NULL;
522 priv->context_changed_signal = 0;
523 }
524
525 if (priv->cell_area)
526 {
527 g_signal_handler_disconnect (priv->cell_area,
528 priv->add_editable_signal);
529 g_signal_handler_disconnect (priv->cell_area,
530 priv->remove_editable_signal);
531
532 g_object_unref (priv->cell_area);
533 priv->cell_area = NULL;
534 priv->add_editable_signal = 0;
535 priv->remove_editable_signal = 0;
536 }
537
538 if (priv->child)
539 {
540 g_object_unref (priv->child);
541 priv->child = NULL;
542 }
543
544 g_clear_object (&priv->button);
545
546 G_OBJECT_CLASS (gtk_tree_view_column_parent_class)->dispose (object);
547 }
548
549 static void
gtk_tree_view_column_finalize(GObject * object)550 gtk_tree_view_column_finalize (GObject *object)
551 {
552 GtkTreeViewColumn *tree_column = (GtkTreeViewColumn *) object;
553 GtkTreeViewColumnPrivate *priv = tree_column->priv;
554
555 g_free (priv->title);
556
557 G_OBJECT_CLASS (gtk_tree_view_column_parent_class)->finalize (object);
558 }
559
560 static void
gtk_tree_view_column_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)561 gtk_tree_view_column_set_property (GObject *object,
562 guint prop_id,
563 const GValue *value,
564 GParamSpec *pspec)
565 {
566 GtkTreeViewColumn *tree_column;
567 GtkCellArea *area;
568
569 tree_column = GTK_TREE_VIEW_COLUMN (object);
570
571 switch (prop_id)
572 {
573 case PROP_VISIBLE:
574 gtk_tree_view_column_set_visible (tree_column,
575 g_value_get_boolean (value));
576 break;
577
578 case PROP_RESIZABLE:
579 gtk_tree_view_column_set_resizable (tree_column,
580 g_value_get_boolean (value));
581 break;
582
583 case PROP_SIZING:
584 gtk_tree_view_column_set_sizing (tree_column,
585 g_value_get_enum (value));
586 break;
587
588 case PROP_FIXED_WIDTH:
589 gtk_tree_view_column_set_fixed_width (tree_column,
590 g_value_get_int (value));
591 break;
592
593 case PROP_MIN_WIDTH:
594 gtk_tree_view_column_set_min_width (tree_column,
595 g_value_get_int (value));
596 break;
597
598 case PROP_MAX_WIDTH:
599 gtk_tree_view_column_set_max_width (tree_column,
600 g_value_get_int (value));
601 break;
602
603 case PROP_SPACING:
604 gtk_tree_view_column_set_spacing (tree_column,
605 g_value_get_int (value));
606 break;
607
608 case PROP_TITLE:
609 gtk_tree_view_column_set_title (tree_column,
610 g_value_get_string (value));
611 break;
612
613 case PROP_EXPAND:
614 gtk_tree_view_column_set_expand (tree_column,
615 g_value_get_boolean (value));
616 break;
617
618 case PROP_CLICKABLE:
619 gtk_tree_view_column_set_clickable (tree_column,
620 g_value_get_boolean (value));
621 break;
622
623 case PROP_WIDGET:
624 gtk_tree_view_column_set_widget (tree_column,
625 (GtkWidget*) g_value_get_object (value));
626 break;
627
628 case PROP_ALIGNMENT:
629 gtk_tree_view_column_set_alignment (tree_column,
630 g_value_get_float (value));
631 break;
632
633 case PROP_REORDERABLE:
634 gtk_tree_view_column_set_reorderable (tree_column,
635 g_value_get_boolean (value));
636 break;
637
638 case PROP_SORT_INDICATOR:
639 gtk_tree_view_column_set_sort_indicator (tree_column,
640 g_value_get_boolean (value));
641 break;
642
643 case PROP_SORT_ORDER:
644 gtk_tree_view_column_set_sort_order (tree_column,
645 g_value_get_enum (value));
646 break;
647
648 case PROP_SORT_COLUMN_ID:
649 gtk_tree_view_column_set_sort_column_id (tree_column,
650 g_value_get_int (value));
651 break;
652
653 case PROP_CELL_AREA:
654 /* Construct-only, can only be assigned once */
655 area = g_value_get_object (value);
656
657 if (area)
658 {
659 if (tree_column->priv->cell_area != NULL)
660 {
661 g_warning ("cell-area has already been set, ignoring construct property");
662 g_object_ref_sink (area);
663 g_object_unref (area);
664 }
665 else
666 gtk_tree_view_column_ensure_cell_area (tree_column, area);
667 }
668 break;
669
670 default:
671 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
672 break;
673 }
674 }
675
676 static void
gtk_tree_view_column_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)677 gtk_tree_view_column_get_property (GObject *object,
678 guint prop_id,
679 GValue *value,
680 GParamSpec *pspec)
681 {
682 GtkTreeViewColumn *tree_column;
683
684 tree_column = GTK_TREE_VIEW_COLUMN (object);
685
686 switch (prop_id)
687 {
688 case PROP_VISIBLE:
689 g_value_set_boolean (value,
690 gtk_tree_view_column_get_visible (tree_column));
691 break;
692
693 case PROP_RESIZABLE:
694 g_value_set_boolean (value,
695 gtk_tree_view_column_get_resizable (tree_column));
696 break;
697
698 case PROP_X_OFFSET:
699 g_value_set_int (value,
700 gtk_tree_view_column_get_x_offset (tree_column));
701 break;
702
703 case PROP_WIDTH:
704 g_value_set_int (value,
705 gtk_tree_view_column_get_width (tree_column));
706 break;
707
708 case PROP_SPACING:
709 g_value_set_int (value,
710 gtk_tree_view_column_get_spacing (tree_column));
711 break;
712
713 case PROP_SIZING:
714 g_value_set_enum (value,
715 gtk_tree_view_column_get_sizing (tree_column));
716 break;
717
718 case PROP_FIXED_WIDTH:
719 g_value_set_int (value,
720 gtk_tree_view_column_get_fixed_width (tree_column));
721 break;
722
723 case PROP_MIN_WIDTH:
724 g_value_set_int (value,
725 gtk_tree_view_column_get_min_width (tree_column));
726 break;
727
728 case PROP_MAX_WIDTH:
729 g_value_set_int (value,
730 gtk_tree_view_column_get_max_width (tree_column));
731 break;
732
733 case PROP_TITLE:
734 g_value_set_string (value,
735 gtk_tree_view_column_get_title (tree_column));
736 break;
737
738 case PROP_EXPAND:
739 g_value_set_boolean (value,
740 gtk_tree_view_column_get_expand (tree_column));
741 break;
742
743 case PROP_CLICKABLE:
744 g_value_set_boolean (value,
745 gtk_tree_view_column_get_clickable (tree_column));
746 break;
747
748 case PROP_WIDGET:
749 g_value_set_object (value,
750 (GObject*) gtk_tree_view_column_get_widget (tree_column));
751 break;
752
753 case PROP_ALIGNMENT:
754 g_value_set_float (value,
755 gtk_tree_view_column_get_alignment (tree_column));
756 break;
757
758 case PROP_REORDERABLE:
759 g_value_set_boolean (value,
760 gtk_tree_view_column_get_reorderable (tree_column));
761 break;
762
763 case PROP_SORT_INDICATOR:
764 g_value_set_boolean (value,
765 gtk_tree_view_column_get_sort_indicator (tree_column));
766 break;
767
768 case PROP_SORT_ORDER:
769 g_value_set_enum (value,
770 gtk_tree_view_column_get_sort_order (tree_column));
771 break;
772
773 case PROP_SORT_COLUMN_ID:
774 g_value_set_int (value,
775 gtk_tree_view_column_get_sort_column_id (tree_column));
776 break;
777
778 case PROP_CELL_AREA:
779 g_value_set_object (value, tree_column->priv->cell_area);
780 break;
781
782 default:
783 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
784 break;
785 }
786 }
787
788 /* Implementation of GtkCellLayout interface
789 */
790
791 static void
gtk_tree_view_column_ensure_cell_area(GtkTreeViewColumn * column,GtkCellArea * cell_area)792 gtk_tree_view_column_ensure_cell_area (GtkTreeViewColumn *column,
793 GtkCellArea *cell_area)
794 {
795 GtkTreeViewColumnPrivate *priv = column->priv;
796
797 if (priv->cell_area)
798 return;
799
800 if (cell_area)
801 priv->cell_area = cell_area;
802 else
803 priv->cell_area = gtk_cell_area_box_new ();
804
805 g_object_ref_sink (priv->cell_area);
806
807 priv->add_editable_signal =
808 g_signal_connect (priv->cell_area, "add-editable",
809 G_CALLBACK (gtk_tree_view_column_add_editable_callback),
810 column);
811 priv->remove_editable_signal =
812 g_signal_connect (priv->cell_area, "remove-editable",
813 G_CALLBACK (gtk_tree_view_column_remove_editable_callback),
814 column);
815
816 priv->cell_area_context = gtk_cell_area_create_context (priv->cell_area);
817
818 priv->context_changed_signal =
819 g_signal_connect (priv->cell_area_context, "notify",
820 G_CALLBACK (gtk_tree_view_column_context_changed),
821 column);
822 }
823
824 static GtkCellArea *
gtk_tree_view_column_cell_layout_get_area(GtkCellLayout * cell_layout)825 gtk_tree_view_column_cell_layout_get_area (GtkCellLayout *cell_layout)
826 {
827 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (cell_layout);
828 GtkTreeViewColumnPrivate *priv = column->priv;
829
830 if (G_UNLIKELY (!priv->cell_area))
831 gtk_tree_view_column_ensure_cell_area (column, NULL);
832
833 return priv->cell_area;
834 }
835
836 static void
focus_in(GtkEventControllerKey * controller,GtkTreeViewColumn * column)837 focus_in (GtkEventControllerKey *controller,
838 GtkTreeViewColumn *column)
839 {
840 _gtk_tree_view_set_focus_column (GTK_TREE_VIEW (column->priv->tree_view), column);
841 }
842
843 /* Button handling code
844 */
845 static void
gtk_tree_view_column_create_button(GtkTreeViewColumn * tree_column)846 gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column)
847 {
848 GtkTreeViewColumnPrivate *priv = tree_column->priv;
849 GtkEventController *controller;
850 GtkWidget *child;
851 GtkWidget *hbox;
852
853 g_return_if_fail (priv->button == NULL);
854
855 priv->button = gtk_button_new ();
856 g_object_ref_sink (priv->button);
857 gtk_widget_set_focus_on_click (priv->button, FALSE);
858 gtk_widget_set_overflow (priv->button, GTK_OVERFLOW_HIDDEN);
859
860 g_signal_connect (priv->button, "clicked",
861 G_CALLBACK (gtk_tree_view_column_button_clicked),
862 tree_column);
863
864 controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
865 g_signal_connect (controller, "drag-begin",
866 G_CALLBACK (column_button_drag_begin), tree_column);
867 g_signal_connect (controller, "drag-update",
868 G_CALLBACK (column_button_drag_update), tree_column);
869 gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
870 gtk_widget_add_controller (priv->button, controller);
871
872 controller = gtk_event_controller_focus_new ();
873 g_signal_connect (controller, "enter", G_CALLBACK (focus_in), tree_column);
874 gtk_widget_add_controller (priv->button, controller);
875
876 priv->frame = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
877 gtk_widget_set_hexpand (priv->frame, TRUE);
878 gtk_widget_set_halign (priv->frame, GTK_ALIGN_START);
879
880 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
881 priv->arrow = gtk_builtin_icon_new ("sort-indicator");
882
883 if (priv->child)
884 child = priv->child;
885 else
886 child = gtk_label_new (priv->title);
887
888 g_signal_connect (child, "mnemonic-activate",
889 G_CALLBACK (gtk_tree_view_column_mnemonic_activate),
890 tree_column);
891
892 if (priv->xalign <= 0.5)
893 {
894 gtk_box_append (GTK_BOX (hbox), priv->frame);
895 gtk_box_append (GTK_BOX (hbox), priv->arrow);
896 }
897 else
898 {
899 gtk_box_append (GTK_BOX (hbox), priv->arrow);
900 gtk_box_append (GTK_BOX (hbox), priv->frame);
901 }
902
903 gtk_box_append (GTK_BOX (priv->frame), child);
904 gtk_button_set_child (GTK_BUTTON (priv->button), hbox);
905 }
906
907 static void
gtk_tree_view_column_update_button(GtkTreeViewColumn * tree_column)908 gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
909 {
910 GtkTreeViewColumnPrivate *priv = tree_column->priv;
911 int sort_column_id = -1;
912 GtkWidget *hbox;
913 GtkWidget *frame;
914 GtkWidget *arrow;
915 GtkWidget *current_child;
916 GtkTreeModel *model;
917
918 if (priv->tree_view)
919 model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
920 else
921 model = NULL;
922
923 hbox = gtk_button_get_child (GTK_BUTTON (priv->button));
924 frame = priv->frame;
925 arrow = priv->arrow;
926 current_child = gtk_widget_get_first_child (frame);
927
928 /* Set up the actual button */
929 if (priv->child)
930 {
931 if (current_child != priv->child)
932 {
933 gtk_box_remove (GTK_BOX (frame), current_child);
934 gtk_box_append (GTK_BOX (frame), priv->child);
935 }
936 }
937 else
938 {
939 if (current_child == NULL)
940 {
941 current_child = gtk_label_new (NULL);
942 gtk_widget_show (current_child);
943 gtk_box_append (GTK_BOX (frame), current_child);
944 }
945
946 g_return_if_fail (GTK_IS_LABEL (current_child));
947
948 if (priv->title)
949 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
950 priv->title);
951 else
952 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
953 "");
954 }
955
956 if (GTK_IS_TREE_SORTABLE (model))
957 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
958 &sort_column_id,
959 NULL);
960
961 if (priv->show_sort_indicator)
962 {
963 gboolean alternative;
964
965 if (priv->tree_view)
966 g_object_get (gtk_widget_get_settings (priv->tree_view),
967 "gtk-alternative-sort-arrows", &alternative,
968 NULL);
969 else
970 alternative = FALSE;
971
972 if ((!alternative && priv->sort_order == GTK_SORT_ASCENDING) ||
973 (alternative && priv->sort_order == GTK_SORT_DESCENDING))
974 {
975 gtk_widget_remove_css_class (arrow, "descending");
976 gtk_widget_add_css_class (arrow, "ascending");
977 }
978 else
979 {
980 gtk_widget_remove_css_class (arrow, "ascending");
981 gtk_widget_add_css_class (arrow, "descending");
982 }
983 }
984
985 /* Put arrow on the right if the text is left-or-center justified, and on the
986 * left otherwise; do this by packing boxes, so flipping text direction will
987 * reverse things
988 */
989 if (priv->xalign <= 0.5)
990 gtk_box_reorder_child_after (GTK_BOX (hbox), arrow, gtk_widget_get_last_child (hbox));
991 else
992 gtk_box_reorder_child_after (GTK_BOX (hbox), arrow, NULL);
993
994 if (priv->show_sort_indicator
995 || (GTK_IS_TREE_SORTABLE (model) && priv->sort_column_id >= 0))
996 gtk_widget_show (arrow);
997 else
998 gtk_widget_hide (arrow);
999
1000 if (priv->show_sort_indicator)
1001 gtk_widget_set_opacity (arrow, 1.0);
1002 else
1003 gtk_widget_set_opacity (arrow, 0.0);
1004
1005 /* It's always safe to hide the button. It isn't always safe to show it, as
1006 * if you show it before it's realized, it'll get the wrong window. */
1007 if (priv->tree_view != NULL &&
1008 gtk_widget_get_realized (priv->tree_view))
1009 {
1010 if (priv->visible &&
1011 gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view)))
1012 {
1013 gtk_widget_show (priv->button);
1014 }
1015 else
1016 {
1017 gtk_widget_hide (priv->button);
1018 }
1019 }
1020
1021 if (priv->reorderable || priv->clickable)
1022 {
1023 gtk_widget_set_focusable (priv->button, TRUE);
1024 }
1025 else
1026 {
1027 gtk_widget_set_focusable (priv->button, FALSE);
1028 if (gtk_widget_has_focus (priv->button))
1029 {
1030 GtkRoot *root = gtk_widget_get_root (priv->tree_view);
1031 gtk_root_set_focus (root, NULL);
1032 }
1033 }
1034 /* Queue a resize on the assumption that we always want to catch all changes
1035 * and columns don't change all that often.
1036 */
1037 if (priv->tree_view && gtk_widget_get_realized (priv->tree_view))
1038 gtk_widget_queue_resize (priv->tree_view);
1039 }
1040
1041 /* Button signal handlers
1042 */
1043
1044 static void
column_button_drag_begin(GtkGestureDrag * gesture,double x,double y,GtkTreeViewColumn * column)1045 column_button_drag_begin (GtkGestureDrag *gesture,
1046 double x,
1047 double y,
1048 GtkTreeViewColumn *column)
1049 {
1050 GtkTreeViewColumnPrivate *priv = column->priv;
1051
1052 if (!priv->reorderable)
1053 {
1054 gtk_gesture_set_state (GTK_GESTURE (gesture),
1055 GTK_EVENT_SEQUENCE_DENIED);
1056 return;
1057 }
1058
1059 priv->drag_x = x;
1060 priv->drag_y = y;
1061 gtk_widget_grab_focus (priv->button);
1062 }
1063
1064 static void
column_button_drag_update(GtkGestureDrag * gesture,double offset_x,double offset_y,GtkTreeViewColumn * column)1065 column_button_drag_update (GtkGestureDrag *gesture,
1066 double offset_x,
1067 double offset_y,
1068 GtkTreeViewColumn *column)
1069 {
1070 GtkTreeViewColumnPrivate *priv = column->priv;
1071
1072 if (gtk_drag_check_threshold_double (priv->button, 0, 0, offset_x, offset_y))
1073 {
1074 gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
1075 _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (priv->tree_view), column,
1076 gtk_gesture_get_device (GTK_GESTURE (gesture)));
1077 }
1078 }
1079
1080 static void
gtk_tree_view_column_button_clicked(GtkWidget * widget,gpointer data)1081 gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
1082 {
1083 g_signal_emit_by_name (data, "clicked");
1084 }
1085
1086 static gboolean
gtk_tree_view_column_mnemonic_activate(GtkWidget * widget,gboolean group_cycling,gpointer data)1087 gtk_tree_view_column_mnemonic_activate (GtkWidget *widget,
1088 gboolean group_cycling,
1089 gpointer data)
1090 {
1091 GtkTreeViewColumn *column = (GtkTreeViewColumn *)data;
1092 GtkTreeViewColumnPrivate *priv = column->priv;
1093
1094 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), FALSE);
1095
1096 _gtk_tree_view_set_focus_column (GTK_TREE_VIEW (priv->tree_view), column);
1097
1098 if (priv->clickable)
1099 g_signal_emit_by_name (priv->button, "clicked");
1100 else if (gtk_widget_get_focusable (priv->button))
1101 gtk_widget_grab_focus (priv->button);
1102 else
1103 gtk_widget_grab_focus (priv->tree_view);
1104
1105 return TRUE;
1106 }
1107
1108 static void
gtk_tree_view_model_sort_column_changed(GtkTreeSortable * sortable,GtkTreeViewColumn * column)1109 gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
1110 GtkTreeViewColumn *column)
1111 {
1112 GtkTreeViewColumnPrivate *priv = column->priv;
1113 int sort_column_id;
1114 GtkSortType order;
1115
1116 if (gtk_tree_sortable_get_sort_column_id (sortable,
1117 &sort_column_id,
1118 &order))
1119 {
1120 if (sort_column_id == priv->sort_column_id)
1121 {
1122 gtk_tree_view_column_set_sort_indicator (column, TRUE);
1123 gtk_tree_view_column_set_sort_order (column, order);
1124 }
1125 else
1126 {
1127 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1128 }
1129 }
1130 else
1131 {
1132 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1133 }
1134 }
1135
1136 static void
gtk_tree_view_column_sort(GtkTreeViewColumn * tree_column,gpointer data)1137 gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
1138 gpointer data)
1139 {
1140 GtkTreeViewColumnPrivate *priv = tree_column->priv;
1141 GtkTreeModel *model;
1142 GtkTreeSortable *sortable;
1143 int sort_column_id;
1144 GtkSortType order;
1145 gboolean has_sort_column;
1146 gboolean has_default_sort_func;
1147
1148 g_return_if_fail (priv->tree_view != NULL);
1149
1150 model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
1151 sortable = GTK_TREE_SORTABLE (model);
1152
1153 has_sort_column =
1154 gtk_tree_sortable_get_sort_column_id (sortable,
1155 &sort_column_id,
1156 &order);
1157 has_default_sort_func =
1158 gtk_tree_sortable_has_default_sort_func (sortable);
1159
1160 if (has_sort_column &&
1161 sort_column_id == priv->sort_column_id)
1162 {
1163 if (order == GTK_SORT_ASCENDING)
1164 gtk_tree_sortable_set_sort_column_id (sortable,
1165 priv->sort_column_id,
1166 GTK_SORT_DESCENDING);
1167 else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
1168 gtk_tree_sortable_set_sort_column_id (sortable,
1169 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1170 GTK_SORT_ASCENDING);
1171 else
1172 gtk_tree_sortable_set_sort_column_id (sortable,
1173 priv->sort_column_id,
1174 GTK_SORT_ASCENDING);
1175 }
1176 else
1177 {
1178 gtk_tree_sortable_set_sort_column_id (sortable,
1179 priv->sort_column_id,
1180 GTK_SORT_ASCENDING);
1181 }
1182 }
1183
1184 static void
gtk_tree_view_column_setup_sort_column_id_callback(GtkTreeViewColumn * tree_column)1185 gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column)
1186 {
1187 GtkTreeViewColumnPrivate *priv = tree_column->priv;
1188 GtkTreeModel *model;
1189
1190 if (priv->tree_view == NULL)
1191 return;
1192
1193 model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
1194
1195 if (model == NULL)
1196 return;
1197
1198 if (GTK_IS_TREE_SORTABLE (model) &&
1199 priv->sort_column_id != -1)
1200 {
1201 int real_sort_column_id;
1202 GtkSortType real_order;
1203
1204 if (priv->sort_column_changed_signal == 0)
1205 priv->sort_column_changed_signal =
1206 g_signal_connect (model, "sort-column-changed",
1207 G_CALLBACK (gtk_tree_view_model_sort_column_changed),
1208 tree_column);
1209
1210 if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
1211 &real_sort_column_id,
1212 &real_order) &&
1213 (real_sort_column_id == priv->sort_column_id))
1214 {
1215 gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
1216 gtk_tree_view_column_set_sort_order (tree_column, real_order);
1217 }
1218 else
1219 {
1220 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
1221 }
1222 }
1223 }
1224
1225 static void
gtk_tree_view_column_context_changed(GtkCellAreaContext * context,GParamSpec * pspec,GtkTreeViewColumn * tree_column)1226 gtk_tree_view_column_context_changed (GtkCellAreaContext *context,
1227 GParamSpec *pspec,
1228 GtkTreeViewColumn *tree_column)
1229 {
1230 /* Here we want the column re-requested if the underlying context was
1231 * actually reset for any reason, this can happen if the underlying
1232 * area/cell configuration changes (i.e. cell packing properties
1233 * or cell spacing and the like)
1234 *
1235 * Note that we block this handler while requesting for sizes
1236 * so there is no need to check for the new context size being -1,
1237 * we also block the handler when explicitly resetting the context
1238 * so as to avoid some infinite stack recursion.
1239 */
1240 if (!strcmp (pspec->name, "minimum-width") ||
1241 !strcmp (pspec->name, "natural-width") ||
1242 !strcmp (pspec->name, "minimum-height") ||
1243 !strcmp (pspec->name, "natural-height"))
1244 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
1245 }
1246
1247 static void
gtk_tree_view_column_add_editable_callback(GtkCellArea * area,GtkCellRenderer * renderer,GtkCellEditable * edit_widget,GdkRectangle * cell_area,const char * path_string,gpointer user_data)1248 gtk_tree_view_column_add_editable_callback (GtkCellArea *area,
1249 GtkCellRenderer *renderer,
1250 GtkCellEditable *edit_widget,
1251 GdkRectangle *cell_area,
1252 const char *path_string,
1253 gpointer user_data)
1254 {
1255 GtkTreeViewColumn *column = user_data;
1256 GtkTreeViewColumnPrivate *priv = column->priv;
1257 GtkTreePath *path;
1258
1259 if (priv->tree_view)
1260 {
1261 path = gtk_tree_path_new_from_string (path_string);
1262
1263 _gtk_tree_view_add_editable (GTK_TREE_VIEW (priv->tree_view),
1264 column,
1265 path,
1266 edit_widget,
1267 cell_area);
1268
1269 gtk_tree_path_free (path);
1270 }
1271 }
1272
1273 static void
gtk_tree_view_column_remove_editable_callback(GtkCellArea * area,GtkCellRenderer * renderer,GtkCellEditable * edit_widget,gpointer user_data)1274 gtk_tree_view_column_remove_editable_callback (GtkCellArea *area,
1275 GtkCellRenderer *renderer,
1276 GtkCellEditable *edit_widget,
1277 gpointer user_data)
1278 {
1279 GtkTreeViewColumn *column = user_data;
1280 GtkTreeViewColumnPrivate *priv = column->priv;
1281
1282 if (priv->tree_view)
1283 _gtk_tree_view_remove_editable (GTK_TREE_VIEW (priv->tree_view),
1284 column,
1285 edit_widget);
1286 }
1287
1288 /* Exported Private Functions.
1289 * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
1290 */
1291 void
_gtk_tree_view_column_realize_button(GtkTreeViewColumn * column)1292 _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column)
1293 {
1294 g_return_if_fail (GTK_IS_TREE_VIEW (column->priv->tree_view));
1295 g_return_if_fail (gtk_widget_get_realized (column->priv->tree_view));
1296 g_return_if_fail (column->priv->button != NULL);
1297
1298 gtk_tree_view_column_update_button (column);
1299 }
1300
1301 void
_gtk_tree_view_column_unset_model(GtkTreeViewColumn * column,GtkTreeModel * old_model)1302 _gtk_tree_view_column_unset_model (GtkTreeViewColumn *column,
1303 GtkTreeModel *old_model)
1304 {
1305 GtkTreeViewColumnPrivate *priv = column->priv;
1306
1307 if (priv->sort_column_changed_signal)
1308 {
1309 g_signal_handler_disconnect (old_model,
1310 priv->sort_column_changed_signal);
1311 priv->sort_column_changed_signal = 0;
1312 }
1313 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1314 }
1315
1316 void
_gtk_tree_view_column_set_tree_view(GtkTreeViewColumn * column,GtkTreeView * tree_view)1317 _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
1318 GtkTreeView *tree_view)
1319 {
1320 GtkTreeViewColumnPrivate *priv = column->priv;
1321
1322 g_assert (priv->tree_view == NULL);
1323
1324 priv->tree_view = GTK_WIDGET (tree_view);
1325
1326 /* avoid a warning with our messed up CSS nodes */
1327 gtk_widget_insert_after (priv->button, GTK_WIDGET (tree_view), NULL);
1328
1329 priv->property_changed_signal =
1330 g_signal_connect_swapped (tree_view,
1331 "notify::model",
1332 G_CALLBACK (gtk_tree_view_column_setup_sort_column_id_callback),
1333 column);
1334
1335 gtk_tree_view_column_setup_sort_column_id_callback (column);
1336 }
1337
1338 void
_gtk_tree_view_column_unset_tree_view(GtkTreeViewColumn * column)1339 _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
1340 {
1341 GtkTreeViewColumnPrivate *priv = column->priv;
1342
1343 if (priv->tree_view == NULL)
1344 return;
1345
1346 gtk_widget_unparent (priv->button);
1347
1348 if (priv->property_changed_signal)
1349 {
1350 g_signal_handler_disconnect (priv->tree_view, priv->property_changed_signal);
1351 priv->property_changed_signal = 0;
1352 }
1353
1354 if (priv->sort_column_changed_signal)
1355 {
1356 g_signal_handler_disconnect (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view)),
1357 priv->sort_column_changed_signal);
1358 priv->sort_column_changed_signal = 0;
1359 }
1360
1361 priv->tree_view = NULL;
1362 }
1363
1364 gboolean
_gtk_tree_view_column_has_editable_cell(GtkTreeViewColumn * column)1365 _gtk_tree_view_column_has_editable_cell (GtkTreeViewColumn *column)
1366 {
1367 GtkTreeViewColumnPrivate *priv = column->priv;
1368 gboolean ret = FALSE;
1369 GList *list, *cells;
1370
1371 cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->cell_area));
1372
1373 for (list = cells; list; list = list->next)
1374 {
1375 GtkCellRenderer *cell = list->data;
1376 GtkCellRendererMode mode;
1377
1378 g_object_get (cell, "mode", &mode, NULL);
1379
1380 if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
1381 {
1382 ret = TRUE;
1383 break;
1384 }
1385 }
1386
1387 g_list_free (cells);
1388
1389 return ret;
1390 }
1391
1392 /* gets cell being edited */
1393 GtkCellRenderer *
_gtk_tree_view_column_get_edited_cell(GtkTreeViewColumn * column)1394 _gtk_tree_view_column_get_edited_cell (GtkTreeViewColumn *column)
1395 {
1396 GtkTreeViewColumnPrivate *priv = column->priv;
1397
1398 return gtk_cell_area_get_edited_cell (priv->cell_area);
1399 }
1400
1401 GtkCellRenderer *
_gtk_tree_view_column_get_cell_at_pos(GtkTreeViewColumn * column,GdkRectangle * cell_area,GdkRectangle * background_area,int x,int y)1402 _gtk_tree_view_column_get_cell_at_pos (GtkTreeViewColumn *column,
1403 GdkRectangle *cell_area,
1404 GdkRectangle *background_area,
1405 int x,
1406 int y)
1407 {
1408 GtkCellRenderer *match = NULL;
1409 GtkTreeViewColumnPrivate *priv = column->priv;
1410
1411 /* If (x, y) is outside of the background area, immediately return */
1412 if (x < background_area->x ||
1413 x > background_area->x + background_area->width ||
1414 y < background_area->y ||
1415 y > background_area->y + background_area->height)
1416 return NULL;
1417
1418 /* If (x, y) is inside the background area, clamp it to the cell_area
1419 * so that a cell is still returned. The main reason for doing this
1420 * (on the x axis) is for handling clicks in the indentation area
1421 * (either at the left or right depending on RTL setting). Another
1422 * reason is for handling clicks on the area where the focus rectangle
1423 * is drawn (this is outside of cell area), this manifests itself
1424 * mainly when a large setting is used for focus-line-width.
1425 */
1426 if (x < cell_area->x)
1427 x = cell_area->x;
1428 else if (x > cell_area->x + cell_area->width)
1429 x = cell_area->x + cell_area->width;
1430
1431 if (y < cell_area->y)
1432 y = cell_area->y;
1433 else if (y > cell_area->y + cell_area->height)
1434 y = cell_area->y + cell_area->height;
1435
1436 match = gtk_cell_area_get_cell_at_position (priv->cell_area,
1437 priv->cell_area_context,
1438 priv->tree_view,
1439 cell_area,
1440 x, y,
1441 NULL);
1442
1443 return match;
1444 }
1445
1446 gboolean
_gtk_tree_view_column_is_blank_at_pos(GtkTreeViewColumn * column,GdkRectangle * cell_area,GdkRectangle * background_area,int x,int y)1447 _gtk_tree_view_column_is_blank_at_pos (GtkTreeViewColumn *column,
1448 GdkRectangle *cell_area,
1449 GdkRectangle *background_area,
1450 int x,
1451 int y)
1452 {
1453 GtkCellRenderer *match;
1454 GdkRectangle cell_alloc, aligned_area, inner_area;
1455 GtkTreeViewColumnPrivate *priv = column->priv;
1456
1457 match = _gtk_tree_view_column_get_cell_at_pos (column,
1458 cell_area,
1459 background_area,
1460 x, y);
1461 if (!match)
1462 return FALSE;
1463
1464 gtk_cell_area_get_cell_allocation (priv->cell_area,
1465 priv->cell_area_context,
1466 priv->tree_view,
1467 match,
1468 cell_area,
1469 &cell_alloc);
1470
1471 gtk_cell_area_inner_cell_area (priv->cell_area, priv->tree_view,
1472 &cell_alloc, &inner_area);
1473 gtk_cell_renderer_get_aligned_area (match, priv->tree_view, 0,
1474 &inner_area, &aligned_area);
1475
1476 if (x < aligned_area.x ||
1477 x > aligned_area.x + aligned_area.width ||
1478 y < aligned_area.y ||
1479 y > aligned_area.y + aligned_area.height)
1480 return TRUE;
1481
1482 return FALSE;
1483 }
1484
1485 /* Public Functions */
1486
1487
1488 /**
1489 * gtk_tree_view_column_new:
1490 *
1491 * Creates a new `GtkTreeViewColumn`.
1492 *
1493 * Returns: A newly created `GtkTreeViewColumn`.
1494 **/
1495 GtkTreeViewColumn *
gtk_tree_view_column_new(void)1496 gtk_tree_view_column_new (void)
1497 {
1498 GtkTreeViewColumn *tree_column;
1499
1500 tree_column = g_object_new (GTK_TYPE_TREE_VIEW_COLUMN, NULL);
1501
1502 return tree_column;
1503 }
1504
1505 /**
1506 * gtk_tree_view_column_new_with_area:
1507 * @area: the `GtkCellArea` that the newly created column should use to layout cells.
1508 *
1509 * Creates a new `GtkTreeViewColumn` using @area to render its cells.
1510 *
1511 * Returns: A newly created `GtkTreeViewColumn`.
1512 */
1513 GtkTreeViewColumn *
gtk_tree_view_column_new_with_area(GtkCellArea * area)1514 gtk_tree_view_column_new_with_area (GtkCellArea *area)
1515 {
1516 GtkTreeViewColumn *tree_column;
1517
1518 tree_column = g_object_new (GTK_TYPE_TREE_VIEW_COLUMN, "cell-area", area, NULL);
1519
1520 return tree_column;
1521 }
1522
1523
1524 /**
1525 * gtk_tree_view_column_new_with_attributes:
1526 * @title: The title to set the header to
1527 * @cell: The `GtkCellRenderer`
1528 * @...: A %NULL-terminated list of attributes
1529 *
1530 * Creates a new `GtkTreeViewColumn` with a number of default values.
1531 * This is equivalent to calling gtk_tree_view_column_set_title(),
1532 * gtk_tree_view_column_pack_start(), and
1533 * gtk_tree_view_column_set_attributes() on the newly created `GtkTreeViewColumn`.
1534 *
1535 * Here’s a simple example:
1536 * |[<!-- language="C" -->
1537 * enum { TEXT_COLUMN, COLOR_COLUMN, N_COLUMNS };
1538 * // ...
1539 * {
1540 * GtkTreeViewColumn *column;
1541 * GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
1542 *
1543 * column = gtk_tree_view_column_new_with_attributes ("Title",
1544 * renderer,
1545 * "text", TEXT_COLUMN,
1546 * "foreground", COLOR_COLUMN,
1547 * NULL);
1548 * }
1549 * ]|
1550 *
1551 * Returns: A newly created `GtkTreeViewColumn`.
1552 **/
1553 GtkTreeViewColumn *
gtk_tree_view_column_new_with_attributes(const char * title,GtkCellRenderer * cell,...)1554 gtk_tree_view_column_new_with_attributes (const char *title,
1555 GtkCellRenderer *cell,
1556 ...)
1557 {
1558 GtkTreeViewColumn *retval;
1559 va_list args;
1560
1561 retval = gtk_tree_view_column_new ();
1562
1563 gtk_tree_view_column_set_title (retval, title);
1564 gtk_tree_view_column_pack_start (retval, cell, TRUE);
1565
1566 va_start (args, cell);
1567 gtk_tree_view_column_set_attributesv (retval, cell, args);
1568 va_end (args);
1569
1570 return retval;
1571 }
1572
1573 /**
1574 * gtk_tree_view_column_pack_start:
1575 * @tree_column: A `GtkTreeViewColumn`.
1576 * @cell: The `GtkCellRenderer`
1577 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1578 *
1579 * Packs the @cell into the beginning of the column. If @expand is %FALSE, then
1580 * the @cell is allocated no more space than it needs. Any unused space is divided
1581 * evenly between cells for which @expand is %TRUE.
1582 **/
1583 void
gtk_tree_view_column_pack_start(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,gboolean expand)1584 gtk_tree_view_column_pack_start (GtkTreeViewColumn *tree_column,
1585 GtkCellRenderer *cell,
1586 gboolean expand)
1587 {
1588 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (tree_column), cell, expand);
1589 }
1590
1591 /**
1592 * gtk_tree_view_column_pack_end:
1593 * @tree_column: A `GtkTreeViewColumn`.
1594 * @cell: The `GtkCellRenderer`
1595 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1596 *
1597 * Adds the @cell to end of the column. If @expand is %FALSE, then the @cell
1598 * is allocated no more space than it needs. Any unused space is divided
1599 * evenly between cells for which @expand is %TRUE.
1600 **/
1601 void
gtk_tree_view_column_pack_end(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,gboolean expand)1602 gtk_tree_view_column_pack_end (GtkTreeViewColumn *tree_column,
1603 GtkCellRenderer *cell,
1604 gboolean expand)
1605 {
1606 gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (tree_column), cell, expand);
1607 }
1608
1609 /**
1610 * gtk_tree_view_column_clear:
1611 * @tree_column: A `GtkTreeViewColumn`
1612 *
1613 * Unsets all the mappings on all renderers on the @tree_column.
1614 **/
1615 void
gtk_tree_view_column_clear(GtkTreeViewColumn * tree_column)1616 gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
1617 {
1618 gtk_cell_layout_clear (GTK_CELL_LAYOUT (tree_column));
1619 }
1620
1621 /**
1622 * gtk_tree_view_column_add_attribute:
1623 * @tree_column: A `GtkTreeViewColumn`
1624 * @cell_renderer: the `GtkCellRenderer` to set attributes on
1625 * @attribute: An attribute on the renderer
1626 * @column: The column position on the model to get the attribute from.
1627 *
1628 * Adds an attribute mapping to the list in @tree_column.
1629 *
1630 * The @column is the
1631 * column of the model to get a value from, and the @attribute is the
1632 * parameter on @cell_renderer to be set from the value. So for example
1633 * if column 2 of the model contains strings, you could have the
1634 * “text” attribute of a `GtkCellRendererText` get its values from
1635 * column 2.
1636 **/
1637 void
gtk_tree_view_column_add_attribute(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell_renderer,const char * attribute,int column)1638 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
1639 GtkCellRenderer *cell_renderer,
1640 const char *attribute,
1641 int column)
1642 {
1643 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (tree_column),
1644 cell_renderer, attribute, column);
1645 }
1646
1647 static void
gtk_tree_view_column_set_attributesv(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell_renderer,va_list args)1648 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
1649 GtkCellRenderer *cell_renderer,
1650 va_list args)
1651 {
1652 GtkTreeViewColumnPrivate *priv = tree_column->priv;
1653 char *attribute;
1654 int column;
1655
1656 attribute = va_arg (args, char *);
1657
1658 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (priv->cell_area),
1659 cell_renderer);
1660
1661 while (attribute != NULL)
1662 {
1663 column = va_arg (args, int);
1664 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->cell_area),
1665 cell_renderer, attribute, column);
1666 attribute = va_arg (args, char *);
1667 }
1668 }
1669
1670 /**
1671 * gtk_tree_view_column_set_attributes:
1672 * @tree_column: A `GtkTreeViewColumn`
1673 * @cell_renderer: the `GtkCellRenderer` we’re setting the attributes of
1674 * @...: A %NULL-terminated list of attributes
1675 *
1676 * Sets the attributes in the list as the attributes of @tree_column.
1677 *
1678 * The attributes should be in attribute/column order, as in
1679 * gtk_tree_view_column_add_attribute(). All existing attributes
1680 * are removed, and replaced with the new attributes.
1681 */
1682 void
gtk_tree_view_column_set_attributes(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell_renderer,...)1683 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
1684 GtkCellRenderer *cell_renderer,
1685 ...)
1686 {
1687 va_list args;
1688
1689 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1690 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1691
1692 va_start (args, cell_renderer);
1693 gtk_tree_view_column_set_attributesv (tree_column, cell_renderer, args);
1694 va_end (args);
1695 }
1696
1697
1698 /**
1699 * gtk_tree_view_column_set_cell_data_func:
1700 * @tree_column: A `GtkTreeViewColumn`
1701 * @cell_renderer: A `GtkCellRenderer`
1702 * @func: (nullable): The `GtkTreeCellDataFunc` to use.
1703 * @func_data: (closure): The user data for @func.
1704 * @destroy: The destroy notification for @func_data
1705 *
1706 * Sets the `GtkTreeCellDataFunc` to use for the column.
1707 *
1708 * This
1709 * function is used instead of the standard attributes mapping for
1710 * setting the column value, and should set the value of @tree_column's
1711 * cell renderer as appropriate. @func may be %NULL to remove an
1712 * older one.
1713 **/
1714 void
gtk_tree_view_column_set_cell_data_func(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell_renderer,GtkTreeCellDataFunc func,gpointer func_data,GDestroyNotify destroy)1715 gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn *tree_column,
1716 GtkCellRenderer *cell_renderer,
1717 GtkTreeCellDataFunc func,
1718 gpointer func_data,
1719 GDestroyNotify destroy)
1720 {
1721 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (tree_column),
1722 cell_renderer,
1723 (GtkCellLayoutDataFunc)func,
1724 func_data, destroy);
1725 }
1726
1727
1728 /**
1729 * gtk_tree_view_column_clear_attributes:
1730 * @tree_column: a `GtkTreeViewColumn`
1731 * @cell_renderer: a `GtkCellRenderer` to clear the attribute mapping on.
1732 *
1733 * Clears all existing attributes previously set with
1734 * gtk_tree_view_column_set_attributes().
1735 **/
1736 void
gtk_tree_view_column_clear_attributes(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell_renderer)1737 gtk_tree_view_column_clear_attributes (GtkTreeViewColumn *tree_column,
1738 GtkCellRenderer *cell_renderer)
1739 {
1740 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (tree_column),
1741 cell_renderer);
1742 }
1743
1744 /**
1745 * gtk_tree_view_column_set_spacing:
1746 * @tree_column: A `GtkTreeViewColumn`.
1747 * @spacing: distance between cell renderers in pixels.
1748 *
1749 * Sets the spacing field of @tree_column, which is the number of pixels to
1750 * place between cell renderers packed into it.
1751 **/
1752 void
gtk_tree_view_column_set_spacing(GtkTreeViewColumn * tree_column,int spacing)1753 gtk_tree_view_column_set_spacing (GtkTreeViewColumn *tree_column,
1754 int spacing)
1755 {
1756 GtkTreeViewColumnPrivate *priv;
1757
1758 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1759 g_return_if_fail (spacing >= 0);
1760
1761 priv = tree_column->priv;
1762
1763 if (gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (priv->cell_area)) != spacing)
1764 {
1765 gtk_cell_area_box_set_spacing (GTK_CELL_AREA_BOX (priv->cell_area), spacing);
1766 if (priv->tree_view)
1767 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
1768 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_SPACING]);
1769 }
1770 }
1771
1772 /**
1773 * gtk_tree_view_column_get_spacing:
1774 * @tree_column: A `GtkTreeViewColumn`.
1775 *
1776 * Returns the spacing of @tree_column.
1777 *
1778 * Returns: the spacing of @tree_column.
1779 **/
1780 int
gtk_tree_view_column_get_spacing(GtkTreeViewColumn * tree_column)1781 gtk_tree_view_column_get_spacing (GtkTreeViewColumn *tree_column)
1782 {
1783 GtkTreeViewColumnPrivate *priv;
1784
1785 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1786
1787 priv = tree_column->priv;
1788
1789 return gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (priv->cell_area));
1790 }
1791
1792 /* Options for manipulating the columns */
1793
1794 /**
1795 * gtk_tree_view_column_set_visible:
1796 * @tree_column: A `GtkTreeViewColumn`.
1797 * @visible: %TRUE if the @tree_column is visible.
1798 *
1799 * Sets the visibility of @tree_column.
1800 */
1801 void
gtk_tree_view_column_set_visible(GtkTreeViewColumn * tree_column,gboolean visible)1802 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
1803 gboolean visible)
1804 {
1805 GtkTreeViewColumnPrivate *priv;
1806
1807 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1808
1809 priv = tree_column->priv;
1810 visible = !! visible;
1811
1812 if (priv->visible == visible)
1813 return;
1814
1815 priv->visible = visible;
1816
1817 gtk_widget_set_visible (priv->button, visible);
1818
1819 if (priv->visible)
1820 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
1821
1822 gtk_tree_view_column_update_button (tree_column);
1823 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_VISIBLE]);
1824 }
1825
1826 /**
1827 * gtk_tree_view_column_get_visible:
1828 * @tree_column: A `GtkTreeViewColumn`.
1829 *
1830 * Returns %TRUE if @tree_column is visible.
1831 *
1832 * Returns: whether the column is visible or not. If it is visible, then
1833 * the tree will show the column.
1834 **/
1835 gboolean
gtk_tree_view_column_get_visible(GtkTreeViewColumn * tree_column)1836 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1837 {
1838 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1839
1840 return tree_column->priv->visible;
1841 }
1842
1843 /**
1844 * gtk_tree_view_column_set_resizable:
1845 * @tree_column: A `GtkTreeViewColumn`
1846 * @resizable: %TRUE, if the column can be resized
1847 *
1848 * If @resizable is %TRUE, then the user can explicitly resize the column by
1849 * grabbing the outer edge of the column button.
1850 *
1851 * If resizable is %TRUE and
1852 * sizing mode of the column is %GTK_TREE_VIEW_COLUMN_AUTOSIZE, then the sizing
1853 * mode is changed to %GTK_TREE_VIEW_COLUMN_GROW_ONLY.
1854 **/
1855 void
gtk_tree_view_column_set_resizable(GtkTreeViewColumn * tree_column,gboolean resizable)1856 gtk_tree_view_column_set_resizable (GtkTreeViewColumn *tree_column,
1857 gboolean resizable)
1858 {
1859 GtkTreeViewColumnPrivate *priv;
1860
1861 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1862
1863 priv = tree_column->priv;
1864 resizable = !! resizable;
1865
1866 if (priv->resizable == resizable)
1867 return;
1868
1869 priv->resizable = resizable;
1870
1871 if (resizable && priv->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1872 gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1873
1874 gtk_tree_view_column_update_button (tree_column);
1875
1876 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_RESIZABLE]);
1877 }
1878
1879 /**
1880 * gtk_tree_view_column_get_resizable:
1881 * @tree_column: A `GtkTreeViewColumn`
1882 *
1883 * Returns %TRUE if the @tree_column can be resized by the end user.
1884 *
1885 * Returns: %TRUE, if the @tree_column can be resized.
1886 **/
1887 gboolean
gtk_tree_view_column_get_resizable(GtkTreeViewColumn * tree_column)1888 gtk_tree_view_column_get_resizable (GtkTreeViewColumn *tree_column)
1889 {
1890 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1891
1892 return tree_column->priv->resizable;
1893 }
1894
1895
1896 /**
1897 * gtk_tree_view_column_set_sizing:
1898 * @tree_column: A `GtkTreeViewColumn`.
1899 * @type: The `GtkTreeViewColumn`Sizing.
1900 *
1901 * Sets the growth behavior of @tree_column to @type.
1902 **/
1903 void
gtk_tree_view_column_set_sizing(GtkTreeViewColumn * tree_column,GtkTreeViewColumnSizing type)1904 gtk_tree_view_column_set_sizing (GtkTreeViewColumn *tree_column,
1905 GtkTreeViewColumnSizing type)
1906 {
1907 GtkTreeViewColumnPrivate *priv;
1908
1909 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1910
1911 priv = tree_column->priv;
1912
1913 if (type == priv->column_type)
1914 return;
1915
1916 if (type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1917 gtk_tree_view_column_set_resizable (tree_column, FALSE);
1918
1919 priv->column_type = type;
1920
1921 gtk_tree_view_column_update_button (tree_column);
1922
1923 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_SIZING]);
1924 }
1925
1926 /**
1927 * gtk_tree_view_column_get_sizing:
1928 * @tree_column: A `GtkTreeViewColumn`.
1929 *
1930 * Returns the current type of @tree_column.
1931 *
1932 * Returns: The type of @tree_column.
1933 **/
1934 GtkTreeViewColumnSizing
gtk_tree_view_column_get_sizing(GtkTreeViewColumn * tree_column)1935 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
1936 {
1937 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1938
1939 return tree_column->priv->column_type;
1940 }
1941
1942 /**
1943 * gtk_tree_view_column_get_width:
1944 * @tree_column: A `GtkTreeViewColumn`.
1945 *
1946 * Returns the current size of @tree_column in pixels.
1947 *
1948 * Returns: The current width of @tree_column.
1949 **/
1950 int
gtk_tree_view_column_get_width(GtkTreeViewColumn * tree_column)1951 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
1952 {
1953 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1954
1955 return tree_column->priv->width;
1956 }
1957
1958 /**
1959 * gtk_tree_view_column_get_x_offset:
1960 * @tree_column: A `GtkTreeViewColumn`.
1961 *
1962 * Returns the current X offset of @tree_column in pixels.
1963 *
1964 * Returns: The current X offset of @tree_column.
1965 */
1966 int
gtk_tree_view_column_get_x_offset(GtkTreeViewColumn * tree_column)1967 gtk_tree_view_column_get_x_offset (GtkTreeViewColumn *tree_column)
1968 {
1969 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1970
1971 return tree_column->priv->x_offset;
1972 }
1973
1974 int
_gtk_tree_view_column_request_width(GtkTreeViewColumn * tree_column)1975 _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column)
1976 {
1977 GtkTreeViewColumnPrivate *priv;
1978 int real_requested_width;
1979
1980 priv = tree_column->priv;
1981
1982 if (priv->fixed_width != -1)
1983 {
1984 real_requested_width = priv->fixed_width;
1985 }
1986 else if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view)))
1987 {
1988 int button_request;
1989 int requested_width;
1990
1991 gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL);
1992 requested_width += priv->padding;
1993
1994 gtk_widget_measure (priv->button, GTK_ORIENTATION_HORIZONTAL, -1,
1995 &button_request, NULL, NULL, NULL);
1996 real_requested_width = MAX (requested_width, button_request);
1997 }
1998 else
1999 {
2000 int requested_width;
2001
2002 gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL);
2003 requested_width += priv->padding;
2004
2005 real_requested_width = requested_width;
2006 if (real_requested_width < 0)
2007 real_requested_width = 0;
2008 }
2009
2010 if (priv->min_width != -1)
2011 real_requested_width = MAX (real_requested_width, priv->min_width);
2012
2013 if (priv->max_width != -1)
2014 real_requested_width = MIN (real_requested_width, priv->max_width);
2015
2016 return real_requested_width;
2017 }
2018
2019 void
_gtk_tree_view_column_allocate(GtkTreeViewColumn * tree_column,int x_offset,int width,int height)2020 _gtk_tree_view_column_allocate (GtkTreeViewColumn *tree_column,
2021 int x_offset,
2022 int width,
2023 int height)
2024 {
2025 GtkTreeViewColumnPrivate *priv;
2026 GtkAllocation allocation = { 0, 0, 0, 0 };
2027
2028 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2029
2030 priv = tree_column->priv;
2031
2032 if (priv->width != width)
2033 gtk_widget_queue_draw (priv->tree_view);
2034
2035 priv->x_offset = x_offset;
2036 priv->width = width;
2037
2038 gtk_cell_area_context_allocate (priv->cell_area_context, priv->width - priv->padding, -1);
2039
2040 if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view)))
2041 {
2042 /* TODO: Underallocates the button horizontally, but
2043 * https://bugzilla.gnome.org/show_bug.cgi?id=770388
2044 */
2045 allocation.x = x_offset;
2046 allocation.y = 0;
2047 allocation.width = width;
2048 allocation.height = height;
2049
2050 gtk_widget_size_allocate (priv->button, &allocation, -1);
2051 }
2052
2053 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_X_OFFSET]);
2054 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_WIDTH]);
2055 }
2056
2057 /**
2058 * gtk_tree_view_column_set_fixed_width:
2059 * @tree_column: A `GtkTreeViewColumn`.
2060 * @fixed_width: The new fixed width, in pixels, or -1.
2061 *
2062 * If @fixed_width is not -1, sets the fixed width of @tree_column; otherwise
2063 * unsets it. The effective value of @fixed_width is clamped between the
2064 * minimum and maximum width of the column; however, the value stored in the
2065 * “fixed-width” property is not clamped. If the column sizing is
2066 * %GTK_TREE_VIEW_COLUMN_GROW_ONLY or %GTK_TREE_VIEW_COLUMN_AUTOSIZE, setting
2067 * a fixed width overrides the automatically calculated width. Note that
2068 * @fixed_width is only a hint to GTK; the width actually allocated to the
2069 * column may be greater or less than requested.
2070 *
2071 * Along with “expand”, the “fixed-width” property changes when the column is
2072 * resized by the user.
2073 **/
2074 void
gtk_tree_view_column_set_fixed_width(GtkTreeViewColumn * tree_column,int fixed_width)2075 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
2076 int fixed_width)
2077 {
2078 GtkTreeViewColumnPrivate *priv;
2079
2080 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2081 g_return_if_fail (fixed_width >= -1);
2082
2083 priv = tree_column->priv;
2084
2085 if (priv->fixed_width != fixed_width)
2086 {
2087 priv->fixed_width = fixed_width;
2088 if (priv->visible &&
2089 priv->tree_view != NULL &&
2090 gtk_widget_get_realized (priv->tree_view))
2091 gtk_widget_queue_resize (priv->tree_view);
2092
2093 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_FIXED_WIDTH]);
2094 }
2095 }
2096
2097 /**
2098 * gtk_tree_view_column_get_fixed_width:
2099 * @tree_column: A `GtkTreeViewColumn`.
2100 *
2101 * Gets the fixed width of the column. This may not be the actual displayed
2102 * width of the column; for that, use gtk_tree_view_column_get_width().
2103 *
2104 * Returns: The fixed width of the column.
2105 **/
2106 int
gtk_tree_view_column_get_fixed_width(GtkTreeViewColumn * tree_column)2107 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
2108 {
2109 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2110
2111 return tree_column->priv->fixed_width;
2112 }
2113
2114 /**
2115 * gtk_tree_view_column_set_min_width:
2116 * @tree_column: A `GtkTreeViewColumn`.
2117 * @min_width: The minimum width of the column in pixels, or -1.
2118 *
2119 * Sets the minimum width of the @tree_column. If @min_width is -1, then the
2120 * minimum width is unset.
2121 **/
2122 void
gtk_tree_view_column_set_min_width(GtkTreeViewColumn * tree_column,int min_width)2123 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
2124 int min_width)
2125 {
2126 GtkTreeViewColumnPrivate *priv;
2127
2128 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2129 g_return_if_fail (min_width >= -1);
2130
2131 priv = tree_column->priv;
2132
2133 if (min_width == priv->min_width)
2134 return;
2135
2136 if (priv->visible &&
2137 priv->tree_view != NULL &&
2138 gtk_widget_get_realized (priv->tree_view))
2139 {
2140 if (min_width > priv->width)
2141 gtk_widget_queue_resize (priv->tree_view);
2142 }
2143
2144 priv->min_width = min_width;
2145 g_object_freeze_notify (G_OBJECT (tree_column));
2146 if (priv->max_width != -1 && priv->max_width < min_width)
2147 {
2148 priv->max_width = min_width;
2149 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_MAX_WIDTH]);
2150 }
2151 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_MIN_WIDTH]);
2152 g_object_thaw_notify (G_OBJECT (tree_column));
2153
2154 if (priv->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE && priv->tree_view)
2155 _gtk_tree_view_column_autosize (GTK_TREE_VIEW (priv->tree_view),
2156 tree_column);
2157 }
2158
2159 /**
2160 * gtk_tree_view_column_get_min_width:
2161 * @tree_column: A `GtkTreeViewColumn`.
2162 *
2163 * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
2164 * width is set.
2165 *
2166 * Returns: The minimum width of the @tree_column.
2167 **/
2168 int
gtk_tree_view_column_get_min_width(GtkTreeViewColumn * tree_column)2169 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
2170 {
2171 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2172
2173 return tree_column->priv->min_width;
2174 }
2175
2176 /**
2177 * gtk_tree_view_column_set_max_width:
2178 * @tree_column: A `GtkTreeViewColumn`.
2179 * @max_width: The maximum width of the column in pixels, or -1.
2180 *
2181 * Sets the maximum width of the @tree_column. If @max_width is -1, then the
2182 * maximum width is unset. Note, the column can actually be wider than max
2183 * width if it’s the last column in a view. In this case, the column expands to
2184 * fill any extra space.
2185 **/
2186 void
gtk_tree_view_column_set_max_width(GtkTreeViewColumn * tree_column,int max_width)2187 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
2188 int max_width)
2189 {
2190 GtkTreeViewColumnPrivate *priv;
2191
2192 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2193 g_return_if_fail (max_width >= -1);
2194
2195 priv = tree_column->priv;
2196
2197 if (max_width == priv->max_width)
2198 return;
2199
2200 if (priv->visible &&
2201 priv->tree_view != NULL &&
2202 gtk_widget_get_realized (priv->tree_view))
2203 {
2204 if (max_width != -1 && max_width < priv->width)
2205 gtk_widget_queue_resize (priv->tree_view);
2206 }
2207
2208 priv->max_width = max_width;
2209 g_object_freeze_notify (G_OBJECT (tree_column));
2210 if (max_width != -1 && max_width < priv->min_width)
2211 {
2212 priv->min_width = max_width;
2213 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_MIN_WIDTH]);
2214 }
2215 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_MAX_WIDTH]);
2216 g_object_thaw_notify (G_OBJECT (tree_column));
2217
2218 if (priv->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE && priv->tree_view)
2219 _gtk_tree_view_column_autosize (GTK_TREE_VIEW (priv->tree_view),
2220 tree_column);
2221 }
2222
2223 /**
2224 * gtk_tree_view_column_get_max_width:
2225 * @tree_column: A `GtkTreeViewColumn`.
2226 *
2227 * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
2228 * width is set.
2229 *
2230 * Returns: The maximum width of the @tree_column.
2231 **/
2232 int
gtk_tree_view_column_get_max_width(GtkTreeViewColumn * tree_column)2233 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
2234 {
2235 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2236
2237 return tree_column->priv->max_width;
2238 }
2239
2240 /**
2241 * gtk_tree_view_column_clicked:
2242 * @tree_column: a `GtkTreeViewColumn`
2243 *
2244 * Emits the “clicked” signal on the column. This function will only work if
2245 * @tree_column is clickable.
2246 **/
2247 void
gtk_tree_view_column_clicked(GtkTreeViewColumn * tree_column)2248 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
2249 {
2250 GtkTreeViewColumnPrivate *priv;
2251
2252 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2253
2254 priv = tree_column->priv;
2255
2256 if (priv->visible && priv->clickable)
2257 g_signal_emit_by_name (priv->button, "clicked");
2258 }
2259
2260 /**
2261 * gtk_tree_view_column_set_title:
2262 * @tree_column: A `GtkTreeViewColumn`.
2263 * @title: The title of the @tree_column.
2264 *
2265 * Sets the title of the @tree_column. If a custom widget has been set, then
2266 * this value is ignored.
2267 **/
2268 void
gtk_tree_view_column_set_title(GtkTreeViewColumn * tree_column,const char * title)2269 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
2270 const char *title)
2271 {
2272 GtkTreeViewColumnPrivate *priv;
2273 char *new_title;
2274
2275 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2276
2277 priv = tree_column->priv;
2278
2279 new_title = g_strdup (title);
2280 g_free (priv->title);
2281 priv->title = new_title;
2282
2283 gtk_tree_view_column_update_button (tree_column);
2284 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_TITLE]);
2285 }
2286
2287 /**
2288 * gtk_tree_view_column_get_title:
2289 * @tree_column: A `GtkTreeViewColumn`.
2290 *
2291 * Returns the title of the widget.
2292 *
2293 * Returns: the title of the column. This string should not be
2294 * modified or freed.
2295 **/
2296 const char *
gtk_tree_view_column_get_title(GtkTreeViewColumn * tree_column)2297 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
2298 {
2299 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2300
2301 return tree_column->priv->title;
2302 }
2303
2304 /**
2305 * gtk_tree_view_column_set_expand:
2306 * @tree_column: A `GtkTreeViewColumn`.
2307 * @expand: %TRUE if the column should expand to fill available space.
2308 *
2309 * Sets the column to take available extra space. This space is shared equally
2310 * amongst all columns that have the expand set to %TRUE. If no column has this
2311 * option set, then the last column gets all extra space. By default, every
2312 * column is created with this %FALSE.
2313 *
2314 * Along with “fixed-width”, the “expand” property changes when the column is
2315 * resized by the user.
2316 **/
2317 void
gtk_tree_view_column_set_expand(GtkTreeViewColumn * tree_column,gboolean expand)2318 gtk_tree_view_column_set_expand (GtkTreeViewColumn *tree_column,
2319 gboolean expand)
2320 {
2321 GtkTreeViewColumnPrivate *priv;
2322
2323 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2324
2325 priv = tree_column->priv;
2326
2327 expand = expand?TRUE:FALSE;
2328 if (priv->expand == expand)
2329 return;
2330 priv->expand = expand;
2331
2332 if (priv->visible &&
2333 priv->tree_view != NULL &&
2334 gtk_widget_get_realized (priv->tree_view))
2335 {
2336 gtk_widget_queue_resize (priv->tree_view);
2337 }
2338
2339 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_EXPAND]);
2340 }
2341
2342 /**
2343 * gtk_tree_view_column_get_expand:
2344 * @tree_column: A `GtkTreeViewColumn`.
2345 *
2346 * Returns %TRUE if the column expands to fill available space.
2347 *
2348 * Returns: %TRUE if the column expands to fill available space.
2349 **/
2350 gboolean
gtk_tree_view_column_get_expand(GtkTreeViewColumn * tree_column)2351 gtk_tree_view_column_get_expand (GtkTreeViewColumn *tree_column)
2352 {
2353 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2354
2355 return tree_column->priv->expand;
2356 }
2357
2358 /**
2359 * gtk_tree_view_column_set_clickable:
2360 * @tree_column: A `GtkTreeViewColumn`.
2361 * @clickable: %TRUE if the header is active.
2362 *
2363 * Sets the header to be active if @clickable is %TRUE. When the header is
2364 * active, then it can take keyboard focus, and can be clicked.
2365 **/
2366 void
gtk_tree_view_column_set_clickable(GtkTreeViewColumn * tree_column,gboolean clickable)2367 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
2368 gboolean clickable)
2369 {
2370 GtkTreeViewColumnPrivate *priv;
2371
2372 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2373
2374 priv = tree_column->priv;
2375
2376 clickable = !! clickable;
2377 if (priv->clickable == clickable)
2378 return;
2379
2380 priv->clickable = clickable;
2381 gtk_tree_view_column_update_button (tree_column);
2382 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_CLICKABLE]);
2383 }
2384
2385 /**
2386 * gtk_tree_view_column_get_clickable:
2387 * @tree_column: a `GtkTreeViewColumn`
2388 *
2389 * Returns %TRUE if the user can click on the header for the column.
2390 *
2391 * Returns: %TRUE if user can click the column header.
2392 **/
2393 gboolean
gtk_tree_view_column_get_clickable(GtkTreeViewColumn * tree_column)2394 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
2395 {
2396 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2397
2398 return tree_column->priv->clickable;
2399 }
2400
2401 /**
2402 * gtk_tree_view_column_set_widget:
2403 * @tree_column: A `GtkTreeViewColumn`.
2404 * @widget: (nullable): A child `GtkWidget`
2405 *
2406 * Sets the widget in the header to be @widget. If widget is %NULL, then the
2407 * header button is set with a `GtkLabel` set to the title of @tree_column.
2408 **/
2409 void
gtk_tree_view_column_set_widget(GtkTreeViewColumn * tree_column,GtkWidget * widget)2410 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
2411 GtkWidget *widget)
2412 {
2413 GtkTreeViewColumnPrivate *priv;
2414
2415 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2416 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
2417
2418 priv = tree_column->priv;
2419
2420 if (widget)
2421 g_object_ref_sink (widget);
2422
2423 if (priv->child)
2424 g_object_unref (priv->child);
2425
2426 priv->child = widget;
2427 gtk_tree_view_column_update_button (tree_column);
2428 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_WIDGET]);
2429 }
2430
2431 /**
2432 * gtk_tree_view_column_get_widget:
2433 * @tree_column: A `GtkTreeViewColumn`
2434 *
2435 * Returns the `GtkWidget` in the button on the column header.
2436 *
2437 * If a custom widget has not been set then %NULL is returned.
2438 *
2439 * Returns: (nullable) (transfer none): The `GtkWidget` in the column header
2440 */
2441 GtkWidget *
gtk_tree_view_column_get_widget(GtkTreeViewColumn * tree_column)2442 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
2443 {
2444 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2445
2446 return tree_column->priv->child;
2447 }
2448
2449 /**
2450 * gtk_tree_view_column_set_alignment:
2451 * @tree_column: A `GtkTreeViewColumn`.
2452 * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
2453 *
2454 * Sets the alignment of the title or custom widget inside the column header.
2455 * The alignment determines its location inside the button -- 0.0 for left, 0.5
2456 * for center, 1.0 for right.
2457 **/
2458 void
gtk_tree_view_column_set_alignment(GtkTreeViewColumn * tree_column,float xalign)2459 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
2460 float xalign)
2461 {
2462 GtkTreeViewColumnPrivate *priv;
2463
2464 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2465
2466 priv = tree_column->priv;
2467
2468 xalign = CLAMP (xalign, 0.0, 1.0);
2469
2470 if (priv->xalign == xalign)
2471 return;
2472
2473 priv->xalign = xalign;
2474 gtk_tree_view_column_update_button (tree_column);
2475 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_ALIGNMENT]);
2476 }
2477
2478 /**
2479 * gtk_tree_view_column_get_alignment:
2480 * @tree_column: A `GtkTreeViewColumn`.
2481 *
2482 * Returns the current x alignment of @tree_column. This value can range
2483 * between 0.0 and 1.0.
2484 *
2485 * Returns: The current alignent of @tree_column.
2486 **/
2487 float
gtk_tree_view_column_get_alignment(GtkTreeViewColumn * tree_column)2488 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
2489 {
2490 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
2491
2492 return tree_column->priv->xalign;
2493 }
2494
2495 /**
2496 * gtk_tree_view_column_set_reorderable:
2497 * @tree_column: A `GtkTreeViewColumn`
2498 * @reorderable: %TRUE, if the column can be reordered.
2499 *
2500 * If @reorderable is %TRUE, then the column can be reordered by the end user
2501 * dragging the header.
2502 **/
2503 void
gtk_tree_view_column_set_reorderable(GtkTreeViewColumn * tree_column,gboolean reorderable)2504 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
2505 gboolean reorderable)
2506 {
2507 GtkTreeViewColumnPrivate *priv;
2508
2509 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2510
2511 priv = tree_column->priv;
2512
2513 /* if (reorderable)
2514 gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
2515
2516 if (priv->reorderable == (reorderable?TRUE:FALSE))
2517 return;
2518
2519 priv->reorderable = (reorderable?TRUE:FALSE);
2520 gtk_tree_view_column_update_button (tree_column);
2521 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_REORDERABLE]);
2522 }
2523
2524 /**
2525 * gtk_tree_view_column_get_reorderable:
2526 * @tree_column: A `GtkTreeViewColumn`
2527 *
2528 * Returns %TRUE if the @tree_column can be reordered by the user.
2529 *
2530 * Returns: %TRUE if the @tree_column can be reordered by the user.
2531 **/
2532 gboolean
gtk_tree_view_column_get_reorderable(GtkTreeViewColumn * tree_column)2533 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
2534 {
2535 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2536
2537 return tree_column->priv->reorderable;
2538 }
2539
2540
2541 /**
2542 * gtk_tree_view_column_set_sort_column_id:
2543 * @tree_column: a `GtkTreeViewColumn`
2544 * @sort_column_id: The @sort_column_id of the model to sort on.
2545 *
2546 * Sets the logical @sort_column_id that this column sorts on when this column
2547 * is selected for sorting. Doing so makes the column header clickable.
2548 **/
2549 void
gtk_tree_view_column_set_sort_column_id(GtkTreeViewColumn * tree_column,int sort_column_id)2550 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
2551 int sort_column_id)
2552 {
2553 GtkTreeViewColumnPrivate *priv;
2554
2555 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2556 g_return_if_fail (sort_column_id >= -1);
2557
2558 priv = tree_column->priv;
2559
2560 if (priv->sort_column_id == sort_column_id)
2561 return;
2562
2563 priv->sort_column_id = sort_column_id;
2564
2565 /* Handle unsetting the id */
2566 if (sort_column_id == -1)
2567 {
2568 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
2569
2570 if (priv->sort_clicked_signal)
2571 {
2572 g_signal_handler_disconnect (tree_column, priv->sort_clicked_signal);
2573 priv->sort_clicked_signal = 0;
2574 }
2575
2576 if (priv->sort_column_changed_signal)
2577 {
2578 g_signal_handler_disconnect (model, priv->sort_column_changed_signal);
2579 priv->sort_column_changed_signal = 0;
2580 }
2581
2582 gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
2583 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
2584 gtk_tree_view_column_set_clickable (tree_column, FALSE);
2585 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_SORT_COLUMN_ID]);
2586 return;
2587 }
2588
2589 gtk_tree_view_column_set_clickable (tree_column, TRUE);
2590
2591 if (! priv->sort_clicked_signal)
2592 priv->sort_clicked_signal = g_signal_connect (tree_column,
2593 "clicked",
2594 G_CALLBACK (gtk_tree_view_column_sort),
2595 NULL);
2596
2597 gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
2598 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_SORT_COLUMN_ID]);
2599 }
2600
2601 /**
2602 * gtk_tree_view_column_get_sort_column_id:
2603 * @tree_column: a `GtkTreeViewColumn`
2604 *
2605 * Gets the logical @sort_column_id that the model sorts on
2606 * when this column is selected for sorting.
2607 *
2608 * See [method@Gtk.TreeViewColumn.set_sort_column_id].
2609 *
2610 * Returns: the current @sort_column_id for this column, or -1 if
2611 * this column can’t be used for sorting
2612 */
2613 int
gtk_tree_view_column_get_sort_column_id(GtkTreeViewColumn * tree_column)2614 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
2615 {
2616 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2617
2618 return tree_column->priv->sort_column_id;
2619 }
2620
2621 /**
2622 * gtk_tree_view_column_set_sort_indicator:
2623 * @tree_column: a `GtkTreeViewColumn`
2624 * @setting: %TRUE to display an indicator that the column is sorted
2625 *
2626 * Call this function with a @setting of %TRUE to display an arrow in
2627 * the header button indicating the column is sorted. Call
2628 * gtk_tree_view_column_set_sort_order() to change the direction of
2629 * the arrow.
2630 *
2631 **/
2632 void
gtk_tree_view_column_set_sort_indicator(GtkTreeViewColumn * tree_column,gboolean setting)2633 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column,
2634 gboolean setting)
2635 {
2636 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2637
2638 setting = setting != FALSE;
2639
2640 if (setting == tree_column->priv->show_sort_indicator)
2641 return;
2642
2643 tree_column->priv->show_sort_indicator = setting;
2644 gtk_tree_view_column_update_button (tree_column);
2645 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_SORT_INDICATOR]);
2646 }
2647
2648 /**
2649 * gtk_tree_view_column_get_sort_indicator:
2650 * @tree_column: a `GtkTreeViewColumn`
2651 *
2652 * Gets the value set by gtk_tree_view_column_set_sort_indicator().
2653 *
2654 * Returns: whether the sort indicator arrow is displayed
2655 **/
2656 gboolean
gtk_tree_view_column_get_sort_indicator(GtkTreeViewColumn * tree_column)2657 gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column)
2658 {
2659 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2660
2661 return tree_column->priv->show_sort_indicator;
2662 }
2663
2664 /**
2665 * gtk_tree_view_column_set_sort_order:
2666 * @tree_column: a `GtkTreeViewColumn`
2667 * @order: sort order that the sort indicator should indicate
2668 *
2669 * Changes the appearance of the sort indicator.
2670 *
2671 * This does not actually sort the model. Use
2672 * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
2673 * support. This function is primarily for custom sorting behavior, and should
2674 * be used in conjunction with gtk_tree_sortable_set_sort_column_id() to do
2675 * that. For custom models, the mechanism will vary.
2676 *
2677 * The sort indicator changes direction to indicate normal sort or reverse sort.
2678 * Note that you must have the sort indicator enabled to see anything when
2679 * calling this function; see gtk_tree_view_column_set_sort_indicator().
2680 **/
2681 void
gtk_tree_view_column_set_sort_order(GtkTreeViewColumn * tree_column,GtkSortType order)2682 gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column,
2683 GtkSortType order)
2684 {
2685 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2686
2687 if (order == tree_column->priv->sort_order)
2688 return;
2689
2690 tree_column->priv->sort_order = order;
2691 gtk_tree_view_column_update_button (tree_column);
2692 g_object_notify_by_pspec (G_OBJECT (tree_column), tree_column_props[PROP_SORT_ORDER]);
2693 }
2694
2695 /**
2696 * gtk_tree_view_column_get_sort_order:
2697 * @tree_column: a `GtkTreeViewColumn`
2698 *
2699 * Gets the value set by gtk_tree_view_column_set_sort_order().
2700 *
2701 * Returns: the sort order the sort indicator is indicating
2702 **/
2703 GtkSortType
gtk_tree_view_column_get_sort_order(GtkTreeViewColumn * tree_column)2704 gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column)
2705 {
2706 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2707
2708 return tree_column->priv->sort_order;
2709 }
2710
2711 /**
2712 * gtk_tree_view_column_cell_set_cell_data:
2713 * @tree_column: A `GtkTreeViewColumn`.
2714 * @tree_model: The `GtkTreeModel` to get the cell renderers attributes from.
2715 * @iter: The `GtkTreeIter` to get the cell renderer’s attributes from.
2716 * @is_expander: %TRUE, if the row has children
2717 * @is_expanded: %TRUE, if the row has visible children
2718 *
2719 * Sets the cell renderer based on the @tree_model and @iter. That is, for
2720 * every attribute mapping in @tree_column, it will get a value from the set
2721 * column on the @iter, and use that value to set the attribute on the cell
2722 * renderer. This is used primarily by the `GtkTreeView`.
2723 **/
2724 void
gtk_tree_view_column_cell_set_cell_data(GtkTreeViewColumn * tree_column,GtkTreeModel * tree_model,GtkTreeIter * iter,gboolean is_expander,gboolean is_expanded)2725 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2726 GtkTreeModel *tree_model,
2727 GtkTreeIter *iter,
2728 gboolean is_expander,
2729 gboolean is_expanded)
2730 {
2731 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2732
2733 if (tree_model == NULL)
2734 return;
2735
2736 gtk_cell_area_apply_attributes (tree_column->priv->cell_area, tree_model, iter,
2737 is_expander, is_expanded);
2738 }
2739
2740 /**
2741 * gtk_tree_view_column_cell_get_size:
2742 * @tree_column: A `GtkTreeViewColumn`.
2743 * @x_offset: (out) (optional): location to return x offset of a cell relative to @cell_area
2744 * @y_offset: (out) (optional): location to return y offset of a cell relative to @cell_area
2745 * @width: (out) (optional): location to return width needed to render a cell
2746 * @height: (out) (optional): location to return height needed to render a cell
2747 *
2748 * Obtains the width and height needed to render the column. This is used
2749 * primarily by the `GtkTreeView`.
2750 **/
2751 void
gtk_tree_view_column_cell_get_size(GtkTreeViewColumn * tree_column,int * x_offset,int * y_offset,int * width,int * height)2752 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2753 int *x_offset,
2754 int *y_offset,
2755 int *width,
2756 int *height)
2757 {
2758 GtkTreeViewColumnPrivate *priv;
2759 int min_width = 0, min_height = 0;
2760
2761 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2762
2763 priv = tree_column->priv;
2764
2765 g_signal_handler_block (priv->cell_area_context,
2766 priv->context_changed_signal);
2767
2768 gtk_cell_area_get_preferred_width (priv->cell_area,
2769 priv->cell_area_context,
2770 priv->tree_view,
2771 NULL, NULL);
2772
2773 gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &min_width, NULL);
2774
2775 gtk_cell_area_get_preferred_height_for_width (priv->cell_area,
2776 priv->cell_area_context,
2777 priv->tree_view,
2778 min_width,
2779 &min_height,
2780 NULL);
2781
2782 g_signal_handler_unblock (priv->cell_area_context,
2783 priv->context_changed_signal);
2784
2785
2786 if (height)
2787 * height = min_height;
2788 if (width)
2789 * width = min_width;
2790
2791 }
2792
2793 /**
2794 * gtk_tree_view_column_cell_snapshot:
2795 * @tree_column: A `GtkTreeViewColumn`.
2796 * @snapshot: `GtkSnapshot` to draw to
2797 * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
2798 * @cell_area: area normally rendered by a cell renderer
2799 * @flags: flags that affect rendering
2800 *
2801 * Renders the cell contained by #tree_column. This is used primarily by the
2802 * `GtkTreeView`.
2803 **/
2804 void
gtk_tree_view_column_cell_snapshot(GtkTreeViewColumn * tree_column,GtkSnapshot * snapshot,const GdkRectangle * background_area,const GdkRectangle * cell_area,guint flags,gboolean draw_focus)2805 gtk_tree_view_column_cell_snapshot (GtkTreeViewColumn *tree_column,
2806 GtkSnapshot *snapshot,
2807 const GdkRectangle *background_area,
2808 const GdkRectangle *cell_area,
2809 guint flags,
2810 gboolean draw_focus)
2811 {
2812 GtkTreeViewColumnPrivate *priv;
2813
2814 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2815 g_return_if_fail (snapshot != NULL);
2816 g_return_if_fail (background_area != NULL);
2817 g_return_if_fail (cell_area != NULL);
2818
2819 priv = tree_column->priv;
2820
2821 gtk_cell_area_snapshot (priv->cell_area, priv->cell_area_context,
2822 priv->tree_view, snapshot,
2823 background_area, cell_area, flags,
2824 draw_focus);
2825 }
2826
2827 gboolean
_gtk_tree_view_column_cell_event(GtkTreeViewColumn * tree_column,GdkEvent * event,const GdkRectangle * cell_area,guint flags)2828 _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column,
2829 GdkEvent *event,
2830 const GdkRectangle *cell_area,
2831 guint flags)
2832 {
2833 GtkTreeViewColumnPrivate *priv;
2834
2835 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2836
2837 priv = tree_column->priv;
2838
2839 return gtk_cell_area_event (priv->cell_area,
2840 priv->cell_area_context,
2841 priv->tree_view,
2842 event,
2843 cell_area,
2844 flags);
2845 }
2846
2847 /**
2848 * gtk_tree_view_column_cell_is_visible:
2849 * @tree_column: A `GtkTreeViewColumn`
2850 *
2851 * Returns %TRUE if any of the cells packed into the @tree_column are visible.
2852 * For this to be meaningful, you must first initialize the cells with
2853 * gtk_tree_view_column_cell_set_cell_data()
2854 *
2855 * Returns: %TRUE, if any of the cells packed into the @tree_column are currently visible
2856 **/
2857 gboolean
gtk_tree_view_column_cell_is_visible(GtkTreeViewColumn * tree_column)2858 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
2859 {
2860 GList *list;
2861 GList *cells;
2862 GtkTreeViewColumnPrivate *priv;
2863
2864 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2865
2866 priv = tree_column->priv;
2867
2868 cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->cell_area));
2869 for (list = cells; list; list = list->next)
2870 {
2871 if (gtk_cell_renderer_get_visible (list->data))
2872 {
2873 g_list_free (cells);
2874 return TRUE;
2875 }
2876 }
2877
2878 g_list_free (cells);
2879
2880 return FALSE;
2881 }
2882
2883 /**
2884 * gtk_tree_view_column_focus_cell:
2885 * @tree_column: A `GtkTreeViewColumn`
2886 * @cell: A `GtkCellRenderer`
2887 *
2888 * Sets the current keyboard focus to be at @cell, if the column contains
2889 * 2 or more editable and activatable cells.
2890 **/
2891 void
gtk_tree_view_column_focus_cell(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell)2892 gtk_tree_view_column_focus_cell (GtkTreeViewColumn *tree_column,
2893 GtkCellRenderer *cell)
2894 {
2895 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2896 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
2897
2898 gtk_cell_area_set_focus_cell (tree_column->priv->cell_area, cell);
2899 }
2900
2901 void
_gtk_tree_view_column_cell_set_dirty(GtkTreeViewColumn * tree_column,gboolean install_handler)2902 _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column,
2903 gboolean install_handler)
2904 {
2905 GtkTreeViewColumnPrivate *priv = tree_column->priv;
2906
2907 priv->dirty = TRUE;
2908 priv->padding = 0;
2909 priv->width = 0;
2910
2911 /* Issue a manual reset on the context to have all
2912 * sizes re-requested for the context.
2913 */
2914 g_signal_handler_block (priv->cell_area_context,
2915 priv->context_changed_signal);
2916 gtk_cell_area_context_reset (priv->cell_area_context);
2917 g_signal_handler_unblock (priv->cell_area_context,
2918 priv->context_changed_signal);
2919
2920 if (priv->tree_view &&
2921 gtk_widget_get_realized (priv->tree_view))
2922 {
2923 _gtk_tree_view_install_mark_rows_col_dirty (GTK_TREE_VIEW (priv->tree_view), install_handler);
2924 gtk_widget_queue_resize (priv->tree_view);
2925 }
2926 }
2927
2928 gboolean
_gtk_tree_view_column_cell_get_dirty(GtkTreeViewColumn * tree_column)2929 _gtk_tree_view_column_cell_get_dirty (GtkTreeViewColumn *tree_column)
2930 {
2931 return tree_column->priv->dirty;
2932 }
2933
2934 /**
2935 * gtk_tree_view_column_cell_get_position:
2936 * @tree_column: a `GtkTreeViewColumn`
2937 * @cell_renderer: a `GtkCellRenderer`
2938 * @x_offset: (out) (optional): return location for the horizontal
2939 * position of @cell within @tree_column
2940 * @width: (out) (optional): return location for the width of @cell
2941 *
2942 * Obtains the horizontal position and size of a cell in a column.
2943 *
2944 * If the cell is not found in the column, @start_pos and @width
2945 * are not changed and %FALSE is returned.
2946 *
2947 * Returns: %TRUE if @cell belongs to @tree_column
2948 */
2949 gboolean
gtk_tree_view_column_cell_get_position(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell_renderer,int * x_offset,int * width)2950 gtk_tree_view_column_cell_get_position (GtkTreeViewColumn *tree_column,
2951 GtkCellRenderer *cell_renderer,
2952 int *x_offset,
2953 int *width)
2954 {
2955 GtkTreeViewColumnPrivate *priv;
2956 GdkRectangle cell_area;
2957 GdkRectangle allocation;
2958
2959 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2960 g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell_renderer), FALSE);
2961
2962 priv = tree_column->priv;
2963
2964 if (! gtk_cell_area_has_renderer (priv->cell_area, cell_renderer))
2965 return FALSE;
2966
2967 gtk_tree_view_get_background_area (GTK_TREE_VIEW (priv->tree_view),
2968 NULL, tree_column, &cell_area);
2969
2970 gtk_cell_area_get_cell_allocation (priv->cell_area,
2971 priv->cell_area_context,
2972 priv->tree_view,
2973 cell_renderer,
2974 &cell_area,
2975 &allocation);
2976
2977 if (x_offset)
2978 *x_offset = allocation.x - cell_area.x;
2979
2980 if (width)
2981 *width = allocation.width;
2982
2983 return TRUE;
2984 }
2985
2986 /**
2987 * gtk_tree_view_column_queue_resize:
2988 * @tree_column: A `GtkTreeViewColumn`
2989 *
2990 * Flags the column, and the cell renderers added to this column, to have
2991 * their sizes renegotiated.
2992 **/
2993 void
gtk_tree_view_column_queue_resize(GtkTreeViewColumn * tree_column)2994 gtk_tree_view_column_queue_resize (GtkTreeViewColumn *tree_column)
2995 {
2996 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2997
2998 if (tree_column->priv->tree_view)
2999 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
3000 }
3001
3002 /**
3003 * gtk_tree_view_column_get_tree_view:
3004 * @tree_column: A `GtkTreeViewColumn`
3005 *
3006 * Returns the `GtkTreeView` wherein @tree_column has been inserted.
3007 * If @column is currently not inserted in any tree view, %NULL is
3008 * returned.
3009 *
3010 * Returns: (nullable) (transfer none): The tree view wherein @column
3011 * has been inserted
3012 */
3013 GtkWidget *
gtk_tree_view_column_get_tree_view(GtkTreeViewColumn * tree_column)3014 gtk_tree_view_column_get_tree_view (GtkTreeViewColumn *tree_column)
3015 {
3016 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
3017
3018 return tree_column->priv->tree_view;
3019 }
3020
3021 /**
3022 * gtk_tree_view_column_get_button:
3023 * @tree_column: A `GtkTreeViewColumn`
3024 *
3025 * Returns the button used in the treeview column header
3026 *
3027 * Returns: (transfer none): The button for the column header.
3028 */
3029 GtkWidget *
gtk_tree_view_column_get_button(GtkTreeViewColumn * tree_column)3030 gtk_tree_view_column_get_button (GtkTreeViewColumn *tree_column)
3031 {
3032 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
3033
3034 return tree_column->priv->button;
3035 }
3036
3037 void
_gtk_tree_view_column_push_padding(GtkTreeViewColumn * column,int padding)3038 _gtk_tree_view_column_push_padding (GtkTreeViewColumn *column,
3039 int padding)
3040 {
3041 column->priv->padding = MAX (column->priv->padding, padding);
3042 }
3043
3044 int
_gtk_tree_view_column_get_requested_width(GtkTreeViewColumn * column)3045 _gtk_tree_view_column_get_requested_width (GtkTreeViewColumn *column)
3046 {
3047 int requested_width;
3048
3049 gtk_cell_area_context_get_preferred_width (column->priv->cell_area_context, &requested_width, NULL);
3050
3051 return requested_width + column->priv->padding;
3052 }
3053
3054 int
_gtk_tree_view_column_get_drag_x(GtkTreeViewColumn * column)3055 _gtk_tree_view_column_get_drag_x (GtkTreeViewColumn *column)
3056 {
3057 return column->priv->drag_x;
3058 }
3059
3060 GtkCellAreaContext *
_gtk_tree_view_column_get_context(GtkTreeViewColumn * column)3061 _gtk_tree_view_column_get_context (GtkTreeViewColumn *column)
3062 {
3063 return column->priv->cell_area_context;
3064 }
3065
3066 gboolean
_gtk_tree_view_column_coords_in_resize_rect(GtkTreeViewColumn * column,double x,double y)3067 _gtk_tree_view_column_coords_in_resize_rect (GtkTreeViewColumn *column,
3068 double x,
3069 double y)
3070 {
3071 GtkTreeViewColumnPrivate *priv = column->priv;
3072 graphene_rect_t button_bounds;
3073
3074 /* x and y are in treeview coordinates. */
3075
3076 if (!gtk_widget_get_realized (priv->button) ||
3077 !priv->resizable ||
3078 !priv->visible)
3079 return FALSE;
3080
3081 if (!gtk_widget_compute_bounds (priv->button, priv->tree_view, &button_bounds))
3082 return FALSE;
3083
3084 if (gtk_widget_get_direction (priv->tree_view) == GTK_TEXT_DIR_LTR)
3085 button_bounds.origin.x += button_bounds.size.width - TREE_VIEW_DRAG_WIDTH;
3086
3087 button_bounds.size.width = TREE_VIEW_DRAG_WIDTH;
3088
3089 return graphene_rect_contains_point (&button_bounds,
3090 &(graphene_point_t){x, y});
3091 }
3092