1/*
2 * Copyright © 2019 Benjamin Otte
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 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 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Benjamin Otte <otte@gnome.org>
18 */
19
20#include "config.h"
21
22#include "gtkcolumnviewlayoutprivate.h"
23
24#include "gtkcolumnviewcellprivate.h"
25#include "gtkcolumnviewcolumnprivate.h"
26#include "gtkcolumnviewprivate.h"
27#include "gtkcolumnviewtitleprivate.h"
28#include "gtkwidgetprivate.h"
29
30struct _GtkColumnViewLayout
31{
32 GtkLayoutManager parent_instance;
33
34 GtkColumnView *view; /* no reference */
35};
36
37G_DEFINE_TYPE (GtkColumnViewLayout, gtk_column_view_layout, GTK_TYPE_LAYOUT_MANAGER)
38
39static void
40gtk_column_view_layout_measure_along (GtkColumnViewLayout *self,
41 GtkWidget *widget,
42 int for_size,
43 int *minimum,
44 int *natural,
45 int *minimum_baseline,
46 int *natural_baseline)
47{
48 GtkOrientation orientation = GTK_ORIENTATION_VERTICAL;
49 GtkWidget *child;
50 guint i, n;
51 GtkRequestedSize *sizes = NULL;
52
53 if (for_size > -1)
54 {
55 n = g_list_model_get_n_items (list: gtk_column_view_get_columns (self: self->view));
56 sizes = g_newa (GtkRequestedSize, n);
57 gtk_column_view_distribute_width (self: self->view, width: for_size, sizes);
58 }
59
60 for (child = _gtk_widget_get_first_child (widget), i = 0;
61 child != NULL;
62 child = _gtk_widget_get_next_sibling (widget: child), i++)
63 {
64 int child_min = 0;
65 int child_nat = 0;
66 int child_min_baseline = -1;
67 int child_nat_baseline = -1;
68
69 if (!gtk_widget_should_layout (widget: child))
70 continue;
71
72 gtk_widget_measure (widget: child, orientation,
73 for_size: for_size > -1 ? sizes[i].minimum_size : -1,
74 minimum: &child_min, natural: &child_nat,
75 minimum_baseline: &child_min_baseline, natural_baseline: &child_nat_baseline);
76
77 *minimum = MAX (*minimum, child_min);
78 *natural = MAX (*natural, child_nat);
79
80 if (child_min_baseline > -1)
81 *minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
82 if (child_nat_baseline > -1)
83 *natural_baseline = MAX (*natural_baseline, child_nat_baseline);
84 }
85}
86
87static void
88gtk_column_view_layout_measure (GtkLayoutManager *layout,
89 GtkWidget *widget,
90 GtkOrientation orientation,
91 int for_size,
92 int *minimum,
93 int *natural,
94 int *minimum_baseline,
95 int *natural_baseline)
96{
97 GtkColumnViewLayout *self = GTK_COLUMN_VIEW_LAYOUT (ptr: layout);
98
99 if (orientation == GTK_ORIENTATION_HORIZONTAL)
100 {
101 gtk_column_view_measure_across (GTK_COLUMN_VIEW (self->view),
102 minimum,
103 natural);
104 }
105 else
106 {
107 gtk_column_view_layout_measure_along (self,
108 widget,
109 for_size,
110 minimum,
111 natural,
112 minimum_baseline,
113 natural_baseline);
114 }
115}
116
117static void
118gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager,
119 GtkWidget *widget,
120 int width,
121 int height,
122 int baseline)
123{
124 GtkWidget *child;
125
126 for (child = _gtk_widget_get_first_child (widget);
127 child != NULL;
128 child = _gtk_widget_get_next_sibling (widget: child))
129 {
130 GtkColumnViewColumn *column;
131 int col_x, col_width, min;
132
133 if (!gtk_widget_should_layout (widget: child))
134 continue;
135
136 if (GTK_IS_COLUMN_VIEW_CELL (child))
137 {
138 column = gtk_column_view_cell_get_column (GTK_COLUMN_VIEW_CELL (child));
139 gtk_column_view_column_get_allocation (self: column, offset: &col_x, size: &col_width);
140 }
141 else
142 {
143 column = gtk_column_view_title_get_column (GTK_COLUMN_VIEW_TITLE (child));
144 gtk_column_view_column_get_header_allocation (self: column, offset: &col_x, size: &col_width);
145 }
146
147 gtk_widget_measure (widget: child, orientation: GTK_ORIENTATION_HORIZONTAL, for_size: -1, minimum: &min, NULL, NULL, NULL);
148
149 gtk_widget_size_allocate (widget: child, allocation: &(GtkAllocation) { col_x, 0, MAX (min, col_width), height }, baseline);
150 }
151}
152
153static void
154gtk_column_view_layout_class_init (GtkColumnViewLayoutClass *klass)
155{
156 GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (ptr: klass);
157
158 layout_manager_class->measure = gtk_column_view_layout_measure;
159 layout_manager_class->allocate = gtk_column_view_layout_allocate;
160}
161
162static void
163gtk_column_view_layout_init (GtkColumnViewLayout *self)
164{
165}
166
167GtkLayoutManager *
168gtk_column_view_layout_new (GtkColumnView *view)
169{
170 GtkColumnViewLayout *result;
171
172 result = g_object_new (GTK_TYPE_COLUMN_VIEW_LAYOUT, NULL);
173
174 result->view = view;
175
176 return GTK_LAYOUT_MANAGER (ptr: result);
177}
178

source code of gtk/gtk/gtkcolumnviewlayout.c