Bug Summary

File:ctk/ctkgrid.c
Warning:line 1434, column 12
Access of 'request.lines' at an overflowing index, while it holds only 2 'struct _CtkGridLines' elements

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkgrid.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/ctk -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-12-18-090527-43637-1 -x c ctkgrid.c
1/* CTK - The GIMP Toolkit
2 * Copyright (C) 2010 Red Hat, Inc.
3 * Author: Matthias Clasen
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20
21#include <string.h>
22
23#include "ctkgrid.h"
24
25#include "ctkorientableprivate.h"
26#include "ctkrender.h"
27#include "ctksizerequest.h"
28#include "ctkwidgetprivate.h"
29#include "ctkcontainerprivate.h"
30#include "ctkcsscustomgadgetprivate.h"
31#include "ctkprivate.h"
32#include "ctkintl.h"
33
34
35/**
36 * SECTION:ctkgrid
37 * @Short_description: Pack widgets in rows and columns
38 * @Title: CtkGrid
39 * @See_also: #CtkBox
40 *
41 * CtkGrid is a container which arranges its child widgets in
42 * rows and columns, with arbitrary positions and horizontal/vertical spans.
43 *
44 * Children are added using ctk_grid_attach(). They can span multiple
45 * rows or columns. It is also possible to add a child next to an
46 * existing child, using ctk_grid_attach_next_to(). The behaviour of
47 * CtkGrid when several children occupy the same grid cell is undefined.
48 *
49 * CtkGrid can be used like a #CtkBox by just using ctk_container_add(),
50 * which will place children next to each other in the direction determined
51 * by the #CtkOrientable:orientation property. However, if all you want is a
52 * single row or column, then #CtkBox is the preferred widget.
53 *
54 * # CSS nodes
55 *
56 * CtkGrid uses a single CSS node with name grid.
57 */
58
59typedef struct _CtkGridChild CtkGridChild;
60typedef struct _CtkGridChildAttach CtkGridChildAttach;
61typedef struct _CtkGridRowProperties CtkGridRowProperties;
62typedef struct _CtkGridLine CtkGridLine;
63typedef struct _CtkGridLines CtkGridLines;
64typedef struct _CtkGridLineData CtkGridLineData;
65typedef struct _CtkGridRequest CtkGridRequest;
66
67struct _CtkGridChildAttach
68{
69 gint pos;
70 gint span;
71};
72
73struct _CtkGridRowProperties
74{
75 gint row;
76 CtkBaselinePosition baseline_position;
77};
78
79static const CtkGridRowProperties ctk_grid_row_properties_default = {
80 0,
81 CTK_BASELINE_POSITION_CENTER
82};
83
84struct _CtkGridChild
85{
86 CtkWidget *widget;
87 CtkGridChildAttach attach[2];
88};
89
90#define CHILD_LEFT(child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos) ((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos)
91#define CHILD_WIDTH(child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].span) ((child)->attach[CTK_ORIENTATION_HORIZONTAL].span)
92#define CHILD_TOP(child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos) ((child)->attach[CTK_ORIENTATION_VERTICAL].pos)
93#define CHILD_HEIGHT(child)((child)->attach[CTK_ORIENTATION_VERTICAL].span) ((child)->attach[CTK_ORIENTATION_VERTICAL].span)
94
95/* A CtkGridLineData struct contains row/column specific parts
96 * of the grid.
97 */
98struct _CtkGridLineData
99{
100 gint16 spacing;
101 guint homogeneous : 1;
102};
103
104struct _CtkGridPrivate
105{
106 GList *children;
107 GList *row_properties;
108
109 CtkCssGadget *gadget;
110
111 CtkOrientation orientation;
112 gint baseline_row;
113
114 CtkGridLineData linedata[2];
115};
116
117#define ROWS(priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL]) (&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])
118#define COLUMNS(priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL]) (&(priv)->linedata[CTK_ORIENTATION_VERTICAL])
119
120/* A CtkGridLine struct represents a single row or column
121 * during size requests
122 */
123struct _CtkGridLine
124{
125 gint minimum;
126 gint natural;
127 gint minimum_above;
128 gint minimum_below;
129 gint natural_above;
130 gint natural_below;
131
132 gint position;
133 gint allocation;
134 gint allocated_baseline;
135
136 guint need_expand : 1;
137 guint expand : 1;
138 guint empty : 1;
139};
140
141struct _CtkGridLines
142{
143 CtkGridLine *lines;
144 gint min, max;
145};
146
147struct _CtkGridRequest
148{
149 CtkGrid *grid;
150 CtkGridLines lines[2];
151};
152
153
154enum
155{
156 PROP_0,
157 PROP_ROW_SPACING,
158 PROP_COLUMN_SPACING,
159 PROP_ROW_HOMOGENEOUS,
160 PROP_COLUMN_HOMOGENEOUS,
161 PROP_BASELINE_ROW,
162 N_PROPERTIES,
163 PROP_ORIENTATION
164};
165
166static GParamSpec *obj_properties[N_PROPERTIES] = { NULL((void*)0), };
167
168enum
169{
170 CHILD_PROP_0,
171 CHILD_PROP_LEFT_ATTACH,
172 CHILD_PROP_TOP_ATTACH,
173 CHILD_PROP_WIDTH,
174 CHILD_PROP_HEIGHT,
175 N_CHILD_PROPERTIES
176};
177
178static GParamSpec *child_properties[N_CHILD_PROPERTIES] = { NULL((void*)0), };
179
180G_DEFINE_TYPE_WITH_CODE (CtkGrid, ctk_grid, CTK_TYPE_CONTAINER,static void ctk_grid_init (CtkGrid *self); static void ctk_grid_class_init
(CtkGridClass *klass); static GType ctk_grid_get_type_once (
void); static gpointer ctk_grid_parent_class = ((void*)0); static
gint CtkGrid_private_offset; static void ctk_grid_class_intern_init
(gpointer klass) { ctk_grid_parent_class = g_type_class_peek_parent
(klass); if (CtkGrid_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkGrid_private_offset); ctk_grid_class_init ((
CtkGridClass*) klass); } __attribute__ ((__unused__)) static inline
gpointer ctk_grid_get_instance_private (CtkGrid *self) { return
(((gpointer) ((guint8*) (self) + (glong) (CtkGrid_private_offset
)))); } GType ctk_grid_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_grid_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_grid_get_type_once (void) { GType
g_define_type_id = g_type_register_static_simple ((ctk_container_get_type
()), g_intern_static_string ("CtkGrid"), sizeof (CtkGridClass
), (GClassInitFunc)(void (*)(void)) ctk_grid_class_intern_init
, sizeof (CtkGrid), (GInstanceInitFunc)(void (*)(void)) ctk_grid_init
, (GTypeFlags) 0); { {{ CtkGrid_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkGridPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ((void*)0), ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (ctk_orientable_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
181 G_ADD_PRIVATE (CtkGrid)static void ctk_grid_init (CtkGrid *self); static void ctk_grid_class_init
(CtkGridClass *klass); static GType ctk_grid_get_type_once (
void); static gpointer ctk_grid_parent_class = ((void*)0); static
gint CtkGrid_private_offset; static void ctk_grid_class_intern_init
(gpointer klass) { ctk_grid_parent_class = g_type_class_peek_parent
(klass); if (CtkGrid_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkGrid_private_offset); ctk_grid_class_init ((
CtkGridClass*) klass); } __attribute__ ((__unused__)) static inline
gpointer ctk_grid_get_instance_private (CtkGrid *self) { return
(((gpointer) ((guint8*) (self) + (glong) (CtkGrid_private_offset
)))); } GType ctk_grid_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_grid_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_grid_get_type_once (void) { GType
g_define_type_id = g_type_register_static_simple ((ctk_container_get_type
()), g_intern_static_string ("CtkGrid"), sizeof (CtkGridClass
), (GClassInitFunc)(void (*)(void)) ctk_grid_class_intern_init
, sizeof (CtkGrid), (GInstanceInitFunc)(void (*)(void)) ctk_grid_init
, (GTypeFlags) 0); { {{ CtkGrid_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkGridPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ((void*)0), ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (ctk_orientable_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
182 G_IMPLEMENT_INTERFACE (CTK_TYPE_ORIENTABLE, NULL))static void ctk_grid_init (CtkGrid *self); static void ctk_grid_class_init
(CtkGridClass *klass); static GType ctk_grid_get_type_once (
void); static gpointer ctk_grid_parent_class = ((void*)0); static
gint CtkGrid_private_offset; static void ctk_grid_class_intern_init
(gpointer klass) { ctk_grid_parent_class = g_type_class_peek_parent
(klass); if (CtkGrid_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkGrid_private_offset); ctk_grid_class_init ((
CtkGridClass*) klass); } __attribute__ ((__unused__)) static inline
gpointer ctk_grid_get_instance_private (CtkGrid *self) { return
(((gpointer) ((guint8*) (self) + (glong) (CtkGrid_private_offset
)))); } GType ctk_grid_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_grid_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_grid_get_type_once (void) { GType
g_define_type_id = g_type_register_static_simple ((ctk_container_get_type
()), g_intern_static_string ("CtkGrid"), sizeof (CtkGridClass
), (GClassInitFunc)(void (*)(void)) ctk_grid_class_intern_init
, sizeof (CtkGrid), (GInstanceInitFunc)(void (*)(void)) ctk_grid_init
, (GTypeFlags) 0); { {{ CtkGrid_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkGridPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ((void*)0), ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (ctk_orientable_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
183
184
185static void ctk_grid_row_properties_free (CtkGridRowProperties *props);
186
187static void
188ctk_grid_get_property (GObject *object,
189 guint prop_id,
190 GValue *value,
191 GParamSpec *pspec)
192{
193 CtkGrid *grid = CTK_GRID (object)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_grid_get_type ()))))))
;
194 CtkGridPrivate *priv = grid->priv;
195
196 switch (prop_id)
197 {
198 case PROP_ORIENTATION:
199 g_value_set_enum (value, priv->orientation);
200 break;
201
202 case PROP_ROW_SPACING:
203 g_value_set_int (value, COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->spacing);
204 break;
205
206 case PROP_COLUMN_SPACING:
207 g_value_set_int (value, ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->spacing);
208 break;
209
210 case PROP_ROW_HOMOGENEOUS:
211 g_value_set_boolean (value, COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->homogeneous);
212 break;
213
214 case PROP_COLUMN_HOMOGENEOUS:
215 g_value_set_boolean (value, ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->homogeneous);
216 break;
217
218 case PROP_BASELINE_ROW:
219 g_value_set_int (value, priv->baseline_row);
220 break;
221
222 default:
223 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkgrid.c", 223, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
224 break;
225 }
226}
227
228static void
229ctk_grid_set_orientation (CtkGrid *grid,
230 CtkOrientation orientation)
231{
232 CtkGridPrivate *priv = grid->priv;
233
234 if (priv->orientation != orientation)
235 {
236 priv->orientation = orientation;
237 _ctk_orientable_set_style_classes (CTK_ORIENTABLE (grid)((((CtkOrientable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_orientable_get_type ()))))))
);
238
239 g_object_notify (G_OBJECT (grid)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), (((GType) ((20) << (2))))))))
, "orientation");
240 }
241}
242
243static void
244ctk_grid_set_property (GObject *object,
245 guint prop_id,
246 const GValue *value,
247 GParamSpec *pspec)
248{
249 CtkGrid *grid = CTK_GRID (object)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_grid_get_type ()))))))
;
250
251 switch (prop_id)
252 {
253 case PROP_ORIENTATION:
254 ctk_grid_set_orientation (grid, g_value_get_enum (value));
255 break;
256
257 case PROP_ROW_SPACING:
258 ctk_grid_set_row_spacing (grid, g_value_get_int (value));
259 break;
260
261 case PROP_COLUMN_SPACING:
262 ctk_grid_set_column_spacing (grid, g_value_get_int (value));
263 break;
264
265 case PROP_ROW_HOMOGENEOUS:
266 ctk_grid_set_row_homogeneous (grid, g_value_get_boolean (value));
267 break;
268
269 case PROP_COLUMN_HOMOGENEOUS:
270 ctk_grid_set_column_homogeneous (grid, g_value_get_boolean (value));
271 break;
272
273 case PROP_BASELINE_ROW:
274 ctk_grid_set_baseline_row (grid, g_value_get_int (value));
275 break;
276
277 default:
278 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkgrid.c", 278, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
279 break;
280 }
281}
282
283static CtkGridChild *
284find_grid_child (CtkGrid *grid,
285 CtkWidget *widget)
286{
287 CtkGridPrivate *priv = grid->priv;
288 CtkGridChild *child;
289 GList *list;
290
291 for (list = priv->children; list; list = list->next)
292 {
293 child = list->data;
294
295 if (child->widget == widget)
296 return child;
297 }
298
299 return NULL((void*)0);
300}
301
302static void
303ctk_grid_get_child_property (CtkContainer *container,
304 CtkWidget *child,
305 guint property_id,
306 GValue *value,
307 GParamSpec *pspec)
308{
309 CtkGrid *grid = CTK_GRID (container)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_grid_get_type ()))))))
;
310 CtkGridChild *grid_child;
311
312 grid_child = find_grid_child (grid, child);
313
314 if (grid_child == NULL((void*)0))
315 {
316 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkgrid.c", 316, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
317 return;
318 }
319
320 switch (property_id)
321 {
322 case CHILD_PROP_LEFT_ATTACH:
323 g_value_set_int (value, CHILD_LEFT (grid_child)((grid_child)->attach[CTK_ORIENTATION_HORIZONTAL].pos));
324 break;
325
326 case CHILD_PROP_TOP_ATTACH:
327 g_value_set_int (value, CHILD_TOP (grid_child)((grid_child)->attach[CTK_ORIENTATION_VERTICAL].pos));
328 break;
329
330 case CHILD_PROP_WIDTH:
331 g_value_set_int (value, CHILD_WIDTH (grid_child)((grid_child)->attach[CTK_ORIENTATION_HORIZONTAL].span));
332 break;
333
334 case CHILD_PROP_HEIGHT:
335 g_value_set_int (value, CHILD_HEIGHT (grid_child)((grid_child)->attach[CTK_ORIENTATION_VERTICAL].span));
336 break;
337
338 default:
339 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkgrid.c", 339, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
340 break;
341 }
342}
343
344static void
345ctk_grid_set_child_property (CtkContainer *container,
346 CtkWidget *child,
347 guint property_id,
348 const GValue *value,
349 GParamSpec *pspec)
350{
351 CtkGrid *grid = CTK_GRID (container)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_grid_get_type ()))))))
;
352 CtkGridChild *grid_child;
353
354 grid_child = find_grid_child (grid, child);
355
356 if (grid_child == NULL((void*)0))
357 {
358 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkgrid.c", 358, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
359 return;
360 }
361
362 switch (property_id)
363 {
364 case CHILD_PROP_LEFT_ATTACH:
365 CHILD_LEFT (grid_child)((grid_child)->attach[CTK_ORIENTATION_HORIZONTAL].pos) = g_value_get_int (value);
366 break;
367
368 case CHILD_PROP_TOP_ATTACH:
369 CHILD_TOP (grid_child)((grid_child)->attach[CTK_ORIENTATION_VERTICAL].pos) = g_value_get_int (value);
370 break;
371
372 case CHILD_PROP_WIDTH:
373 CHILD_WIDTH (grid_child)((grid_child)->attach[CTK_ORIENTATION_HORIZONTAL].span) = g_value_get_int (value);
374 break;
375
376 case CHILD_PROP_HEIGHT:
377 CHILD_HEIGHT (grid_child)((grid_child)->attach[CTK_ORIENTATION_VERTICAL].span) = g_value_get_int (value);
378 break;
379
380 default:
381 CTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec)do { GObject *_glib__object = (GObject*) ((container)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkgrid.c", 381, ("child property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
382 break;
383 }
384
385 if (_ctk_widget_get_visible (child) &&
386 _ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
387 ctk_widget_queue_resize (child);
388}
389
390static void
391ctk_grid_finalize (GObject *object)
392{
393 CtkGrid *grid = CTK_GRID (object)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_grid_get_type ()))))))
;
394 CtkGridPrivate *priv = grid->priv;
395
396 g_list_free_full (priv->row_properties, (GDestroyNotify)ctk_grid_row_properties_free);
397
398 g_clear_object (&priv->gadget)do { _Static_assert (sizeof *((&priv->gadget)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->gadget))) _pp = ((&priv->gadget)); __typeof__
(*((&priv->gadget))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
399
400 G_OBJECT_CLASS (ctk_grid_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_grid_parent_class)), (((GType) ((20) << (2))))
))))
->finalize (object);
401}
402
403static void
404grid_attach (CtkGrid *grid,
405 CtkWidget *widget,
406 gint left,
407 gint top,
408 gint width,
409 gint height)
410{
411 CtkGridPrivate *priv = grid->priv;
412 CtkGridChild *child;
413
414 child = g_slice_new (CtkGridChild)((CtkGridChild*) g_slice_alloc (sizeof (CtkGridChild)));
415 child->widget = widget;
416 CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos) = left;
417 CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos) = top;
418 CHILD_WIDTH (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].span) = width;
419 CHILD_HEIGHT (child)((child)->attach[CTK_ORIENTATION_VERTICAL].span) = height;
420
421 priv->children = g_list_prepend (priv->children, child);
422
423 ctk_widget_set_parent (widget, CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
424}
425
426/* Find the position 'touching' existing
427 * children. @orientation and @max determine
428 * from which direction to approach (horizontal
429 * + max = right, vertical + !max = top, etc).
430 * @op_pos, @op_span determine the rows/columns
431 * in which the touching has to happen.
432 */
433static gint
434find_attach_position (CtkGrid *grid,
435 CtkOrientation orientation,
436 gint op_pos,
437 gint op_span,
438 gboolean max)
439{
440 CtkGridPrivate *priv = grid->priv;
441 CtkGridChild *grid_child;
442 CtkGridChildAttach *attach;
443 CtkGridChildAttach *opposite;
444 GList *list;
445 gint pos;
446 gboolean hit;
447
448 if (max)
449 pos = -G_MAXINT2147483647;
450 else
451 pos = G_MAXINT2147483647;
452
453 hit = FALSE(0);
454
455 for (list = priv->children; list; list = list->next)
456 {
457 grid_child = list->data;
458
459 attach = &grid_child->attach[orientation];
460 opposite = &grid_child->attach[1 - orientation];
461
462 /* check if the ranges overlap */
463 if (opposite->pos <= op_pos + op_span && op_pos <= opposite->pos + opposite->span)
464 {
465 hit = TRUE(!(0));
466
467 if (max)
468 pos = MAX (pos, attach->pos + attach->span)(((pos) > (attach->pos + attach->span)) ? (pos) : (attach
->pos + attach->span))
;
469 else
470 pos = MIN (pos, attach->pos)(((pos) < (attach->pos)) ? (pos) : (attach->pos));
471 }
472 }
473
474 if (!hit)
475 pos = 0;
476
477 return pos;
478}
479
480static void
481ctk_grid_add (CtkContainer *container,
482 CtkWidget *child)
483{
484 CtkGrid *grid = CTK_GRID (container)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_grid_get_type ()))))))
;
485 CtkGridPrivate *priv = grid->priv;
486 gint pos[2] = { 0, 0 };
487
488 pos[priv->orientation] = find_attach_position (grid, priv->orientation, 0, 1, TRUE(!(0)));
489 grid_attach (grid, child, pos[0], pos[1], 1, 1);
490}
491
492static void
493ctk_grid_remove (CtkContainer *container,
494 CtkWidget *child)
495{
496 CtkGrid *grid = CTK_GRID (container)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_grid_get_type ()))))))
;
497 CtkGridPrivate *priv = grid->priv;
498 CtkGridChild *grid_child;
499 GList *list;
500
501 for (list = priv->children; list; list = list->next)
502 {
503 grid_child = list->data;
504
505 if (grid_child->widget == child)
506 {
507 gboolean was_visible = _ctk_widget_get_visible (child);
508
509 ctk_widget_unparent (child);
510
511 priv->children = g_list_remove (priv->children, grid_child);
512
513 g_slice_free (CtkGridChild, grid_child)do { if (1) g_slice_free1 (sizeof (CtkGridChild), (grid_child
)); else (void) ((CtkGridChild*) 0 == (grid_child)); } while (
0)
;
514
515 if (was_visible && _ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
516 ctk_widget_queue_resize (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
517
518 break;
519 }
520 }
521}
522
523static void
524ctk_grid_forall (CtkContainer *container,
525 gboolean include_internals G_GNUC_UNUSED__attribute__ ((__unused__)),
526 CtkCallback callback,
527 gpointer callback_data)
528{
529 CtkGrid *grid = CTK_GRID (container)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_grid_get_type ()))))))
;
530 CtkGridPrivate *priv = grid->priv;
531 CtkGridChild *child;
532 GList *list;
533
534 list = priv->children;
535 while (list)
536 {
537 child = list->data;
538 list = list->next;
539
540 (* callback) (child->widget, callback_data);
541 }
542}
543
544static GType
545ctk_grid_child_type (CtkContainer *container G_GNUC_UNUSED__attribute__ ((__unused__)))
546{
547 return CTK_TYPE_WIDGET(ctk_widget_get_type ());
548}
549
550/* Calculates the min and max numbers for both orientations.
551 */
552static void
553ctk_grid_request_count_lines (CtkGridRequest *request)
554{
555 CtkGridPrivate *priv = request->grid->priv;
556 CtkGridChild *child;
557 CtkGridChildAttach *attach;
558 GList *list;
559 gint min[2];
560 gint max[2];
561
562 min[0] = min[1] = G_MAXINT2147483647;
563 max[0] = max[1] = G_MININT(-2147483647 -1);
564
565 for (list = priv->children; list; list = list->next)
566 {
567 child = list->data;
568 attach = child->attach;
569
570 min[0] = MIN (min[0], attach[0].pos)(((min[0]) < (attach[0].pos)) ? (min[0]) : (attach[0].pos)
)
;
571 max[0] = MAX (max[0], attach[0].pos + attach[0].span)(((max[0]) > (attach[0].pos + attach[0].span)) ? (max[0]) :
(attach[0].pos + attach[0].span))
;
572 min[1] = MIN (min[1], attach[1].pos)(((min[1]) < (attach[1].pos)) ? (min[1]) : (attach[1].pos)
)
;
573 max[1] = MAX (max[1], attach[1].pos + attach[1].span)(((max[1]) > (attach[1].pos + attach[1].span)) ? (max[1]) :
(attach[1].pos + attach[1].span))
;
574 }
575
576 request->lines[0].min = min[0];
577 request->lines[0].max = max[0];
578 request->lines[1].min = min[1];
579 request->lines[1].max = max[1];
580}
581
582/* Sets line sizes to 0 and marks lines as expand
583 * if they have a non-spanning expanding child.
584 */
585static void
586ctk_grid_request_init (CtkGridRequest *request,
587 CtkOrientation orientation)
588{
589 CtkGridPrivate *priv = request->grid->priv;
590 CtkGridChild *child;
591 CtkGridChildAttach *attach;
592 CtkGridLines *lines;
593 GList *list;
594 gint i;
595
596 lines = &request->lines[orientation];
597
598 for (i = 0; i < lines->max - lines->min; i++)
599 {
600 lines->lines[i].minimum = 0;
601 lines->lines[i].natural = 0;
602 lines->lines[i].minimum_above = -1;
603 lines->lines[i].minimum_below = -1;
604 lines->lines[i].natural_above = -1;
605 lines->lines[i].natural_below = -1;
606 lines->lines[i].expand = FALSE(0);
607 lines->lines[i].empty = TRUE(!(0));
608 }
609
610 for (list = priv->children; list; list = list->next)
611 {
612 child = list->data;
613
614 attach = &child->attach[orientation];
615 if (attach->span == 1 && ctk_widget_compute_expand (child->widget, orientation))
616 lines->lines[attach->pos - lines->min].expand = TRUE(!(0));
617 }
618}
619
620/* Sums allocations for lines spanned by child and their spacing.
621 */
622static gint
623compute_allocation_for_child (CtkGridRequest *request,
624 CtkGridChild *child,
625 CtkOrientation orientation)
626{
627 CtkGridPrivate *priv = request->grid->priv;
628 CtkGridLineData *linedata;
629 CtkGridLines *lines;
630 CtkGridLine *line;
631 CtkGridChildAttach *attach;
632 gint size;
633 gint i;
634
635 linedata = &priv->linedata[orientation];
636 lines = &request->lines[orientation];
637 attach = &child->attach[orientation];
638
639 size = (attach->span - 1) * linedata->spacing;
640 for (i = 0; i < attach->span; i++)
641 {
642 line = &lines->lines[attach->pos - lines->min + i];
643 size += line->allocation;
644 }
645
646 return size;
647}
648
649static void
650compute_request_for_child (CtkGridRequest *request,
651 CtkGridChild *child,
652 CtkOrientation orientation,
653 gboolean contextual,
654 gint *minimum,
655 gint *natural,
656 gint *minimum_baseline,
657 gint *natural_baseline)
658{
659 if (minimum_baseline)
660 *minimum_baseline = -1;
661 if (natural_baseline)
662 *natural_baseline = -1;
663 if (contextual)
664 {
665 gint size;
666
667 size = compute_allocation_for_child (request, child, 1 - orientation);
668 if (orientation == CTK_ORIENTATION_HORIZONTAL)
669 ctk_widget_get_preferred_width_for_height (child->widget,
670 size,
671 minimum, natural);
672 else
673 ctk_widget_get_preferred_height_and_baseline_for_width (child->widget,
674 size,
675 minimum, natural,
676 minimum_baseline, natural_baseline);
677 }
678 else
679 {
680 if (orientation == CTK_ORIENTATION_HORIZONTAL)
681 ctk_widget_get_preferred_width (child->widget, minimum, natural);
682 else
683 ctk_widget_get_preferred_height_and_baseline_for_width (child->widget,
684 -1,
685 minimum, natural,
686 minimum_baseline, natural_baseline);
687 }
688}
689
690/* Sets requisition to max. of non-spanning children.
691 * If contextual is TRUE, requires allocations of
692 * lines in the opposite orientation to be set.
693 */
694static void
695ctk_grid_request_non_spanning (CtkGridRequest *request,
696 CtkOrientation orientation,
697 gboolean contextual)
698{
699 CtkGridPrivate *priv = request->grid->priv;
700 CtkGridChild *child;
701 CtkGridChildAttach *attach;
702 CtkGridLines *lines;
703 CtkGridLine *line;
704 GList *list;
705 gint i;
706 CtkBaselinePosition baseline_pos;
707 gint minimum, minimum_baseline;
708 gint natural, natural_baseline;
709
710 lines = &request->lines[orientation];
711
712 for (list = priv->children; list; list = list->next)
713 {
714 child = list->data;
715
716 if (!_ctk_widget_get_visible (child->widget))
717 continue;
718
719 attach = &child->attach[orientation];
720 if (attach->span != 1)
721 continue;
722
723 compute_request_for_child (request, child, orientation, contextual, &minimum, &natural, &minimum_baseline, &natural_baseline);
724
725 line = &lines->lines[attach->pos - lines->min];
726
727 if (minimum_baseline != -1)
728 {
729 line->minimum_above = MAX (line->minimum_above, minimum_baseline)(((line->minimum_above) > (minimum_baseline)) ? (line->
minimum_above) : (minimum_baseline))
;
730 line->minimum_below = MAX (line->minimum_below, minimum - minimum_baseline)(((line->minimum_below) > (minimum - minimum_baseline))
? (line->minimum_below) : (minimum - minimum_baseline))
;
731 line->natural_above = MAX (line->natural_above, natural_baseline)(((line->natural_above) > (natural_baseline)) ? (line->
natural_above) : (natural_baseline))
;
732 line->natural_below = MAX (line->natural_below, natural - natural_baseline)(((line->natural_below) > (natural - natural_baseline))
? (line->natural_below) : (natural - natural_baseline))
;
733 }
734 else
735 {
736 line->minimum = MAX (line->minimum, minimum)(((line->minimum) > (minimum)) ? (line->minimum) : (
minimum))
;
737 line->natural = MAX (line->natural, natural)(((line->natural) > (natural)) ? (line->natural) : (
natural))
;
738 }
739 }
740
741 for (i = 0; i < lines->max - lines->min; i++)
742 {
743 line = &lines->lines[i];
744
745 if (line->minimum_above != -1)
746 {
747 line->minimum = MAX (line->minimum, line->minimum_above + line->minimum_below)(((line->minimum) > (line->minimum_above + line->
minimum_below)) ? (line->minimum) : (line->minimum_above
+ line->minimum_below))
;
748 line->natural = MAX (line->natural, line->natural_above + line->natural_below)(((line->natural) > (line->natural_above + line->
natural_below)) ? (line->natural) : (line->natural_above
+ line->natural_below))
;
749
750 baseline_pos = ctk_grid_get_row_baseline_position (request->grid, i + lines->min);
751
752 switch (baseline_pos)
753 {
754 case CTK_BASELINE_POSITION_TOP:
755 line->minimum_above += 0;
756 line->minimum_below += line->minimum - (line->minimum_above + line->minimum_below);
757 line->natural_above += 0;
758 line->natural_below += line->natural - (line->natural_above + line->natural_below);
759 break;
760 case CTK_BASELINE_POSITION_CENTER:
761 line->minimum_above += (line->minimum - (line->minimum_above + line->minimum_below))/2;
762 line->minimum_below += (line->minimum - (line->minimum_above + line->minimum_below))/2;
763 line->natural_above += (line->natural - (line->natural_above + line->natural_below))/2;
764 line->natural_below += (line->natural - (line->natural_above + line->natural_below))/2;
765 break;
766 case CTK_BASELINE_POSITION_BOTTOM:
767 line->minimum_above += line->minimum - (line->minimum_above + line->minimum_below);
768 line->minimum_below += 0;
769 line->natural_above += line->natural - (line->natural_above + line->natural_below);
770 line->natural_below += 0;
771 break;
772 }
773 }
774 }
775}
776
777/* Enforce homogeneous sizes.
778 */
779static void
780ctk_grid_request_homogeneous (CtkGridRequest *request,
781 CtkOrientation orientation)
782{
783 CtkGridPrivate *priv = request->grid->priv;
784 CtkGridLineData *linedata;
785 CtkGridLines *lines;
786 gint minimum, natural;
787 gint i;
788
789 linedata = &priv->linedata[orientation];
790 lines = &request->lines[orientation];
791
792 if (!linedata->homogeneous)
793 return;
794
795 minimum = 0;
796 natural = 0;
797
798 for (i = 0; i < lines->max - lines->min; i++)
799 {
800 minimum = MAX (minimum, lines->lines[i].minimum)(((minimum) > (lines->lines[i].minimum)) ? (minimum) : (
lines->lines[i].minimum))
;
801 natural = MAX (natural, lines->lines[i].natural)(((natural) > (lines->lines[i].natural)) ? (natural) : (
lines->lines[i].natural))
;
802 }
803
804 for (i = 0; i < lines->max - lines->min; i++)
805 {
806 lines->lines[i].minimum = minimum;
807 lines->lines[i].natural = natural;
808 /* TODO: Do we want to adjust the baseline here too?
809 * And if so, also in the homogenous resize.
810 */
811 }
812}
813
814/* Deals with spanning children.
815 * Requires expand fields of lines to be set for
816 * non-spanning children.
817 */
818static void
819ctk_grid_request_spanning (CtkGridRequest *request,
820 CtkOrientation orientation,
821 gboolean contextual)
822{
823 CtkGridPrivate *priv = request->grid->priv;
824 GList *list;
825 CtkGridChild *child;
826 CtkGridChildAttach *attach;
827 CtkGridLineData *linedata;
828 CtkGridLines *lines;
829 CtkGridLine *line;
830 gint minimum;
831 gint natural;
832 gint span_minimum;
833 gint span_natural;
834 gint span_expand;
835 gboolean force_expand;
836 gint extra;
837 gint expand;
838 gint line_extra;
839 gint i;
840
841 linedata = &priv->linedata[orientation];
842 lines = &request->lines[orientation];
843
844 for (list = priv->children; list; list = list->next)
845 {
846 child = list->data;
847
848 if (!_ctk_widget_get_visible (child->widget))
849 continue;
850
851 attach = &child->attach[orientation];
852 if (attach->span == 1)
853 continue;
854
855 /* We ignore baselines for spanning children */
856 compute_request_for_child (request, child, orientation, contextual, &minimum, &natural, NULL((void*)0), NULL((void*)0));
857
858 span_minimum = (attach->span - 1) * linedata->spacing;
859 span_natural = (attach->span - 1) * linedata->spacing;
860 span_expand = 0;
861 force_expand = FALSE(0);
862 for (i = 0; i < attach->span; i++)
863 {
864 line = &lines->lines[attach->pos - lines->min + i];
865 span_minimum += line->minimum;
866 span_natural += line->natural;
867 if (line->expand)
868 span_expand += 1;
869 }
870 if (span_expand == 0)
871 {
872 span_expand = attach->span;
873 force_expand = TRUE(!(0));
874 }
875
876 /* If we need to request more space for this child to fill
877 * its requisition, then divide up the needed space amongst the
878 * lines it spans, favoring expandable lines if any.
879 *
880 * When doing homogeneous allocation though, try to keep the
881 * line allocations even, since we're going to force them to
882 * be the same anyway, and we don't want to introduce unnecessary
883 * extra space.
884 */
885 if (span_minimum < minimum)
886 {
887 if (linedata->homogeneous)
888 {
889 gint total, m;
890
891 total = minimum - (attach->span - 1) * linedata->spacing;
892 m = total / attach->span + (total % attach->span ? 1 : 0);
893 for (i = 0; i < attach->span; i++)
894 {
895 line = &lines->lines[attach->pos - lines->min + i];
896 line->minimum = MAX(line->minimum, m)(((line->minimum) > (m)) ? (line->minimum) : (m));
897 }
898 }
899 else
900 {
901 extra = minimum - span_minimum;
902 expand = span_expand;
903 for (i = 0; i < attach->span; i++)
904 {
905 line = &lines->lines[attach->pos - lines->min + i];
906 if (force_expand || line->expand)
907 {
908 line_extra = extra / expand;
909 line->minimum += line_extra;
910 extra -= line_extra;
911 expand -= 1;
912 }
913 }
914 }
915 }
916
917 if (span_natural < natural)
918 {
919 if (linedata->homogeneous)
920 {
921 gint total, n;
922
923 total = natural - (attach->span - 1) * linedata->spacing;
924 n = total / attach->span + (total % attach->span ? 1 : 0);
925 for (i = 0; i < attach->span; i++)
926 {
927 line = &lines->lines[attach->pos - lines->min + i];
928 line->natural = MAX(line->natural, n)(((line->natural) > (n)) ? (line->natural) : (n));
929 }
930 }
931 else
932 {
933 extra = natural - span_natural;
934 expand = span_expand;
935 for (i = 0; i < attach->span; i++)
936 {
937 line = &lines->lines[attach->pos - lines->min + i];
938 if (force_expand || line->expand)
939 {
940 line_extra = extra / expand;
941 line->natural += line_extra;
942 extra -= line_extra;
943 expand -= 1;
944 }
945 }
946 }
947 }
948 }
949}
950
951/* Marks empty and expanding lines and counts them.
952 */
953static void
954ctk_grid_request_compute_expand (CtkGridRequest *request,
955 CtkOrientation orientation,
956 gint min,
957 gint max,
958 gint *nonempty_lines,
959 gint *expand_lines)
960{
961 CtkGridPrivate *priv = request->grid->priv;
962 CtkGridChild *child;
963 CtkGridChildAttach *attach;
964 GList *list;
965 gint i;
966 CtkGridLines *lines;
967 CtkGridLine *line;
968 gboolean has_expand;
969 gint expand;
970 gint empty;
971
972 lines = &request->lines[orientation];
973
974 min = MAX (min, lines->min)(((min) > (lines->min)) ? (min) : (lines->min));
975 max = MIN (max, lines->max)(((max) < (lines->max)) ? (max) : (lines->max));
976
977 for (i = min - lines->min; i < max - lines->min; i++)
978 {
979 lines->lines[i].need_expand = FALSE(0);
980 lines->lines[i].expand = FALSE(0);
981 lines->lines[i].empty = TRUE(!(0));
982 }
983
984 for (list = priv->children; list; list = list->next)
985 {
986 child = list->data;
987
988 if (!_ctk_widget_get_visible (child->widget))
989 continue;
990
991 attach = &child->attach[orientation];
992 if (attach->span != 1)
993 continue;
994
995 if (attach->pos >= max || attach->pos < min)
996 continue;
997
998 line = &lines->lines[attach->pos - lines->min];
999 line->empty = FALSE(0);
1000 if (ctk_widget_compute_expand (child->widget, orientation))
1001 line->expand = TRUE(!(0));
1002 }
1003
1004 for (list = priv->children; list; list = list->next)
1005 {
1006 child = list->data;
1007
1008 if (!_ctk_widget_get_visible (child->widget))
1009 continue;
1010
1011 attach = &child->attach[orientation];
1012 if (attach->span == 1)
1013 continue;
1014
1015 has_expand = FALSE(0);
1016 for (i = 0; i < attach->span; i++)
1017 {
1018 line = &lines->lines[attach->pos - lines->min + i];
1019
1020 if (line->expand)
1021 has_expand = TRUE(!(0));
1022
1023 if (attach->pos + i >= max || attach->pos + 1 < min)
1024 continue;
1025
1026 line->empty = FALSE(0);
1027 }
1028
1029 if (!has_expand && ctk_widget_compute_expand (child->widget, orientation))
1030 {
1031 for (i = 0; i < attach->span; i++)
1032 {
1033 if (attach->pos + i >= max || attach->pos + 1 < min)
1034 continue;
1035
1036 line = &lines->lines[attach->pos - lines->min + i];
1037 line->need_expand = TRUE(!(0));
1038 }
1039 }
1040 }
1041
1042 empty = 0;
1043 expand = 0;
1044 for (i = min - lines->min; i < max - lines->min; i++)
1045 {
1046 line = &lines->lines[i];
1047
1048 if (line->need_expand)
1049 line->expand = TRUE(!(0));
1050
1051 if (line->empty)
1052 empty += 1;
1053
1054 if (line->expand)
1055 expand += 1;
1056 }
1057
1058 if (nonempty_lines)
1059 *nonempty_lines = max - min - empty;
1060
1061 if (expand_lines)
1062 *expand_lines = expand;
1063}
1064
1065/* Sums the minimum and natural fields of lines and their spacing.
1066 */
1067static void
1068ctk_grid_request_sum (CtkGridRequest *request,
1069 CtkOrientation orientation,
1070 gint *minimum,
1071 gint *natural,
1072 gint *minimum_baseline,
1073 gint *natural_baseline)
1074{
1075 CtkGridPrivate *priv = request->grid->priv;
1076 CtkGridLineData *linedata;
1077 CtkGridLines *lines;
1078 gint i;
1079 gint min, nat;
1080 gint nonempty;
1081
1082 ctk_grid_request_compute_expand (request, orientation, G_MININT(-2147483647 -1), G_MAXINT2147483647, &nonempty, NULL((void*)0));
1083
1084 linedata = &priv->linedata[orientation];
1085 lines = &request->lines[orientation];
1086
1087 min = 0;
1088 nat = 0;
1089 for (i = 0; i < lines->max - lines->min; i++)
1090 {
1091 if (orientation == CTK_ORIENTATION_VERTICAL &&
1092 lines->min + i == priv->baseline_row &&
1093 lines->lines[i].minimum_above != -1)
1094 {
1095 if (minimum_baseline)
1096 *minimum_baseline = min + lines->lines[i].minimum_above;
1097 if (natural_baseline)
1098 *natural_baseline = nat + lines->lines[i].natural_above;
1099 }
1100
1101 min += lines->lines[i].minimum;
1102 nat += lines->lines[i].natural;
1103
1104 if (!lines->lines[i].empty)
1105 {
1106 min += linedata->spacing;
1107 nat += linedata->spacing;
1108 }
1109 }
1110
1111 /* Remove last spacing, if any was applied */
1112 if (nonempty > 0)
1113 {
1114 min -= linedata->spacing;
1115 nat -= linedata->spacing;
1116 }
1117
1118 *minimum = min;
1119 *natural = nat;
1120}
1121
1122/* Computes minimum and natural fields of lines.
1123 * When contextual is TRUE, requires allocation of
1124 * lines in the opposite orientation to be set.
1125 */
1126static void
1127ctk_grid_request_run (CtkGridRequest *request,
1128 CtkOrientation orientation,
1129 gboolean contextual)
1130{
1131 ctk_grid_request_init (request, orientation);
1132 ctk_grid_request_non_spanning (request, orientation, contextual);
1133 ctk_grid_request_homogeneous (request, orientation);
1134 ctk_grid_request_spanning (request, orientation, contextual);
1135 ctk_grid_request_homogeneous (request, orientation);
1136}
1137
1138static void
1139ctk_grid_distribute_non_homogeneous (CtkGridLines *lines,
1140 gint nonempty,
1141 gint expand,
1142 gint size,
1143 gint min,
1144 gint max)
1145{
1146 CtkRequestedSize *sizes;
1147 CtkGridLine *line;
1148 gint extra;
1149 gint rest;
1150 int i, j;
1151
1152 if (nonempty == 0)
1153 return;
1154
1155 sizes = g_newa (CtkRequestedSize, nonempty)((CtkRequestedSize*) __builtin_alloca (sizeof (CtkRequestedSize
) * (gsize) (nonempty)))
;
1156
1157 j = 0;
1158 for (i = min - lines->min; i < max - lines->min; i++)
1159 {
1160 line = &lines->lines[i];
1161 if (line->empty)
1162 continue;
1163
1164 size -= line->minimum;
1165
1166 sizes[j].minimum_size = line->minimum;
1167 sizes[j].natural_size = line->natural;
1168 sizes[j].data = line;
1169 j++;
1170 }
1171
1172 size = ctk_distribute_natural_allocation (MAX (0, size)(((0) > (size)) ? (0) : (size)), nonempty, sizes);
1173
1174 if (expand > 0)
1175 {
1176 extra = size / expand;
1177 rest = size % expand;
1178 }
1179 else
1180 {
1181 extra = 0;
1182 rest = 0;
1183 }
1184
1185 j = 0;
1186 for (i = min - lines->min; i < max - lines->min; i++)
1187 {
1188 line = &lines->lines[i];
1189 if (line->empty)
1190 continue;
1191
1192 g_assert (line == sizes[j].data)do { if (line == sizes[j].data) ; else g_assertion_message_expr
("Ctk", "ctkgrid.c", 1192, ((const char*) (__func__)), "line == sizes[j].data"
); } while (0)
;
1193
1194 line->allocation = sizes[j].minimum_size;
1195 if (line->expand)
1196 {
1197 line->allocation += extra;
1198 if (rest > 0)
1199 {
1200 line->allocation += 1;
1201 rest -= 1;
1202 }
1203 }
1204
1205 j++;
1206 }
1207}
1208
1209/* Requires that the minimum and natural fields of lines
1210 * have been set, computes the allocation field of lines
1211 * by distributing total_size among lines.
1212 */
1213static void
1214ctk_grid_request_allocate (CtkGridRequest *request,
1215 CtkOrientation orientation,
1216 gint total_size)
1217{
1218 CtkGridPrivate *priv = request->grid->priv;
1219 CtkGridLineData *linedata;
1220 CtkGridLines *lines;
1221 CtkGridLine *line;
1222 gint nonempty1, nonempty2;
1223 gint expand1, expand2;
1224 gint i;
1225 CtkBaselinePosition baseline_pos;
1226 gint baseline;
1227 gint extra, extra2;
1228 gint rest;
1229 gint size1, size2;
1230 gint split, split_pos;
1231
1232 linedata = &priv->linedata[orientation];
1233 lines = &request->lines[orientation];
1234
1235 baseline = ctk_widget_get_allocated_baseline (CTK_WIDGET (request->grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((request->grid)), ((ctk_widget_get_type ()))))))
);
1236
1237 if (orientation == CTK_ORIENTATION_VERTICAL && baseline != -1 &&
1238 priv->baseline_row >= lines->min && priv->baseline_row < lines->max &&
1239 lines->lines[priv->baseline_row - lines->min].minimum_above != -1)
1240 {
1241 split = priv->baseline_row;
1242 split_pos = baseline - lines->lines[priv->baseline_row - lines->min].minimum_above;
1243 ctk_grid_request_compute_expand (request, orientation, lines->min, split, &nonempty1, &expand1);
1244 ctk_grid_request_compute_expand (request, orientation, split, lines->max, &nonempty2, &expand2);
1245
1246 if (nonempty2 > 0)
1247 {
1248 size1 = split_pos - (nonempty1) * linedata->spacing;
1249 size2 = (total_size - split_pos) - (nonempty2 - 1) * linedata->spacing;
1250 }
1251 else
1252 {
1253 size1 = total_size - (nonempty1 - 1) * linedata->spacing;
1254 size2 = 0;
1255 }
1256 }
1257 else
1258 {
1259 ctk_grid_request_compute_expand (request, orientation, lines->min, lines->max, &nonempty1, &expand1);
1260 nonempty2 = expand2 = 0;
1261 split = lines->max;
1262
1263 size1 = total_size - (nonempty1 - 1) * linedata->spacing;
1264 size2 = 0;
1265 }
1266
1267 if (nonempty1 == 0 && nonempty2 == 0)
1268 return;
1269
1270 if (linedata->homogeneous)
1271 {
1272 if (nonempty1 > 0)
1273 {
1274 extra = size1 / nonempty1;
1275 rest = size1 % nonempty1;
1276 }
1277 else
1278 {
1279 extra = 0;
1280 rest = 0;
1281 }
1282 if (nonempty2 > 0)
1283 {
1284 extra2 = size2 / nonempty2;
1285 if (extra2 < extra || nonempty1 == 0)
1286 {
1287 extra = extra2;
1288 rest = size2 % nonempty2;
1289 }
1290 }
1291
1292 for (i = 0; i < lines->max - lines->min; i++)
1293 {
1294 line = &lines->lines[i];
1295 if (line->empty)
1296 continue;
1297
1298 line->allocation = extra;
1299 if (rest > 0)
1300 {
1301 line->allocation += 1;
1302 rest -= 1;
1303 }
1304 }
1305 }
1306 else
1307 {
1308 ctk_grid_distribute_non_homogeneous (lines,
1309 nonempty1,
1310 expand1,
1311 size1,
1312 lines->min,
1313 split);
1314 ctk_grid_distribute_non_homogeneous (lines,
1315 nonempty2,
1316 expand2,
1317 size2,
1318 split,
1319 lines->max);
1320 }
1321
1322 for (i = 0; i < lines->max - lines->min; i++)
1323 {
1324 line = &lines->lines[i];
1325 if (line->empty)
1326 continue;
1327
1328 if (line->minimum_above != -1)
1329 {
1330 /* Note: This is overridden in ctk_grid_request_position for the allocated baseline */
1331 baseline_pos = ctk_grid_get_row_baseline_position (request->grid, i + lines->min);
1332
1333 switch (baseline_pos)
1334 {
1335 case CTK_BASELINE_POSITION_TOP:
1336 line->allocated_baseline =
1337 line->minimum_above;
1338 break;
1339 case CTK_BASELINE_POSITION_CENTER:
1340 line->allocated_baseline =
1341 line->minimum_above +
1342 (line->allocation - (line->minimum_above + line->minimum_below)) / 2;
1343 break;
1344 case CTK_BASELINE_POSITION_BOTTOM:
1345 line->allocated_baseline =
1346 line->allocation - line->minimum_below;
1347 break;
1348 }
1349 }
1350 else
1351 line->allocated_baseline = -1;
1352 }
1353}
1354
1355/* Computes the position fields from allocation and spacing.
1356 */
1357static void
1358ctk_grid_request_position (CtkGridRequest *request,
1359 CtkOrientation orientation)
1360{
1361 CtkGridPrivate *priv = request->grid->priv;
1362 CtkGridLineData *linedata;
1363 CtkGridLines *lines;
1364 CtkGridLine *line;
1365 gint position, old_position;
1366 int allocated_baseline;
1367 gint i, j;
1368
1369 linedata = &priv->linedata[orientation];
1370 lines = &request->lines[orientation];
1371
1372 allocated_baseline = ctk_widget_get_allocated_baseline (CTK_WIDGET(request->grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((request->grid)), ((ctk_widget_get_type ()))))))
);
1373
1374 position = 0;
1375 for (i = 0; i < lines->max - lines->min; i++)
1376 {
1377 line = &lines->lines[i];
1378
1379 if (orientation == CTK_ORIENTATION_VERTICAL &&
1380 i + lines->min == priv->baseline_row &&
1381 allocated_baseline != -1 &&
1382 lines->lines[i].minimum_above != -1)
1383 {
1384 old_position = position;
1385 position = allocated_baseline - line->minimum_above;
1386
1387 /* Back-patch previous rows */
1388 for (j = 0; j < i; j++)
1389 {
1390 if (!lines->lines[j].empty)
1391 lines->lines[j].position += position - old_position;
1392 }
1393 }
1394
1395 if (!line->empty)
1396 {
1397 line->position = position;
1398 position += line->allocation + linedata->spacing;
1399
1400 if (orientation == CTK_ORIENTATION_VERTICAL &&
1401 i + lines->min == priv->baseline_row &&
1402 allocated_baseline != -1 &&
1403 lines->lines[i].minimum_above != -1)
1404 line->allocated_baseline = allocated_baseline - line->position;
1405 }
1406 }
1407}
1408
1409static void
1410ctk_grid_get_size (CtkGrid *grid,
1411 CtkOrientation orientation,
1412 gint *minimum,
1413 gint *natural,
1414 gint *minimum_baseline,
1415 gint *natural_baseline)
1416{
1417 CtkGridRequest request;
1418 CtkGridLines *lines;
1419
1420 *minimum = 0;
1421 *natural = 0;
1422
1423 if (minimum_baseline)
4
Assuming 'minimum_baseline' is null
5
Taking false branch
1424 *minimum_baseline = -1;
1425
1426 if (natural_baseline)
6
Assuming 'natural_baseline' is null
7
Taking false branch
1427 *natural_baseline = -1;
1428
1429 if (grid->priv->children == NULL((void*)0))
8
Assuming field 'children' is not equal to NULL
9
Taking false branch
1430 return;
1431
1432 request.grid = grid;
1433 ctk_grid_request_count_lines (&request);
1434 lines = &request.lines[orientation];
10
Access of 'request.lines' at an overflowing index, while it holds only 2 'struct _CtkGridLines' elements
1435 lines->lines = g_newa (CtkGridLine, lines->max - lines->min)((CtkGridLine*) __builtin_alloca (sizeof (CtkGridLine) * (gsize
) (lines->max - lines->min)))
;
1436 memset (lines->lines, 0, (lines->max - lines->min) * sizeof (CtkGridLine));
1437
1438 ctk_grid_request_run (&request, orientation, FALSE(0));
1439 ctk_grid_request_sum (&request, orientation, minimum, natural,
1440 minimum_baseline, natural_baseline);
1441}
1442
1443static void
1444ctk_grid_get_size_for_size (CtkGrid *grid,
1445 CtkOrientation orientation,
1446 gint size,
1447 gint *minimum,
1448 gint *natural,
1449 gint *minimum_baseline,
1450 gint *natural_baseline)
1451{
1452 CtkGridRequest request;
1453 CtkGridLines *lines;
1454 gint min_size, nat_size;
1455
1456 *minimum = 0;
1457 *natural = 0;
1458
1459 if (minimum_baseline)
1460 *minimum_baseline = -1;
1461
1462 if (natural_baseline)
1463 *natural_baseline = -1;
1464
1465 if (grid->priv->children == NULL((void*)0))
1466 return;
1467
1468 request.grid = grid;
1469 ctk_grid_request_count_lines (&request);
1470 lines = &request.lines[0];
1471 lines->lines = g_newa (CtkGridLine, lines->max - lines->min)((CtkGridLine*) __builtin_alloca (sizeof (CtkGridLine) * (gsize
) (lines->max - lines->min)))
;
1472 memset (lines->lines, 0, (lines->max - lines->min) * sizeof (CtkGridLine));
1473 lines = &request.lines[1];
1474 lines->lines = g_newa (CtkGridLine, lines->max - lines->min)((CtkGridLine*) __builtin_alloca (sizeof (CtkGridLine) * (gsize
) (lines->max - lines->min)))
;
1475 memset (lines->lines, 0, (lines->max - lines->min) * sizeof (CtkGridLine));
1476
1477 ctk_grid_request_run (&request, 1 - orientation, FALSE(0));
1478 ctk_grid_request_sum (&request, 1 - orientation, &min_size, &nat_size, NULL((void*)0), NULL((void*)0));
1479 ctk_grid_request_allocate (&request, 1 - orientation, MAX (size, min_size)(((size) > (min_size)) ? (size) : (min_size)));
1480
1481 ctk_grid_request_run (&request, orientation, TRUE(!(0)));
1482 ctk_grid_request_sum (&request, orientation, minimum, natural, minimum_baseline, natural_baseline);
1483}
1484
1485static void
1486ctk_grid_get_preferred_width (CtkWidget *widget,
1487 gint *minimum,
1488 gint *natural)
1489{
1490 ctk_css_gadget_get_preferred_size (CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
->priv->gadget,
1491 CTK_ORIENTATION_HORIZONTAL,
1492 -1,
1493 minimum, natural,
1494 NULL((void*)0), NULL((void*)0));
1495}
1496
1497static void
1498ctk_grid_get_preferred_height (CtkWidget *widget,
1499 gint *minimum,
1500 gint *natural)
1501{
1502 ctk_css_gadget_get_preferred_size (CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
->priv->gadget,
1503 CTK_ORIENTATION_VERTICAL,
1504 -1,
1505 minimum, natural,
1506 NULL((void*)0), NULL((void*)0));
1507}
1508
1509static void
1510ctk_grid_get_preferred_width_for_height (CtkWidget *widget,
1511 gint height,
1512 gint *minimum,
1513 gint *natural)
1514{
1515 ctk_css_gadget_get_preferred_size (CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
->priv->gadget,
1516 CTK_ORIENTATION_HORIZONTAL,
1517 height,
1518 minimum, natural,
1519 NULL((void*)0), NULL((void*)0));
1520}
1521
1522static void
1523ctk_grid_get_preferred_height_for_width (CtkWidget *widget,
1524 gint width,
1525 gint *minimum,
1526 gint *natural)
1527{
1528 ctk_css_gadget_get_preferred_size (CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
->priv->gadget,
1529 CTK_ORIENTATION_VERTICAL,
1530 width,
1531 minimum, natural,
1532 NULL((void*)0), NULL((void*)0));
1533}
1534
1535static void
1536ctk_grid_get_preferred_height_and_baseline_for_width (CtkWidget *widget,
1537 gint width,
1538 gint *minimum,
1539 gint *natural,
1540 gint *minimum_baseline,
1541 gint *natural_baseline)
1542{
1543 ctk_css_gadget_get_preferred_size (CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
->priv->gadget,
1544 CTK_ORIENTATION_VERTICAL,
1545 width,
1546 minimum, natural,
1547 minimum_baseline, natural_baseline);
1548}
1549
1550static void
1551ctk_grid_measure (CtkCssGadget *gadget,
1552 CtkOrientation orientation,
1553 int for_size,
1554 int *minimum,
1555 int *natural,
1556 int *minimum_baseline,
1557 int *natural_baseline,
1558 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1559{
1560 CtkWidget *widget = ctk_css_gadget_get_owner (gadget);
1561 CtkGrid *grid = CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
;
1562
1563 if ((orientation == CTK_ORIENTATION_HORIZONTAL &&
1
Assuming 'orientation' is not equal to CTK_ORIENTATION_HORIZONTAL
1564 ctk_widget_get_request_mode (widget) == CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT) ||
1565 (orientation == CTK_ORIENTATION_VERTICAL &&
2
Assuming 'orientation' is not equal to CTK_ORIENTATION_VERTICAL
1566 ctk_widget_get_request_mode (widget) == CTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH))
1567 ctk_grid_get_size_for_size (grid, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
1568 else
1569 ctk_grid_get_size (grid, orientation, minimum, natural, minimum_baseline, natural_baseline);
3
Calling 'ctk_grid_get_size'
1570}
1571
1572static void
1573allocate_child (CtkGridRequest *request,
1574 CtkOrientation orientation,
1575 CtkGridChild *child,
1576 gint *position,
1577 gint *size,
1578 gint *baseline)
1579{
1580 CtkGridPrivate *priv = request->grid->priv;
1581 CtkGridLineData *linedata;
1582 CtkGridLines *lines;
1583 CtkGridLine *line;
1584 CtkGridChildAttach *attach;
1585 gint i;
1586
1587 linedata = &priv->linedata[orientation];
1588 lines = &request->lines[orientation];
1589 attach = &child->attach[orientation];
1590
1591 *position = lines->lines[attach->pos - lines->min].position;
1592 if (attach->span == 1)
1593 *baseline = lines->lines[attach->pos - lines->min].allocated_baseline;
1594 else
1595 *baseline = -1;
1596
1597 *size = (attach->span - 1) * linedata->spacing;
1598 for (i = 0; i < attach->span; i++)
1599 {
1600 line = &lines->lines[attach->pos - lines->min + i];
1601 *size += line->allocation;
1602 }
1603}
1604
1605static void
1606ctk_grid_request_allocate_children (CtkGridRequest *request,
1607 const CtkAllocation *allocation)
1608{
1609 CtkGridPrivate *priv = request->grid->priv;
1610 GList *list;
1611 CtkGridChild *child;
1612 CtkAllocation child_allocation;
1613 gint x, y, width, height, baseline, ignore;
1614
1615 for (list = priv->children; list; list = list->next)
1616 {
1617 child = list->data;
1618
1619 if (!_ctk_widget_get_visible (child->widget))
1620 continue;
1621
1622 allocate_child (request, CTK_ORIENTATION_HORIZONTAL, child, &x, &width, &ignore);
1623 allocate_child (request, CTK_ORIENTATION_VERTICAL, child, &y, &height, &baseline);
1624
1625 child_allocation.x = allocation->x + x;
1626 child_allocation.y = allocation->y + y;
1627 child_allocation.width = MAX (1, width)(((1) > (width)) ? (1) : (width));
1628 child_allocation.height = MAX (1, height)(((1) > (height)) ? (1) : (height));
1629
1630 if (ctk_widget_get_direction (CTK_WIDGET (request->grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((request->grid)), ((ctk_widget_get_type ()))))))
) == CTK_TEXT_DIR_RTL)
1631 child_allocation.x = allocation->x + allocation->width
1632 - (child_allocation.x - allocation->x) - child_allocation.width;
1633
1634 ctk_widget_size_allocate_with_baseline (child->widget, &child_allocation, baseline);
1635 }
1636}
1637
1638#define GET_SIZE(allocation, orientation)(orientation == CTK_ORIENTATION_HORIZONTAL ? allocation->width
: allocation->height)
(orientation == CTK_ORIENTATION_HORIZONTAL ? allocation->width : allocation->height)
1639
1640static void
1641ctk_grid_size_allocate (CtkWidget *widget,
1642 CtkAllocation *allocation)
1643{
1644 CtkAllocation clip;
1645
1646 ctk_widget_set_allocation (widget, allocation);
1647
1648 ctk_css_gadget_allocate (CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
->priv->gadget,
1649 allocation,
1650 ctk_widget_get_allocated_baseline (widget),
1651 &clip);
1652
1653 ctk_widget_set_clip (widget, &clip);
1654}
1655
1656static void
1657ctk_grid_allocate (CtkCssGadget *gadget,
1658 const CtkAllocation *allocation,
1659 int baseline G_GNUC_UNUSED__attribute__ ((__unused__)),
1660 CtkAllocation *out_clip,
1661 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1662{
1663 CtkWidget *widget = ctk_css_gadget_get_owner (gadget);
1664 CtkGrid *grid = CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
;
1665 CtkGridPrivate *priv = grid->priv;
1666 CtkGridRequest request;
1667 CtkGridLines *lines;
1668 CtkOrientation orientation;
1669
1670 if (priv->children == NULL((void*)0))
1671 return;
1672
1673 request.grid = grid;
1674
1675 ctk_grid_request_count_lines (&request);
1676 lines = &request.lines[0];
1677 lines->lines = g_newa (CtkGridLine, lines->max - lines->min)((CtkGridLine*) __builtin_alloca (sizeof (CtkGridLine) * (gsize
) (lines->max - lines->min)))
;
1678 memset (lines->lines, 0, (lines->max - lines->min) * sizeof (CtkGridLine));
1679 lines = &request.lines[1];
1680 lines->lines = g_newa (CtkGridLine, lines->max - lines->min)((CtkGridLine*) __builtin_alloca (sizeof (CtkGridLine) * (gsize
) (lines->max - lines->min)))
;
1681 memset (lines->lines, 0, (lines->max - lines->min) * sizeof (CtkGridLine));
1682
1683 if (ctk_widget_get_request_mode (widget) == CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
1684 orientation = CTK_ORIENTATION_HORIZONTAL;
1685 else
1686 orientation = CTK_ORIENTATION_VERTICAL;
1687
1688 ctk_grid_request_run (&request, 1 - orientation, FALSE(0));
1689 ctk_grid_request_allocate (&request, 1 - orientation, GET_SIZE (allocation, 1 - orientation)(1 - orientation == CTK_ORIENTATION_HORIZONTAL ? allocation->
width : allocation->height)
);
1690 ctk_grid_request_run (&request, orientation, TRUE(!(0)));
1691
1692 ctk_grid_request_allocate (&request, orientation, GET_SIZE (allocation, orientation)(orientation == CTK_ORIENTATION_HORIZONTAL ? allocation->width
: allocation->height)
);
1693
1694 ctk_grid_request_position (&request, 0);
1695 ctk_grid_request_position (&request, 1);
1696
1697 ctk_grid_request_allocate_children (&request, allocation);
1698
1699 ctk_container_get_children_clip (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, out_clip);
1700}
1701
1702static gboolean
1703ctk_grid_render (CtkCssGadget *gadget,
1704 cairo_t *cr,
1705 int x G_GNUC_UNUSED__attribute__ ((__unused__)),
1706 int y G_GNUC_UNUSED__attribute__ ((__unused__)),
1707 int width G_GNUC_UNUSED__attribute__ ((__unused__)),
1708 int height G_GNUC_UNUSED__attribute__ ((__unused__)),
1709 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1710{
1711 CTK_WIDGET_CLASS (ctk_grid_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_grid_parent_class)), ((ctk_widget_get_type ()))))))
->draw (ctk_css_gadget_get_owner (gadget), cr);
1712
1713 return FALSE(0);
1714}
1715
1716static gboolean
1717ctk_grid_draw (CtkWidget *widget,
1718 cairo_t *cr)
1719{
1720 ctk_css_gadget_draw (CTK_GRID (widget)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_grid_get_type ()))))))
->priv->gadget, cr);
1721
1722 return FALSE(0);
1723}
1724
1725static void
1726ctk_grid_class_init (CtkGridClass *class)
1727{
1728 GObjectClass *object_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
1729 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_widget_get_type ()))))))
;
1730 CtkContainerClass *container_class = CTK_CONTAINER_CLASS (class)((((CtkContainerClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_container_get_type ()))))))
;
1731
1732 object_class->get_property = ctk_grid_get_property;
1733 object_class->set_property = ctk_grid_set_property;
1734 object_class->finalize = ctk_grid_finalize;
1735
1736 widget_class->size_allocate = ctk_grid_size_allocate;
1737 widget_class->get_preferred_width = ctk_grid_get_preferred_width;
1738 widget_class->get_preferred_height = ctk_grid_get_preferred_height;
1739 widget_class->get_preferred_width_for_height = ctk_grid_get_preferred_width_for_height;
1740 widget_class->get_preferred_height_for_width = ctk_grid_get_preferred_height_for_width;
1741 widget_class->get_preferred_height_and_baseline_for_width = ctk_grid_get_preferred_height_and_baseline_for_width;
1742 widget_class->draw = ctk_grid_draw;
1743
1744 container_class->add = ctk_grid_add;
1745 container_class->remove = ctk_grid_remove;
1746 container_class->forall = ctk_grid_forall;
1747 container_class->child_type = ctk_grid_child_type;
1748 container_class->set_child_property = ctk_grid_set_child_property;
1749 container_class->get_child_property = ctk_grid_get_child_property;
1750 ctk_container_class_handle_border_width (container_class);
1751
1752 g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
1753
1754 obj_properties[PROP_ROW_SPACING] =
1755 g_param_spec_int ("row-spacing",
1756 P_("Row spacing")g_dgettext("ctk30" "-properties","Row spacing"),
1757 P_("The amount of space between two consecutive rows")g_dgettext("ctk30" "-properties","The amount of space between two consecutive rows"
)
,
1758 0, G_MAXINT16((gint16) 0x7fff), 0,
1759 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1760
1761 obj_properties[PROP_COLUMN_SPACING] =
1762 g_param_spec_int ("column-spacing",
1763 P_("Column spacing")g_dgettext("ctk30" "-properties","Column spacing"),
1764 P_("The amount of space between two consecutive columns")g_dgettext("ctk30" "-properties","The amount of space between two consecutive columns"
)
,
1765 0, G_MAXINT16((gint16) 0x7fff), 0,
1766 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1767
1768 obj_properties[PROP_ROW_HOMOGENEOUS] =
1769 g_param_spec_boolean ("row-homogeneous",
1770 P_("Row Homogeneous")g_dgettext("ctk30" "-properties","Row Homogeneous"),
1771 P_("If TRUE, the rows are all the same height")g_dgettext("ctk30" "-properties","If TRUE, the rows are all the same height"
)
,
1772 FALSE(0),
1773 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1774
1775 obj_properties[PROP_COLUMN_HOMOGENEOUS] =
1776 g_param_spec_boolean ("column-homogeneous",
1777 P_("Column Homogeneous")g_dgettext("ctk30" "-properties","Column Homogeneous"),
1778 P_("If TRUE, the columns are all the same width")g_dgettext("ctk30" "-properties","If TRUE, the columns are all the same width"
)
,
1779 FALSE(0),
1780 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1781
1782 obj_properties[PROP_BASELINE_ROW] =
1783 g_param_spec_int ("baseline-row",
1784 P_("Baseline Row")g_dgettext("ctk30" "-properties","Baseline Row"),
1785 P_("The row to align the to the baseline when valign is CTK_ALIGN_BASELINE")g_dgettext("ctk30" "-properties","The row to align the to the baseline when valign is CTK_ALIGN_BASELINE"
)
,
1786 0, G_MAXINT2147483647, 0,
1787 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1788
1789 g_object_class_install_properties (object_class,
1790 N_PROPERTIES,
1791 obj_properties);
1792
1793 child_properties[CHILD_PROP_LEFT_ATTACH] =
1794 g_param_spec_int ("left-attach",
1795 P_("Left attachment")g_dgettext("ctk30" "-properties","Left attachment"),
1796 P_("The column number to attach the left side of the child to")g_dgettext("ctk30" "-properties","The column number to attach the left side of the child to"
)
,
1797 G_MININT(-2147483647 -1), G_MAXINT2147483647, 0,
1798 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1799
1800 child_properties[CHILD_PROP_TOP_ATTACH] =
1801 g_param_spec_int ("top-attach",
1802 P_("Top attachment")g_dgettext("ctk30" "-properties","Top attachment"),
1803 P_("The row number to attach the top side of a child widget to")g_dgettext("ctk30" "-properties","The row number to attach the top side of a child widget to"
)
,
1804 G_MININT(-2147483647 -1), G_MAXINT2147483647, 0,
1805 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1806
1807 child_properties[CHILD_PROP_WIDTH] =
1808 g_param_spec_int ("width",
1809 P_("Width")g_dgettext("ctk30" "-properties","Width"),
1810 P_("The number of columns that a child spans")g_dgettext("ctk30" "-properties","The number of columns that a child spans"
)
,
1811 1, G_MAXINT2147483647, 1,
1812 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1813
1814 child_properties[CHILD_PROP_HEIGHT] =
1815 g_param_spec_int ("height",
1816 P_("Height")g_dgettext("ctk30" "-properties","Height"),
1817 P_("The number of rows that a child spans")g_dgettext("ctk30" "-properties","The number of rows that a child spans"
)
,
1818 1, G_MAXINT2147483647, 1,
1819 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
1820
1821 ctk_container_class_install_child_properties (container_class, N_CHILD_PROPERTIES, child_properties);
1822 ctk_widget_class_set_css_name (widget_class, "grid");
1823}
1824
1825static void
1826ctk_grid_init (CtkGrid *grid)
1827{
1828 CtkGridPrivate *priv;
1829
1830 grid->priv = ctk_grid_get_instance_private (grid);
1831 priv = grid->priv;
1832
1833 ctk_widget_set_has_window (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
, FALSE(0));
1834
1835 priv->children = NULL((void*)0);
1836 priv->orientation = CTK_ORIENTATION_HORIZONTAL;
1837 priv->baseline_row = 0;
1838
1839 priv->linedata[0].spacing = 0;
1840 priv->linedata[1].spacing = 0;
1841
1842 priv->linedata[0].homogeneous = FALSE(0);
1843 priv->linedata[1].homogeneous = FALSE(0);
1844
1845 priv->gadget = ctk_css_custom_gadget_new_for_node (ctk_widget_get_css_node (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
),
1846 CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
,
1847 ctk_grid_measure,
1848 ctk_grid_allocate,
1849 ctk_grid_render,
1850 NULL((void*)0),
1851 NULL((void*)0));
1852
1853
1854 _ctk_orientable_set_style_classes (CTK_ORIENTABLE (grid)((((CtkOrientable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_orientable_get_type ()))))))
);
1855}
1856
1857/**
1858 * ctk_grid_new:
1859 *
1860 * Creates a new grid widget.
1861 *
1862 * Returns: the new #CtkGrid
1863 */
1864CtkWidget *
1865ctk_grid_new (void)
1866{
1867 return g_object_new (CTK_TYPE_GRID(ctk_grid_get_type ()), NULL((void*)0));
1868}
1869
1870/**
1871 * ctk_grid_attach:
1872 * @grid: a #CtkGrid
1873 * @child: the widget to add
1874 * @left: the column number to attach the left side of @child to
1875 * @top: the row number to attach the top side of @child to
1876 * @width: the number of columns that @child will span
1877 * @height: the number of rows that @child will span
1878 *
1879 * Adds a widget to the grid.
1880 *
1881 * The position of @child is determined by @left and @top. The
1882 * number of “cells” that @child will occupy is determined by
1883 * @width and @height.
1884 */
1885void
1886ctk_grid_attach (CtkGrid *grid,
1887 CtkWidget *child,
1888 gint left,
1889 gint top,
1890 gint width,
1891 gint height)
1892{
1893 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
1894 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (child)"); return; } } while (0)
;
1895 g_return_if_fail (_ctk_widget_get_parent (child) == NULL)do { if ((_ctk_widget_get_parent (child) == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "_ctk_widget_get_parent (child) == NULL"); return; } } while
(0)
;
1896 g_return_if_fail (width > 0)do { if ((width > 0)) { } else { g_return_if_fail_warning (
"Ctk", ((const char*) (__func__)), "width > 0"); return; }
} while (0)
;
1897 g_return_if_fail (height > 0)do { if ((height > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "height > 0"); return
; } } while (0)
;
1898
1899 grid_attach (grid, child, left, top, width, height);
1900}
1901
1902/**
1903 * ctk_grid_attach_next_to:
1904 * @grid: a #CtkGrid
1905 * @child: the widget to add
1906 * @sibling: (allow-none): the child of @grid that @child will be placed
1907 * next to, or %NULL to place @child at the beginning or end
1908 * @side: the side of @sibling that @child is positioned next to
1909 * @width: the number of columns that @child will span
1910 * @height: the number of rows that @child will span
1911 *
1912 * Adds a widget to the grid.
1913 *
1914 * The widget is placed next to @sibling, on the side determined by
1915 * @side. When @sibling is %NULL, the widget is placed in row (for
1916 * left or right placement) or column 0 (for top or bottom placement),
1917 * at the end indicated by @side.
1918 *
1919 * Attaching widgets labeled [1], [2], [3] with @sibling == %NULL and
1920 * @side == %CTK_POS_LEFT yields a layout of [3][2][1].
1921 */
1922void
1923ctk_grid_attach_next_to (CtkGrid *grid,
1924 CtkWidget *child,
1925 CtkWidget *sibling,
1926 CtkPositionType side,
1927 gint width,
1928 gint height)
1929{
1930 CtkGridChild *grid_sibling;
1931 gint left, top;
1932
1933 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
1934 g_return_if_fail (CTK_IS_WIDGET (child))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (child)"); return; } } while (0)
;
1935 g_return_if_fail (_ctk_widget_get_parent (child) == NULL)do { if ((_ctk_widget_get_parent (child) == ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "_ctk_widget_get_parent (child) == NULL"); return; } } while
(0)
;
1936 g_return_if_fail (sibling == NULL || _ctk_widget_get_parent (sibling) == (CtkWidget*)grid)do { if ((sibling == ((void*)0) || _ctk_widget_get_parent (sibling
) == (CtkWidget*)grid)) { } else { g_return_if_fail_warning (
"Ctk", ((const char*) (__func__)), "sibling == NULL || _ctk_widget_get_parent (sibling) == (CtkWidget*)grid"
); return; } } while (0)
;
1937 g_return_if_fail (width > 0)do { if ((width > 0)) { } else { g_return_if_fail_warning (
"Ctk", ((const char*) (__func__)), "width > 0"); return; }
} while (0)
;
1938 g_return_if_fail (height > 0)do { if ((height > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "height > 0"); return
; } } while (0)
;
1939
1940 if (sibling)
1941 {
1942 grid_sibling = find_grid_child (grid, sibling);
1943
1944 switch (side)
1945 {
1946 case CTK_POS_LEFT:
1947 left = CHILD_LEFT (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_HORIZONTAL].pos) - width;
1948 top = CHILD_TOP (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_VERTICAL].pos);
1949 break;
1950 case CTK_POS_RIGHT:
1951 left = CHILD_LEFT (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_HORIZONTAL].pos) + CHILD_WIDTH (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_HORIZONTAL].span);
1952 top = CHILD_TOP (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_VERTICAL].pos);
1953 break;
1954 case CTK_POS_TOP:
1955 left = CHILD_LEFT (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_HORIZONTAL].pos);
1956 top = CHILD_TOP (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_VERTICAL].pos) - height;
1957 break;
1958 case CTK_POS_BOTTOM:
1959 left = CHILD_LEFT (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_HORIZONTAL].pos);
1960 top = CHILD_TOP (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_VERTICAL].pos) + CHILD_HEIGHT (grid_sibling)((grid_sibling)->attach[CTK_ORIENTATION_VERTICAL].span);
1961 break;
1962 default:
1963 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkgrid.c", 1963, ((const
char*) (__func__)), ((void*)0)); } while (0)
;
1964 }
1965 }
1966 else
1967 {
1968 switch (side)
1969 {
1970 case CTK_POS_LEFT:
1971 left = find_attach_position (grid, CTK_ORIENTATION_HORIZONTAL, 0, height, FALSE(0));
1972 left -= width;
1973 top = 0;
1974 break;
1975 case CTK_POS_RIGHT:
1976 left = find_attach_position (grid, CTK_ORIENTATION_HORIZONTAL, 0, height, TRUE(!(0)));
1977 top = 0;
1978 break;
1979 case CTK_POS_TOP:
1980 left = 0;
1981 top = find_attach_position (grid, CTK_ORIENTATION_VERTICAL, 0, width, FALSE(0));
1982 top -= height;
1983 break;
1984 case CTK_POS_BOTTOM:
1985 left = 0;
1986 top = find_attach_position (grid, CTK_ORIENTATION_VERTICAL, 0, width, TRUE(!(0)));
1987 break;
1988 default:
1989 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkgrid.c", 1989, ((const
char*) (__func__)), ((void*)0)); } while (0)
;
1990 }
1991 }
1992
1993 grid_attach (grid, child, left, top, width, height);
1994}
1995
1996/**
1997 * ctk_grid_get_child_at:
1998 * @grid: a #CtkGrid
1999 * @left: the left edge of the cell
2000 * @top: the top edge of the cell
2001 *
2002 * Gets the child of @grid whose area covers the grid
2003 * cell whose upper left corner is at @left, @top.
2004 *
2005 * Returns: (transfer none) (nullable): the child at the given position, or %NULL
2006 *
2007 * Since: 3.2
2008 */
2009CtkWidget *
2010ctk_grid_get_child_at (CtkGrid *grid,
2011 gint left,
2012 gint top)
2013{
2014 CtkGridPrivate *priv;
2015 CtkGridChild *child;
2016 GList *list;
2017
2018 g_return_val_if_fail (CTK_IS_GRID (grid), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return (((void*)0)); } } while (0)
;
2019
2020 priv = grid->priv;
2021
2022 for (list = priv->children; list; list = list->next)
2023 {
2024 child = list->data;
2025
2026 if (CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos) <= left &&
2027 CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos) + CHILD_WIDTH (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].span) > left &&
2028 CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos) <= top &&
2029 CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos) + CHILD_HEIGHT (child)((child)->attach[CTK_ORIENTATION_VERTICAL].span) > top)
2030 return child->widget;
2031 }
2032
2033 return NULL((void*)0);
2034}
2035
2036/**
2037 * ctk_grid_insert_row:
2038 * @grid: a #CtkGrid
2039 * @position: the position to insert the row at
2040 *
2041 * Inserts a row at the specified position.
2042 *
2043 * Children which are attached at or below this position
2044 * are moved one row down. Children which span across this
2045 * position are grown to span the new row.
2046 *
2047 * Since: 3.2
2048 */
2049void
2050ctk_grid_insert_row (CtkGrid *grid,
2051 gint position)
2052{
2053 CtkGridPrivate *priv;
2054 CtkGridChild *child;
2055 GList *list;
2056 gint top, height;
2057
2058 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2059
2060 priv = grid->priv;
2061
2062 for (list = priv->children; list; list = list->next)
2063 {
2064 child = list->data;
2065
2066 top = CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos);
2067 height = CHILD_HEIGHT (child)((child)->attach[CTK_ORIENTATION_VERTICAL].span);
2068
2069 if (top >= position)
2070 {
2071 CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos) = top + 1;
2072 ctk_container_child_notify_by_pspec (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
,
2073 child->widget,
2074 child_properties[CHILD_PROP_TOP_ATTACH]);
2075 }
2076 else if (top + height > position)
2077 {
2078 CHILD_HEIGHT (child)((child)->attach[CTK_ORIENTATION_VERTICAL].span) = height + 1;
2079 ctk_container_child_notify_by_pspec (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
,
2080 child->widget,
2081 child_properties[CHILD_PROP_HEIGHT]);
2082 }
2083 }
2084
2085 for (list = priv->row_properties; list != NULL((void*)0); list = list->next)
2086 {
2087 CtkGridRowProperties *prop = list->data;
2088
2089 if (prop->row >= position)
2090 prop->row += 1;
2091 }
2092}
2093
2094/**
2095 * ctk_grid_remove_row:
2096 * @grid: a #CtkGrid
2097 * @position: the position of the row to remove
2098 *
2099 * Removes a row from the grid.
2100 *
2101 * Children that are placed in this row are removed,
2102 * spanning children that overlap this row have their
2103 * height reduced by one, and children below the row
2104 * are moved up.
2105 *
2106 * Since: 3.10
2107 */
2108void
2109ctk_grid_remove_row (CtkGrid *grid,
2110 gint position)
2111{
2112 CtkGridPrivate *priv;
2113 CtkGridChild *child;
2114 GList *list;
2115 gint top, height;
2116
2117 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2118
2119 priv = grid->priv;
2120
2121 list = priv->children;
2122 while (list)
2123 {
2124 child = list->data;
2125 list = list->next;
2126
2127 top = CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos);
2128 height = CHILD_HEIGHT (child)((child)->attach[CTK_ORIENTATION_VERTICAL].span);
2129
2130 if (top <= position && top + height > position)
2131 height--;
2132 if (top > position)
2133 top--;
2134
2135 if (height <= 0)
2136 ctk_container_remove (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, child->widget);
2137 else
2138 ctk_container_child_set (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, child->widget,
2139 "height", height,
2140 "top-attach", top,
2141 NULL((void*)0));
2142 }
2143}
2144
2145/**
2146 * ctk_grid_insert_column:
2147 * @grid: a #CtkGrid
2148 * @position: the position to insert the column at
2149 *
2150 * Inserts a column at the specified position.
2151 *
2152 * Children which are attached at or to the right of this position
2153 * are moved one column to the right. Children which span across this
2154 * position are grown to span the new column.
2155 *
2156 * Since: 3.2
2157 */
2158void
2159ctk_grid_insert_column (CtkGrid *grid,
2160 gint position)
2161{
2162 CtkGridPrivate *priv;
2163 CtkGridChild *child;
2164 GList *list;
2165 gint left, width;
2166
2167 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2168
2169 priv = grid->priv;
2170
2171 for (list = priv->children; list; list = list->next)
2172 {
2173 child = list->data;
2174
2175 left = CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos);
2176 width = CHILD_WIDTH (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].span);
2177
2178 if (left >= position)
2179 {
2180 CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos) = left + 1;
2181 ctk_container_child_notify_by_pspec (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
,
2182 child->widget,
2183 child_properties[CHILD_PROP_LEFT_ATTACH]);
2184 }
2185 else if (left + width > position)
2186 {
2187 CHILD_WIDTH (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].span) = width + 1;
2188 ctk_container_child_notify_by_pspec (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
,
2189 child->widget,
2190 child_properties[CHILD_PROP_WIDTH]);
2191 }
2192 }
2193}
2194
2195/**
2196 * ctk_grid_remove_column:
2197 * @grid: a #CtkGrid
2198 * @position: the position of the column to remove
2199 *
2200 * Removes a column from the grid.
2201 *
2202 * Children that are placed in this column are removed,
2203 * spanning children that overlap this column have their
2204 * width reduced by one, and children after the column
2205 * are moved to the left.
2206 *
2207 * Since: 3.10
2208 */
2209void
2210ctk_grid_remove_column (CtkGrid *grid,
2211 gint position)
2212{
2213 CtkGridPrivate *priv;
2214 CtkGridChild *child;
2215 GList *list;
2216 gint left, width;
2217
2218 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2219
2220 priv = grid->priv;
2221
2222 list = priv->children;
2223 while (list)
2224 {
2225 child = list->data;
2226 list = list->next;
2227
2228 left = CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos);
2229 width = CHILD_WIDTH (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].span);
2230
2231 if (left <= position && left + width > position)
2232 width--;
2233 if (left > position)
2234 left--;
2235
2236 if (width <= 0)
2237 ctk_container_remove (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, child->widget);
2238 else
2239 ctk_container_child_set (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, child->widget,
2240 "width", width,
2241 "left-attach", left,
2242 NULL((void*)0));
2243 }
2244}
2245
2246/**
2247 * ctk_grid_insert_next_to:
2248 * @grid: a #CtkGrid
2249 * @sibling: the child of @grid that the new row or column will be
2250 * placed next to
2251 * @side: the side of @sibling that @child is positioned next to
2252 *
2253 * Inserts a row or column at the specified position.
2254 *
2255 * The new row or column is placed next to @sibling, on the side
2256 * determined by @side. If @side is %CTK_POS_TOP or %CTK_POS_BOTTOM,
2257 * a row is inserted. If @side is %CTK_POS_LEFT of %CTK_POS_RIGHT,
2258 * a column is inserted.
2259 *
2260 * Since: 3.2
2261 */
2262void
2263ctk_grid_insert_next_to (CtkGrid *grid,
2264 CtkWidget *sibling,
2265 CtkPositionType side)
2266{
2267 CtkGridChild *child;
2268
2269 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2270 g_return_if_fail (CTK_IS_WIDGET (sibling))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((sibling)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (sibling)"); return; } } while (0)
;
2271 g_return_if_fail (_ctk_widget_get_parent (sibling) == (CtkWidget*)grid)do { if ((_ctk_widget_get_parent (sibling) == (CtkWidget*)grid
)) { } else { g_return_if_fail_warning ("Ctk", ((const char*)
(__func__)), "_ctk_widget_get_parent (sibling) == (CtkWidget*)grid"
); return; } } while (0)
;
2272
2273 child = find_grid_child (grid, sibling);
2274
2275 switch (side)
2276 {
2277 case CTK_POS_LEFT:
2278 ctk_grid_insert_column (grid, CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos));
2279 break;
2280 case CTK_POS_RIGHT:
2281 ctk_grid_insert_column (grid, CHILD_LEFT (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].pos) + CHILD_WIDTH (child)((child)->attach[CTK_ORIENTATION_HORIZONTAL].span));
2282 break;
2283 case CTK_POS_TOP:
2284 ctk_grid_insert_row (grid, CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos));
2285 break;
2286 case CTK_POS_BOTTOM:
2287 ctk_grid_insert_row (grid, CHILD_TOP (child)((child)->attach[CTK_ORIENTATION_VERTICAL].pos) + CHILD_HEIGHT (child)((child)->attach[CTK_ORIENTATION_VERTICAL].span));
2288 break;
2289 default:
2290 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkgrid.c", 2290, ((const
char*) (__func__)), ((void*)0)); } while (0)
;
2291 }
2292}
2293
2294/**
2295 * ctk_grid_set_row_homogeneous:
2296 * @grid: a #CtkGrid
2297 * @homogeneous: %TRUE to make rows homogeneous
2298 *
2299 * Sets whether all rows of @grid will have the same height.
2300 */
2301void
2302ctk_grid_set_row_homogeneous (CtkGrid *grid,
2303 gboolean homogeneous)
2304{
2305 CtkGridPrivate *priv;
2306 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2307
2308 priv = grid->priv;
2309
2310 /* Yes, homogeneous rows means all the columns have the same size */
2311 if (COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->homogeneous != homogeneous)
2312 {
2313 COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->homogeneous = homogeneous;
2314
2315 if (_ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
2316 ctk_widget_queue_resize (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
2317
2318 g_object_notify_by_pspec (G_OBJECT (grid)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), (((GType) ((20) << (2))))))))
, obj_properties [PROP_ROW_HOMOGENEOUS]);
2319 }
2320}
2321
2322/**
2323 * ctk_grid_get_row_homogeneous:
2324 * @grid: a #CtkGrid
2325 *
2326 * Returns whether all rows of @grid have the same height.
2327 *
2328 * Returns: whether all rows of @grid have the same height.
2329 */
2330gboolean
2331ctk_grid_get_row_homogeneous (CtkGrid *grid)
2332{
2333 CtkGridPrivate *priv;
2334 g_return_val_if_fail (CTK_IS_GRID (grid), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return ((0)); } } while (0)
;
2335
2336 priv = grid->priv;
2337
2338 return COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->homogeneous;
2339}
2340
2341/**
2342 * ctk_grid_set_column_homogeneous:
2343 * @grid: a #CtkGrid
2344 * @homogeneous: %TRUE to make columns homogeneous
2345 *
2346 * Sets whether all columns of @grid will have the same width.
2347 */
2348void
2349ctk_grid_set_column_homogeneous (CtkGrid *grid,
2350 gboolean homogeneous)
2351{
2352 CtkGridPrivate *priv;
2353 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2354
2355 priv = grid->priv;
2356
2357 /* Yes, homogeneous columns means all the rows have the same size */
2358 if (ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->homogeneous != homogeneous)
2359 {
2360 ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->homogeneous = homogeneous;
2361
2362 if (_ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
2363 ctk_widget_queue_resize (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
2364
2365 g_object_notify_by_pspec (G_OBJECT (grid)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), (((GType) ((20) << (2))))))))
, obj_properties [PROP_COLUMN_HOMOGENEOUS]);
2366 }
2367}
2368
2369/**
2370 * ctk_grid_get_column_homogeneous:
2371 * @grid: a #CtkGrid
2372 *
2373 * Returns whether all columns of @grid have the same width.
2374 *
2375 * Returns: whether all columns of @grid have the same width.
2376 */
2377gboolean
2378ctk_grid_get_column_homogeneous (CtkGrid *grid)
2379{
2380 CtkGridPrivate *priv;
2381 g_return_val_if_fail (CTK_IS_GRID (grid), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return ((0)); } } while (0)
;
2382
2383 priv = grid->priv;
2384
2385 return ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->homogeneous;
2386}
2387
2388/**
2389 * ctk_grid_set_row_spacing:
2390 * @grid: a #CtkGrid
2391 * @spacing: the amount of space to insert between rows
2392 *
2393 * Sets the amount of space between rows of @grid.
2394 */
2395void
2396ctk_grid_set_row_spacing (CtkGrid *grid,
2397 guint spacing)
2398{
2399 CtkGridPrivate *priv;
2400 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2401 g_return_if_fail (spacing <= G_MAXINT16)do { if ((spacing <= ((gint16) 0x7fff))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "spacing <= G_MAXINT16"
); return; } } while (0)
;
2402
2403 priv = grid->priv;
2404
2405 if (COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->spacing != spacing)
2406 {
2407 COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->spacing = spacing;
2408
2409 if (_ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
2410 ctk_widget_queue_resize (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
2411
2412 g_object_notify_by_pspec (G_OBJECT (grid)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), (((GType) ((20) << (2))))))))
, obj_properties [PROP_ROW_SPACING]);
2413 }
2414}
2415
2416/**
2417 * ctk_grid_get_row_spacing:
2418 * @grid: a #CtkGrid
2419 *
2420 * Returns the amount of space between the rows of @grid.
2421 *
2422 * Returns: the row spacing of @grid
2423 */
2424guint
2425ctk_grid_get_row_spacing (CtkGrid *grid)
2426{
2427 CtkGridPrivate *priv;
2428 g_return_val_if_fail (CTK_IS_GRID (grid), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return (0); } } while (0)
;
2429
2430 priv = grid->priv;
2431
2432 return COLUMNS (priv)(&(priv)->linedata[CTK_ORIENTATION_VERTICAL])->spacing;
2433}
2434
2435/**
2436 * ctk_grid_set_column_spacing:
2437 * @grid: a #CtkGrid
2438 * @spacing: the amount of space to insert between columns
2439 *
2440 * Sets the amount of space between columns of @grid.
2441 */
2442void
2443ctk_grid_set_column_spacing (CtkGrid *grid,
2444 guint spacing)
2445{
2446 CtkGridPrivate *priv;
2447 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2448 g_return_if_fail (spacing <= G_MAXINT16)do { if ((spacing <= ((gint16) 0x7fff))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "spacing <= G_MAXINT16"
); return; } } while (0)
;
2449
2450 priv = grid->priv;
2451
2452 if (ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->spacing != spacing)
2453 {
2454 ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->spacing = spacing;
2455
2456 if (_ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
2457 ctk_widget_queue_resize (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
2458
2459 g_object_notify_by_pspec (G_OBJECT (grid)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), (((GType) ((20) << (2))))))))
, obj_properties [PROP_COLUMN_SPACING]);
2460 }
2461}
2462
2463/**
2464 * ctk_grid_get_column_spacing:
2465 * @grid: a #CtkGrid
2466 *
2467 * Returns the amount of space between the columns of @grid.
2468 *
2469 * Returns: the column spacing of @grid
2470 */
2471guint
2472ctk_grid_get_column_spacing (CtkGrid *grid)
2473{
2474 CtkGridPrivate *priv;
2475
2476 g_return_val_if_fail (CTK_IS_GRID (grid), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return (0); } } while (0)
;
2477
2478 priv = grid->priv;
2479
2480 return ROWS (priv)(&(priv)->linedata[CTK_ORIENTATION_HORIZONTAL])->spacing;
2481}
2482
2483static CtkGridRowProperties *
2484find_row_properties (CtkGrid *grid,
2485 gint row)
2486{
2487 GList *l;
2488
2489 for (l = grid->priv->row_properties; l != NULL((void*)0); l = l->next)
2490 {
2491 CtkGridRowProperties *prop = l->data;
2492 if (prop->row == row)
2493 return prop;
2494 }
2495
2496 return NULL((void*)0);
2497}
2498
2499static void
2500ctk_grid_row_properties_free (CtkGridRowProperties *props)
2501{
2502 g_slice_free (CtkGridRowProperties, props)do { if (1) g_slice_free1 (sizeof (CtkGridRowProperties), (props
)); else (void) ((CtkGridRowProperties*) 0 == (props)); } while
(0)
;
2503}
2504
2505static CtkGridRowProperties *
2506get_row_properties_or_create (CtkGrid *grid,
2507 gint row)
2508{
2509 CtkGridRowProperties *props;
2510 CtkGridPrivate *priv = grid->priv;
2511
2512 props = find_row_properties (grid, row);
2513 if (props)
2514 return props;
2515
2516 props = g_slice_new (CtkGridRowProperties)((CtkGridRowProperties*) g_slice_alloc (sizeof (CtkGridRowProperties
)))
;
2517 *props = ctk_grid_row_properties_default;
2518 props->row = row;
2519
2520 priv->row_properties =
2521 g_list_prepend (priv->row_properties, props);
2522
2523 return props;
2524}
2525
2526static const CtkGridRowProperties *
2527get_row_properties_or_default (CtkGrid *grid,
2528 gint row)
2529{
2530 CtkGridRowProperties *props;
2531
2532 props = find_row_properties (grid, row);
2533 if (props)
2534 return props;
2535 return &ctk_grid_row_properties_default;
2536}
2537
2538/**
2539 * ctk_grid_set_row_baseline_position:
2540 * @grid: a #CtkGrid
2541 * @row: a row index
2542 * @pos: a #CtkBaselinePosition
2543 *
2544 * Sets how the baseline should be positioned on @row of the
2545 * grid, in case that row is assigned more space than is requested.
2546 *
2547 * Since: 3.10
2548 */
2549void
2550ctk_grid_set_row_baseline_position (CtkGrid *grid,
2551 gint row,
2552 CtkBaselinePosition pos)
2553{
2554 CtkGridRowProperties *props;
2555
2556 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2557
2558 props = get_row_properties_or_create (grid, row);
2559
2560 if (props->baseline_position != pos)
2561 {
2562 props->baseline_position = pos;
2563
2564 if (_ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
2565 ctk_widget_queue_resize (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
2566 }
2567}
2568
2569/**
2570 * ctk_grid_get_row_baseline_position:
2571 * @grid: a #CtkGrid
2572 * @row: a row index
2573 *
2574 * Returns the baseline position of @row as set
2575 * by ctk_grid_set_row_baseline_position() or the default value
2576 * %CTK_BASELINE_POSITION_CENTER.
2577 *
2578 * Returns: the baseline position of @row
2579 *
2580 * Since: 3.10
2581 */
2582CtkBaselinePosition
2583ctk_grid_get_row_baseline_position (CtkGrid *grid,
2584 gint row)
2585{
2586 const CtkGridRowProperties *props;
2587
2588 g_return_val_if_fail (CTK_IS_GRID (grid), CTK_BASELINE_POSITION_CENTER)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return (CTK_BASELINE_POSITION_CENTER
); } } while (0)
;
2589
2590 props = get_row_properties_or_default (grid, row);
2591
2592 return props->baseline_position;
2593}
2594
2595/**
2596 * ctk_grid_set_baseline_row:
2597 * @grid: a #CtkGrid
2598 * @row: the row index
2599 *
2600 * Sets which row defines the global baseline for the entire grid.
2601 * Each row in the grid can have its own local baseline, but only
2602 * one of those is global, meaning it will be the baseline in the
2603 * parent of the @grid.
2604 *
2605 * Since: 3.10
2606 */
2607void
2608ctk_grid_set_baseline_row (CtkGrid *grid,
2609 gint row)
2610{
2611 CtkGridPrivate *priv;
2612
2613 g_return_if_fail (CTK_IS_GRID (grid))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return; } } while (0)
;
2614
2615 priv = grid->priv;
2616
2617 if (priv->baseline_row != row)
2618 {
2619 priv->baseline_row = row;
2620
2621 if (_ctk_widget_get_visible (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
))
2622 ctk_widget_queue_resize (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
2623 g_object_notify (G_OBJECT (grid)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), (((GType) ((20) << (2))))))))
, "baseline-row");
2624 }
2625}
2626
2627/**
2628 * ctk_grid_get_baseline_row:
2629 * @grid: a #CtkGrid
2630 *
2631 * Returns which row defines the global baseline of @grid.
2632 *
2633 * Returns: the row index defining the global baseline
2634 *
2635 * Since: 3.10
2636 */
2637gint
2638ctk_grid_get_baseline_row (CtkGrid *grid)
2639{
2640 CtkGridPrivate *priv;
2641
2642 g_return_val_if_fail (CTK_IS_GRID (grid), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((grid)); GType __t = ((ctk_grid_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_GRID (grid)"); return (0); } } while (0)
;
2643
2644 priv = grid->priv;
2645
2646 return priv->baseline_row;
2647}