Bug Summary

File:ctk/ctkcellareabox.c
Warning:line 1603, column 21
Use of memory allocated with size zero

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 ctkcellareabox.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-171502-43637-1 -x c ctkcellareabox.c
1/* ctkcellareabox.c
2 *
3 * Copyright (C) 2010 Openismus GmbH
4 *
5 * Authors:
6 * Tristan Van Berkom <tristanvb@openismus.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22
23/**
24 * SECTION:ctkcellareabox
25 * @Short_Description: A cell area that renders CtkCellRenderers
26 * into a row or a column
27 * @Title: CtkCellAreaBox
28 *
29 * The #CtkCellAreaBox renders cell renderers into a row or a column
30 * depending on its #CtkOrientation.
31 *
32 * CtkCellAreaBox uses a notion of packing. Packing
33 * refers to adding cell renderers with reference to a particular position
34 * in a #CtkCellAreaBox. There are two reference positions: the
35 * start and the end of the box.
36 * When the #CtkCellAreaBox is oriented in the %CTK_ORIENTATION_VERTICAL
37 * orientation, the start is defined as the top of the box and the end is
38 * defined as the bottom. In the %CTK_ORIENTATION_HORIZONTAL orientation
39 * start is defined as the left side and the end is defined as the right
40 * side.
41 *
42 * Alignments of #CtkCellRenderers rendered in adjacent rows can be
43 * configured by configuring the #CtkCellAreaBox align child cell property
44 * with ctk_cell_area_cell_set_property() or by specifying the "align"
45 * argument to ctk_cell_area_box_pack_start() and ctk_cell_area_box_pack_end().
46 */
47
48#include "config.h"
49#include "ctkintl.h"
50#include "ctkorientable.h"
51#include "ctkcelllayout.h"
52#include "ctkcellareabox.h"
53#include "ctkcellareaboxcontextprivate.h"
54#include "ctktypebuiltins.h"
55#include "ctkprivate.h"
56
57
58/* GObjectClass */
59static void ctk_cell_area_box_finalize (GObject *object);
60static void ctk_cell_area_box_dispose (GObject *object);
61static void ctk_cell_area_box_set_property (GObject *object,
62 guint prop_id,
63 const GValue *value,
64 GParamSpec *pspec);
65static void ctk_cell_area_box_get_property (GObject *object,
66 guint prop_id,
67 GValue *value,
68 GParamSpec *pspec);
69
70/* CtkCellAreaClass */
71static void ctk_cell_area_box_add (CtkCellArea *area,
72 CtkCellRenderer *renderer);
73static void ctk_cell_area_box_remove (CtkCellArea *area,
74 CtkCellRenderer *renderer);
75static void ctk_cell_area_box_foreach (CtkCellArea *area,
76 CtkCellCallback callback,
77 gpointer callback_data);
78static void ctk_cell_area_box_foreach_alloc (CtkCellArea *area,
79 CtkCellAreaContext *context,
80 CtkWidget *widget,
81 const CdkRectangle *cell_area,
82 const CdkRectangle *background_area,
83 CtkCellAllocCallback callback,
84 gpointer callback_data);
85static void ctk_cell_area_box_apply_attributes (CtkCellArea *area,
86 CtkTreeModel *tree_model,
87 CtkTreeIter *iter,
88 gboolean is_expander,
89 gboolean is_expanded);
90static void ctk_cell_area_box_set_cell_property (CtkCellArea *area,
91 CtkCellRenderer *renderer,
92 guint prop_id,
93 const GValue *value,
94 GParamSpec *pspec);
95static void ctk_cell_area_box_get_cell_property (CtkCellArea *area,
96 CtkCellRenderer *renderer,
97 guint prop_id,
98 GValue *value,
99 GParamSpec *pspec);
100static CtkCellAreaContext *ctk_cell_area_box_create_context (CtkCellArea *area);
101static CtkCellAreaContext *ctk_cell_area_box_copy_context (CtkCellArea *area,
102 CtkCellAreaContext *context);
103static CtkSizeRequestMode ctk_cell_area_box_get_request_mode (CtkCellArea *area);
104static void ctk_cell_area_box_get_preferred_width (CtkCellArea *area,
105 CtkCellAreaContext *context,
106 CtkWidget *widget,
107 gint *minimum_width,
108 gint *natural_width);
109static void ctk_cell_area_box_get_preferred_height (CtkCellArea *area,
110 CtkCellAreaContext *context,
111 CtkWidget *widget,
112 gint *minimum_height,
113 gint *natural_height);
114static void ctk_cell_area_box_get_preferred_height_for_width (CtkCellArea *area,
115 CtkCellAreaContext *context,
116 CtkWidget *widget,
117 gint width,
118 gint *minimum_height,
119 gint *natural_height);
120static void ctk_cell_area_box_get_preferred_width_for_height (CtkCellArea *area,
121 CtkCellAreaContext *context,
122 CtkWidget *widget,
123 gint height,
124 gint *minimum_width,
125 gint *natural_width);
126static gboolean ctk_cell_area_box_focus (CtkCellArea *area,
127 CtkDirectionType direction);
128
129/* CtkCellLayoutIface */
130static void ctk_cell_area_box_cell_layout_init (CtkCellLayoutIface *iface);
131static void ctk_cell_area_box_layout_pack_start (CtkCellLayout *cell_layout,
132 CtkCellRenderer *renderer,
133 gboolean expand);
134static void ctk_cell_area_box_layout_pack_end (CtkCellLayout *cell_layout,
135 CtkCellRenderer *renderer,
136 gboolean expand);
137static void ctk_cell_area_box_layout_reorder (CtkCellLayout *cell_layout,
138 CtkCellRenderer *renderer,
139 gint position);
140static void ctk_cell_area_box_focus_changed (CtkCellArea *area,
141 GParamSpec *pspec,
142 CtkCellAreaBox *box);
143
144
145/* CellInfo/CellGroup metadata handling and convenience functions */
146typedef struct {
147 CtkCellRenderer *renderer;
148
149 guint expand : 1; /* Whether the cell expands */
150 guint pack : 1; /* Whether it is packed from the start or end */
151 guint align : 1; /* Whether to align its position with adjacent rows */
152 guint fixed : 1; /* Whether to require the same size for all rows */
153} CellInfo;
154
155typedef struct {
156 GList *cells;
157
158 guint id : 8;
159 guint n_cells : 8;
160 guint expand_cells : 8;
161 guint align : 1;
162 guint visible : 1;
163} CellGroup;
164
165typedef struct {
166 CtkCellRenderer *renderer;
167
168 gint position;
169 gint size;
170} AllocatedCell;
171
172static CellInfo *cell_info_new (CtkCellRenderer *renderer,
173 CtkPackType pack,
174 gboolean expand,
175 gboolean align,
176 gboolean fixed);
177static void cell_info_free (CellInfo *info);
178static gint cell_info_find (CellInfo *info,
179 CtkCellRenderer *renderer);
180
181static AllocatedCell *allocated_cell_new (CtkCellRenderer *renderer,
182 gint position,
183 gint size);
184static void allocated_cell_free (AllocatedCell *cell);
185static GList *list_consecutive_cells (CtkCellAreaBox *box);
186static gint count_expand_groups (CtkCellAreaBox *box);
187static void context_weak_notify (CtkCellAreaBox *box,
188 CtkCellAreaBoxContext *dead_context);
189static void reset_contexts (CtkCellAreaBox *box);
190static void init_context_groups (CtkCellAreaBox *box);
191static void init_context_group (CtkCellAreaBox *box,
192 CtkCellAreaBoxContext *context);
193static GSList *get_allocated_cells (CtkCellAreaBox *box,
194 CtkCellAreaBoxContext *context,
195 CtkWidget *widget,
196 gint width,
197 gint height);
198
199
200struct _CtkCellAreaBoxPrivate
201{
202 /* We hold on to the previously focused cell when navigating
203 * up and down in a horizontal box (or left and right on a vertical one)
204 * this way we always re-enter the last focused cell.
205 */
206 CtkCellRenderer *last_focus_cell;
207 gulong focus_cell_id;
208
209 GList *cells;
210 GArray *groups;
211
212 GSList *contexts;
213
214 CtkOrientation orientation;
215 gint spacing;
216
217 /* We hold on to the rtl state from a widget we are requested for
218 * so that we can navigate focus correctly
219 */
220 gboolean rtl;
221};
222
223enum {
224 PROP_0,
225 PROP_ORIENTATION,
226 PROP_SPACING
227};
228
229enum {
230 CELL_PROP_0,
231 CELL_PROP_EXPAND,
232 CELL_PROP_ALIGN,
233 CELL_PROP_FIXED_SIZE,
234 CELL_PROP_PACK_TYPE
235};
236
237G_DEFINE_TYPE_WITH_CODE (CtkCellAreaBox, ctk_cell_area_box, CTK_TYPE_CELL_AREA,static void ctk_cell_area_box_init (CtkCellAreaBox *self); static
void ctk_cell_area_box_class_init (CtkCellAreaBoxClass *klass
); static GType ctk_cell_area_box_get_type_once (void); static
gpointer ctk_cell_area_box_parent_class = ((void*)0); static
gint CtkCellAreaBox_private_offset; static void ctk_cell_area_box_class_intern_init
(gpointer klass) { ctk_cell_area_box_parent_class = g_type_class_peek_parent
(klass); if (CtkCellAreaBox_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCellAreaBox_private_offset); ctk_cell_area_box_class_init
((CtkCellAreaBoxClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_cell_area_box_get_instance_private
(CtkCellAreaBox *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCellAreaBox_private_offset)))); } GType ctk_cell_area_box_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_cell_area_box_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_cell_area_box_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((ctk_cell_area_get_type ()), g_intern_static_string ("CtkCellAreaBox"
), sizeof (CtkCellAreaBoxClass), (GClassInitFunc)(void (*)(void
)) ctk_cell_area_box_class_intern_init, sizeof (CtkCellAreaBox
), (GInstanceInitFunc)(void (*)(void)) ctk_cell_area_box_init
, (GTypeFlags) 0); { {{ CtkCellAreaBox_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCellAreaBoxPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_cell_area_box_cell_layout_init, ((void*
)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_cell_layout_get_type ()), &g_implement_interface_info
); } { 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; }
238 G_ADD_PRIVATE (CtkCellAreaBox)static void ctk_cell_area_box_init (CtkCellAreaBox *self); static
void ctk_cell_area_box_class_init (CtkCellAreaBoxClass *klass
); static GType ctk_cell_area_box_get_type_once (void); static
gpointer ctk_cell_area_box_parent_class = ((void*)0); static
gint CtkCellAreaBox_private_offset; static void ctk_cell_area_box_class_intern_init
(gpointer klass) { ctk_cell_area_box_parent_class = g_type_class_peek_parent
(klass); if (CtkCellAreaBox_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCellAreaBox_private_offset); ctk_cell_area_box_class_init
((CtkCellAreaBoxClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_cell_area_box_get_instance_private
(CtkCellAreaBox *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCellAreaBox_private_offset)))); } GType ctk_cell_area_box_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_cell_area_box_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_cell_area_box_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((ctk_cell_area_get_type ()), g_intern_static_string ("CtkCellAreaBox"
), sizeof (CtkCellAreaBoxClass), (GClassInitFunc)(void (*)(void
)) ctk_cell_area_box_class_intern_init, sizeof (CtkCellAreaBox
), (GInstanceInitFunc)(void (*)(void)) ctk_cell_area_box_init
, (GTypeFlags) 0); { {{ CtkCellAreaBox_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCellAreaBoxPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_cell_area_box_cell_layout_init, ((void*
)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_cell_layout_get_type ()), &g_implement_interface_info
); } { 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; }
239 G_IMPLEMENT_INTERFACE (CTK_TYPE_CELL_LAYOUT,static void ctk_cell_area_box_init (CtkCellAreaBox *self); static
void ctk_cell_area_box_class_init (CtkCellAreaBoxClass *klass
); static GType ctk_cell_area_box_get_type_once (void); static
gpointer ctk_cell_area_box_parent_class = ((void*)0); static
gint CtkCellAreaBox_private_offset; static void ctk_cell_area_box_class_intern_init
(gpointer klass) { ctk_cell_area_box_parent_class = g_type_class_peek_parent
(klass); if (CtkCellAreaBox_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCellAreaBox_private_offset); ctk_cell_area_box_class_init
((CtkCellAreaBoxClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_cell_area_box_get_instance_private
(CtkCellAreaBox *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCellAreaBox_private_offset)))); } GType ctk_cell_area_box_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_cell_area_box_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_cell_area_box_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((ctk_cell_area_get_type ()), g_intern_static_string ("CtkCellAreaBox"
), sizeof (CtkCellAreaBoxClass), (GClassInitFunc)(void (*)(void
)) ctk_cell_area_box_class_intern_init, sizeof (CtkCellAreaBox
), (GInstanceInitFunc)(void (*)(void)) ctk_cell_area_box_init
, (GTypeFlags) 0); { {{ CtkCellAreaBox_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCellAreaBoxPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_cell_area_box_cell_layout_init, ((void*
)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_cell_layout_get_type ()), &g_implement_interface_info
); } { 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; }
240 ctk_cell_area_box_cell_layout_init)static void ctk_cell_area_box_init (CtkCellAreaBox *self); static
void ctk_cell_area_box_class_init (CtkCellAreaBoxClass *klass
); static GType ctk_cell_area_box_get_type_once (void); static
gpointer ctk_cell_area_box_parent_class = ((void*)0); static
gint CtkCellAreaBox_private_offset; static void ctk_cell_area_box_class_intern_init
(gpointer klass) { ctk_cell_area_box_parent_class = g_type_class_peek_parent
(klass); if (CtkCellAreaBox_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCellAreaBox_private_offset); ctk_cell_area_box_class_init
((CtkCellAreaBoxClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_cell_area_box_get_instance_private
(CtkCellAreaBox *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCellAreaBox_private_offset)))); } GType ctk_cell_area_box_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_cell_area_box_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_cell_area_box_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((ctk_cell_area_get_type ()), g_intern_static_string ("CtkCellAreaBox"
), sizeof (CtkCellAreaBoxClass), (GClassInitFunc)(void (*)(void
)) ctk_cell_area_box_class_intern_init, sizeof (CtkCellAreaBox
), (GInstanceInitFunc)(void (*)(void)) ctk_cell_area_box_init
, (GTypeFlags) 0); { {{ CtkCellAreaBox_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCellAreaBoxPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_cell_area_box_cell_layout_init, ((void*
)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_cell_layout_get_type ()), &g_implement_interface_info
); } { 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; }
241 G_IMPLEMENT_INTERFACE (CTK_TYPE_ORIENTABLE, NULL))static void ctk_cell_area_box_init (CtkCellAreaBox *self); static
void ctk_cell_area_box_class_init (CtkCellAreaBoxClass *klass
); static GType ctk_cell_area_box_get_type_once (void); static
gpointer ctk_cell_area_box_parent_class = ((void*)0); static
gint CtkCellAreaBox_private_offset; static void ctk_cell_area_box_class_intern_init
(gpointer klass) { ctk_cell_area_box_parent_class = g_type_class_peek_parent
(klass); if (CtkCellAreaBox_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkCellAreaBox_private_offset); ctk_cell_area_box_class_init
((CtkCellAreaBoxClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_cell_area_box_get_instance_private
(CtkCellAreaBox *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkCellAreaBox_private_offset)))); } GType ctk_cell_area_box_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_cell_area_box_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_cell_area_box_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((ctk_cell_area_get_type ()), g_intern_static_string ("CtkCellAreaBox"
), sizeof (CtkCellAreaBoxClass), (GClassInitFunc)(void (*)(void
)) ctk_cell_area_box_class_intern_init, sizeof (CtkCellAreaBox
), (GInstanceInitFunc)(void (*)(void)) ctk_cell_area_box_init
, (GTypeFlags) 0); { {{ CtkCellAreaBox_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkCellAreaBoxPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_cell_area_box_cell_layout_init, ((void*
)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_cell_layout_get_type ()), &g_implement_interface_info
); } { 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; }
242
243static void
244ctk_cell_area_box_init (CtkCellAreaBox *box)
245{
246 CtkCellAreaBoxPrivate *priv;
247
248 box->priv = ctk_cell_area_box_get_instance_private (box);
249 priv = box->priv;
250
251 priv->orientation = CTK_ORIENTATION_HORIZONTAL;
252 priv->groups = g_array_new (FALSE(0), TRUE(!(0)), sizeof (CellGroup));
253 priv->cells = NULL((void*)0);
254 priv->contexts = NULL((void*)0);
255 priv->spacing = 0;
256 priv->rtl = FALSE(0);
257
258 /* Watch whenever focus is given to a cell, even if it's not with keynav,
259 * this way we remember upon entry of the area where focus was last time
260 * around
261 */
262 priv->focus_cell_id = g_signal_connect (box, "notify::focus-cell",g_signal_connect_data ((box), ("notify::focus-cell"), (((GCallback
) (ctk_cell_area_box_focus_changed))), (box), ((void*)0), (GConnectFlags
) 0)
263 G_CALLBACK (ctk_cell_area_box_focus_changed), box)g_signal_connect_data ((box), ("notify::focus-cell"), (((GCallback
) (ctk_cell_area_box_focus_changed))), (box), ((void*)0), (GConnectFlags
) 0)
;
264}
265
266static void
267ctk_cell_area_box_class_init (CtkCellAreaBoxClass *class)
268{
269 GObjectClass *object_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
270 CtkCellAreaClass *area_class = CTK_CELL_AREA_CLASS (class)((((CtkCellAreaClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_cell_area_get_type ()))))))
;
271
272 /* GObjectClass */
273 object_class->finalize = ctk_cell_area_box_finalize;
274 object_class->dispose = ctk_cell_area_box_dispose;
275 object_class->set_property = ctk_cell_area_box_set_property;
276 object_class->get_property = ctk_cell_area_box_get_property;
277
278 /* CtkCellAreaClass */
279 area_class->add = ctk_cell_area_box_add;
280 area_class->remove = ctk_cell_area_box_remove;
281 area_class->foreach = ctk_cell_area_box_foreach;
282 area_class->foreach_alloc = ctk_cell_area_box_foreach_alloc;
283 area_class->apply_attributes = ctk_cell_area_box_apply_attributes;
284 area_class->set_cell_property = ctk_cell_area_box_set_cell_property;
285 area_class->get_cell_property = ctk_cell_area_box_get_cell_property;
286
287 area_class->create_context = ctk_cell_area_box_create_context;
288 area_class->copy_context = ctk_cell_area_box_copy_context;
289 area_class->get_request_mode = ctk_cell_area_box_get_request_mode;
290 area_class->get_preferred_width = ctk_cell_area_box_get_preferred_width;
291 area_class->get_preferred_height = ctk_cell_area_box_get_preferred_height;
292 area_class->get_preferred_height_for_width = ctk_cell_area_box_get_preferred_height_for_width;
293 area_class->get_preferred_width_for_height = ctk_cell_area_box_get_preferred_width_for_height;
294
295 area_class->focus = ctk_cell_area_box_focus;
296
297 /* Properties */
298 g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
299
300 /**
301 * CtkCellAreaBox:spacing:
302 *
303 * The amount of space to reserve between cells.
304 *
305 * Since: 3.0
306 */
307 g_object_class_install_property (object_class,
308 PROP_SPACING,
309 g_param_spec_int ("spacing",
310 P_("Spacing")g_dgettext("ctk30" "-properties","Spacing"),
311 P_("Space which is inserted between cells")g_dgettext("ctk30" "-properties","Space which is inserted between cells"
)
,
312 0,
313 G_MAXINT2147483647,
314 0,
315 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY));
316
317 /* Cell Properties */
318 /**
319 * CtkCellAreaBox:expand:
320 *
321 * Whether the cell renderer should receive extra space
322 * when the area receives more than its natural size.
323 *
324 * Since: 3.0
325 */
326 ctk_cell_area_class_install_cell_property (area_class,
327 CELL_PROP_EXPAND,
328 g_param_spec_boolean
329 ("expand",
330 P_("Expand")g_dgettext("ctk30" "-properties","Expand"),
331 P_("Whether the cell expands")g_dgettext("ctk30" "-properties","Whether the cell expands"),
332 FALSE(0),
333 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
334
335 /**
336 * CtkCellAreaBox:align:
337 *
338 * Whether the cell renderer should be aligned in adjacent rows.
339 *
340 * Since: 3.0
341 */
342 ctk_cell_area_class_install_cell_property (area_class,
343 CELL_PROP_ALIGN,
344 g_param_spec_boolean
345 ("align",
346 P_("Align")g_dgettext("ctk30" "-properties","Align"),
347 P_("Whether cell should align with adjacent rows")g_dgettext("ctk30" "-properties","Whether cell should align with adjacent rows"
)
,
348 FALSE(0),
349 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
350
351 /**
352 * CtkCellAreaBox:fixed-size:
353 *
354 * Whether the cell renderer should require the same size
355 * for all rows for which it was requested.
356 *
357 * Since: 3.0
358 */
359 ctk_cell_area_class_install_cell_property (area_class,
360 CELL_PROP_FIXED_SIZE,
361 g_param_spec_boolean
362 ("fixed-size",
363 P_("Fixed Size")g_dgettext("ctk30" "-properties","Fixed Size"),
364 P_("Whether cells should be the same size in all rows")g_dgettext("ctk30" "-properties","Whether cells should be the same size in all rows"
)
,
365 TRUE(!(0)),
366 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
367
368 /**
369 * CtkCellAreaBox:pack-type:
370 *
371 * A CtkPackType indicating whether the cell renderer is packed
372 * with reference to the start or end of the area.
373 *
374 * Since: 3.0
375 */
376 ctk_cell_area_class_install_cell_property (area_class,
377 CELL_PROP_PACK_TYPE,
378 g_param_spec_enum
379 ("pack-type",
380 P_("Pack Type")g_dgettext("ctk30" "-properties","Pack Type"),
381 P_("A CtkPackType indicating whether the cell is packed with "g_dgettext("ctk30" "-properties","A CtkPackType indicating whether the cell is packed with "
"reference to the start or end of the cell area")
382 "reference to the start or end of the cell area")g_dgettext("ctk30" "-properties","A CtkPackType indicating whether the cell is packed with "
"reference to the start or end of the cell area")
,
383 CTK_TYPE_PACK_TYPE(ctk_pack_type_get_type ()), CTK_PACK_START,
384 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
385}
386
387
388/*************************************************************
389 * CellInfo/CellGroup basics and convenience functions *
390 *************************************************************/
391static CellInfo *
392cell_info_new (CtkCellRenderer *renderer,
393 CtkPackType pack,
394 gboolean expand,
395 gboolean align,
396 gboolean fixed)
397{
398 CellInfo *info = g_slice_new (CellInfo)((CellInfo*) g_slice_alloc (sizeof (CellInfo)));
399
400 info->renderer = g_object_ref_sink (renderer)((__typeof__ (renderer)) (g_object_ref_sink) (renderer));
401 info->pack = pack;
402 info->expand = expand;
403 info->align = align;
404 info->fixed = fixed;
405
406 return info;
407}
408
409static void
410cell_info_free (CellInfo *info)
411{
412 g_object_unref (info->renderer);
413
414 g_slice_free (CellInfo, info)do { if (1) g_slice_free1 (sizeof (CellInfo), (info)); else (
void) ((CellInfo*) 0 == (info)); } while (0)
;
415}
416
417static gint
418cell_info_find (CellInfo *info,
419 CtkCellRenderer *renderer)
420{
421 return (info->renderer == renderer) ? 0 : -1;
422}
423
424static AllocatedCell *
425allocated_cell_new (CtkCellRenderer *renderer,
426 gint position,
427 gint size)
428{
429 AllocatedCell *cell = g_slice_new (AllocatedCell)((AllocatedCell*) g_slice_alloc (sizeof (AllocatedCell)));
430
431 cell->renderer = renderer;
432 cell->position = position;
433 cell->size = size;
434
435 return cell;
436}
437
438static void
439allocated_cell_free (AllocatedCell *cell)
440{
441 g_slice_free (AllocatedCell, cell)do { if (1) g_slice_free1 (sizeof (AllocatedCell), (cell)); else
(void) ((AllocatedCell*) 0 == (cell)); } while (0)
;
442}
443
444static GList *
445list_consecutive_cells (CtkCellAreaBox *box)
446{
447 CtkCellAreaBoxPrivate *priv = box->priv;
448 GList *l, *consecutive_cells = NULL((void*)0), *pack_end_cells = NULL((void*)0);
449 CellInfo *info;
450
451 /* List cells in consecutive order taking their
452 * PACK_START/PACK_END options into account
453 */
454 for (l = priv->cells; l; l = l->next)
455 {
456 info = l->data;
457
458 if (info->pack == CTK_PACK_START)
459 consecutive_cells = g_list_prepend (consecutive_cells, info);
460 }
461
462 for (l = priv->cells; l; l = l->next)
463 {
464 info = l->data;
465
466 if (info->pack == CTK_PACK_END)
467 pack_end_cells = g_list_prepend (pack_end_cells, info);
468 }
469
470 consecutive_cells = g_list_reverse (consecutive_cells);
471 consecutive_cells = g_list_concat (consecutive_cells, pack_end_cells);
472
473 return consecutive_cells;
474}
475
476static void
477cell_groups_clear (CtkCellAreaBox *box)
478{
479 CtkCellAreaBoxPrivate *priv = box->priv;
480 gint i;
481
482 for (i = 0; i < priv->groups->len; i++)
483 {
484 CellGroup *group = &g_array_index (priv->groups, CellGroup, i)(((CellGroup*) (void *) (priv->groups)->data) [(i)]);
485
486 g_list_free (group->cells);
487 }
488
489 g_array_set_size (priv->groups, 0);
490}
491
492static void
493cell_groups_rebuild (CtkCellAreaBox *box)
494{
495 CtkCellAreaBoxPrivate *priv = box->priv;
496 CellGroup group = { 0, };
497 CellGroup *group_ptr;
498 GList *cells, *l;
499 guint id = 0;
500 gboolean last_cell_fixed = FALSE(0);
501
502 cell_groups_clear (box);
503
504 if (!priv->cells)
505 return;
506
507 cells = list_consecutive_cells (box);
508
509 /* First group is implied */
510 g_array_append_val (priv->groups, group)g_array_append_vals (priv->groups, &(group), 1);
511 group_ptr = &g_array_index (priv->groups, CellGroup, id)(((CellGroup*) (void *) (priv->groups)->data) [(id)]);
512
513 for (l = cells; l; l = l->next)
514 {
515 CellInfo *info = l->data;
516
517 /* A new group starts with any aligned cell, or
518 * at the beginning and end of a fixed size cell.
519 * the first group is implied */
520 if ((info->align || info->fixed || last_cell_fixed) && l != cells)
521 {
522 memset (&group, 0x0, sizeof (CellGroup));
523 group.id = ++id;
524
525 g_array_append_val (priv->groups, group)g_array_append_vals (priv->groups, &(group), 1);
526 group_ptr = &g_array_index (priv->groups, CellGroup, id)(((CellGroup*) (void *) (priv->groups)->data) [(id)]);
527 }
528
529 group_ptr->cells = g_list_prepend (group_ptr->cells, info);
530 group_ptr->n_cells++;
531
532 /* Not every group is aligned, some are floating
533 * fixed size cells */
534 if (info->align)
535 group_ptr->align = TRUE(!(0));
536
537 /* A group expands if it contains any expand cells */
538 if (info->expand)
539 group_ptr->expand_cells++;
540
541 last_cell_fixed = info->fixed;
542 }
543
544 g_list_free (cells);
545
546 for (id = 0; id < priv->groups->len; id++)
547 {
548 group_ptr = &g_array_index (priv->groups, CellGroup, id)(((CellGroup*) (void *) (priv->groups)->data) [(id)]);
549
550 group_ptr->cells = g_list_reverse (group_ptr->cells);
551 }
552
553 /* Contexts need to be updated with the new grouping information */
554 init_context_groups (box);
555}
556
557static gint
558count_visible_cells (CellGroup *group,
559 gint *expand_cells)
560{
561 GList *l;
562 gint visible_cells = 0;
563 gint n_expand_cells = 0;
564
565 for (l = group->cells; l; l = l->next)
566 {
567 CellInfo *info = l->data;
568
569 if (ctk_cell_renderer_get_visible (info->renderer))
570 {
571 visible_cells++;
572
573 if (info->expand)
574 n_expand_cells++;
575 }
576 }
577
578 if (expand_cells)
579 *expand_cells = n_expand_cells;
580
581 return visible_cells;
582}
583
584static gint
585count_expand_groups (CtkCellAreaBox *box)
586{
587 CtkCellAreaBoxPrivate *priv = box->priv;
588 gint i;
589 gint expand_groups = 0;
590
591 for (i = 0; i < priv->groups->len; i++)
592 {
593 CellGroup *group = &g_array_index (priv->groups, CellGroup, i)(((CellGroup*) (void *) (priv->groups)->data) [(i)]);
594
595 if (group->expand_cells > 0)
596 expand_groups++;
597 }
598
599 return expand_groups;
600}
601
602static void
603context_weak_notify (CtkCellAreaBox *box,
604 CtkCellAreaBoxContext *dead_context)
605{
606 CtkCellAreaBoxPrivate *priv = box->priv;
607
608 priv->contexts = g_slist_remove (priv->contexts, dead_context);
609}
610
611static void
612init_context_group (CtkCellAreaBox *box,
613 CtkCellAreaBoxContext *context)
614{
615 CtkCellAreaBoxPrivate *priv = box->priv;
616 gint *expand_groups, *align_groups, i;
617
618 expand_groups = g_new (gboolean, priv->groups->len)((gboolean *) g_malloc_n ((priv->groups->len), sizeof (
gboolean)))
;
619 align_groups = g_new (gboolean, priv->groups->len)((gboolean *) g_malloc_n ((priv->groups->len), sizeof (
gboolean)))
;
620
621 for (i = 0; i < priv->groups->len; i++)
622 {
623 CellGroup *group = &g_array_index (priv->groups, CellGroup, i)(((CellGroup*) (void *) (priv->groups)->data) [(i)]);
624
625 expand_groups[i] = (group->expand_cells > 0);
626 align_groups[i] = group->align;
627 }
628
629 /* This call implies resetting the request info */
630 _ctk_cell_area_box_init_groups (context, priv->groups->len, expand_groups, align_groups);
631 g_free (expand_groups);
632 g_free (align_groups);
633}
634
635static void
636init_context_groups (CtkCellAreaBox *box)
637{
638 CtkCellAreaBoxPrivate *priv = box->priv;
639 GSList *l;
640
641 /* When the box's groups are reconstructed,
642 * contexts need to be reinitialized.
643 */
644 for (l = priv->contexts; l; l = l->next)
645 {
646 CtkCellAreaBoxContext *context = l->data;
647
648 init_context_group (box, context);
649 }
650}
651
652static void
653reset_contexts (CtkCellAreaBox *box)
654{
655 CtkCellAreaBoxPrivate *priv = box->priv;
656 GSList *l;
657
658 /* When the box layout changes, contexts need to
659 * be reset and sizes for the box get requested again
660 */
661 for (l = priv->contexts; l; l = l->next)
662 {
663 CtkCellAreaContext *context = l->data;
664
665 ctk_cell_area_context_reset (context);
666 }
667}
668
669/* Fall back on a completely unaligned dynamic allocation of cells
670 * when not allocated for the said orientation, alignment of cells
671 * is not done when each area gets a different size in the orientation
672 * of the box.
673 */
674static GSList *
675allocate_cells_manually (CtkCellAreaBox *box,
676 CtkWidget *widget,
677 gint width,
678 gint height)
679{
680 CtkCellAreaBoxPrivate *priv = box->priv;
681 GList *cells, *l;
682 GSList *allocated_cells = NULL((void*)0);
683 CtkRequestedSize *sizes;
684 gint i;
685 gint nvisible = 0, nexpand = 0, group_expand;
686 gint avail_size, extra_size, extra_extra, full_size;
687 gint position = 0, for_size;
688 gboolean rtl;
689
690 if (!priv->cells)
691 return NULL((void*)0);
692
693 /* For vertical oriented boxes, we just let the cell renderers
694 * realign themselves for rtl
695 */
696 rtl = (priv->orientation == CTK_ORIENTATION_HORIZONTAL &&
697 ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
698
699 cells = list_consecutive_cells (box);
700
701 /* Count the visible and expand cells */
702 for (i = 0; i < priv->groups->len; i++)
703 {
704 CellGroup *group = &g_array_index (priv->groups, CellGroup, i)(((CellGroup*) (void *) (priv->groups)->data) [(i)]);
705
706 nvisible += count_visible_cells (group, &group_expand);
707 nexpand += group_expand;
708 }
709
710 if (nvisible <= 0)
711 {
712 g_list_free (cells);
713 return NULL((void*)0);
714 }
715
716 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL)
717 {
718 full_size = avail_size = width;
719 for_size = height;
720 }
721 else
722 {
723 full_size = avail_size = height;
724 for_size = width;
725 }
726
727 /* Go ahead and collect the requests on the fly */
728 sizes = g_new0 (CtkRequestedSize, nvisible)((CtkRequestedSize *) g_malloc0_n ((nvisible), sizeof (CtkRequestedSize
)))
;
729 for (l = cells, i = 0; l; l = l->next)
730 {
731 CellInfo *info = l->data;
732
733 if (!ctk_cell_renderer_get_visible (info->renderer))
734 continue;
735
736 ctk_cell_area_request_renderer (CTK_CELL_AREA (box)((((CtkCellArea*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_cell_area_get_type ()))))))
, info->renderer,
737 priv->orientation,
738 widget, for_size,
739 &sizes[i].minimum_size,
740 &sizes[i].natural_size);
741
742 avail_size -= sizes[i].minimum_size;
743
744 sizes[i].data = info;
745
746 i++;
747 }
748
749 /* Naturally distribute the allocation */
750 avail_size -= (nvisible - 1) * priv->spacing;
751 if (avail_size > 0)
752 avail_size = ctk_distribute_natural_allocation (avail_size, nvisible, sizes);
753 else
754 avail_size = 0;
755
756 /* Calculate/distribute expand for cells */
757 if (nexpand > 0)
758 {
759 extra_size = avail_size / nexpand;
760 extra_extra = avail_size % nexpand;
761 }
762 else
763 extra_size = extra_extra = 0;
764
765 /* Create the allocated cells */
766 for (i = 0; i < nvisible; i++)
767 {
768 CellInfo *info = sizes[i].data;
769 AllocatedCell *cell;
770
771 if (info->expand)
772 {
773 sizes[i].minimum_size += extra_size;
774 if (extra_extra)
775 {
776 sizes[i].minimum_size++;
777 extra_extra--;
778 }
779 }
780
781 if (rtl)
782 cell = allocated_cell_new (info->renderer,
783 full_size - (position + sizes[i].minimum_size),
784 sizes[i].minimum_size);
785 else
786 cell = allocated_cell_new (info->renderer, position, sizes[i].minimum_size);
787
788 allocated_cells = g_slist_prepend (allocated_cells, cell);
789
790 position += sizes[i].minimum_size;
791 position += priv->spacing;
792 }
793
794 g_free (sizes);
795 g_list_free (cells);
796
797 /* Note it might not be important to reverse the list here at all,
798 * we have the correct positions, no need to allocate from left to right
799 */
800 return g_slist_reverse (allocated_cells);
801}
802
803/* Returns an allocation for each cell in the orientation of the box,
804 * used in ->render()/->event() implementations to get a straight-forward
805 * list of allocated cells to operate on.
806 */
807static GSList *
808get_allocated_cells (CtkCellAreaBox *box,
809 CtkCellAreaBoxContext *context,
810 CtkWidget *widget,
811 gint width,
812 gint height)
813{
814 CtkCellAreaBoxAllocation *group_allocs;
815 CtkCellArea *area = CTK_CELL_AREA (box)((((CtkCellArea*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_cell_area_get_type ()))))))
;
816 CtkCellAreaBoxPrivate *priv = box->priv;
817 GList *cell_list;
818 GSList *allocated_cells = NULL((void*)0);
819 gint i, j, n_allocs, position;
820 gint for_size, full_size;
821 gboolean rtl;
822
823 group_allocs = _ctk_cell_area_box_context_get_orientation_allocs (context, &n_allocs);
824 if (!group_allocs)
825 return allocate_cells_manually (box, widget, width, height);
826
827 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL)
828 {
829 full_size = width;
830 for_size = height;
831 }
832 else
833 {
834 full_size = height;
835 for_size = width;
836 }
837
838 /* For vertical oriented boxes, we just let the cell renderers
839 * realign themselves for rtl
840 */
841 rtl = (priv->orientation == CTK_ORIENTATION_HORIZONTAL &&
842 ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
843
844 for (position = 0, i = 0; i < n_allocs; i++)
845 {
846 /* We dont always allocate all groups, sometimes the requested
847 * group has only invisible cells for every row, hence the usage
848 * of group_allocs[i].group_idx here
849 */
850 CellGroup *group = &g_array_index (priv->groups, CellGroup, group_allocs[i].group_idx)(((CellGroup*) (void *) (priv->groups)->data) [(group_allocs
[i].group_idx)])
;
851
852 /* Exception for single cell groups */
853 if (group->n_cells == 1)
854 {
855 CellInfo *info = group->cells->data;
856 AllocatedCell *cell;
857 gint cell_position, cell_size;
858
859 if (!ctk_cell_renderer_get_visible (info->renderer))
860 continue;
861
862 /* If were not aligned, place the cell after the last cell */
863 if (info->align)
864 position = cell_position = group_allocs[i].position;
865 else
866 cell_position = position;
867
868 /* If not a fixed size, use only the requested size for this row */
869 if (info->fixed)
870 cell_size = group_allocs[i].size;
871 else
872 {
873 gint dummy;
874 ctk_cell_area_request_renderer (area, info->renderer,
875 priv->orientation,
876 widget, for_size,
877 &dummy,
878 &cell_size);
879 cell_size = MIN (cell_size, group_allocs[i].size)(((cell_size) < (group_allocs[i].size)) ? (cell_size) : (group_allocs
[i].size))
;
880 }
881
882 if (rtl)
883 cell = allocated_cell_new (info->renderer,
884 full_size - (cell_position + cell_size), cell_size);
885 else
886 cell = allocated_cell_new (info->renderer, cell_position, cell_size);
887
888 position += cell_size;
889 position += priv->spacing;
890
891 allocated_cells = g_slist_prepend (allocated_cells, cell);
892 }
893 else
894 {
895 CtkRequestedSize *sizes;
896 gint avail_size, cell_position;
897 gint visible_cells, expand_cells;
898 gint extra_size, extra_extra;
899
900 visible_cells = count_visible_cells (group, &expand_cells);
901
902 /* If this row has no visible cells in this group, just
903 * skip the allocation
904 */
905 if (visible_cells == 0)
906 continue;
907
908 /* If were not aligned, place the cell after the last cell
909 * and eat up the extra space
910 */
911 if (group->align)
912 {
913 avail_size = group_allocs[i].size;
914 position = cell_position = group_allocs[i].position;
915 }
916 else
917 {
918 avail_size = group_allocs[i].size + (group_allocs[i].position - position);
919 cell_position = position;
920 }
921
922 sizes = g_new (CtkRequestedSize, visible_cells)((CtkRequestedSize *) g_malloc_n ((visible_cells), sizeof (CtkRequestedSize
)))
;
923
924 for (j = 0, cell_list = group->cells; cell_list; cell_list = cell_list->next)
925 {
926 CellInfo *info = cell_list->data;
927
928 if (!ctk_cell_renderer_get_visible (info->renderer))
929 continue;
930
931 ctk_cell_area_request_renderer (area, info->renderer,
932 priv->orientation,
933 widget, for_size,
934 &sizes[j].minimum_size,
935 &sizes[j].natural_size);
936
937 sizes[j].data = info;
938 avail_size -= sizes[j].minimum_size;
939
940 j++;
941 }
942
943 /* Distribute cells naturally within the group */
944 avail_size -= (visible_cells - 1) * priv->spacing;
945 if (avail_size > 0)
946 avail_size = ctk_distribute_natural_allocation (avail_size, visible_cells, sizes);
947 else
948 avail_size = 0;
949
950 /* Calculate/distribute expand for cells */
951 if (expand_cells > 0)
952 {
953 extra_size = avail_size / expand_cells;
954 extra_extra = avail_size % expand_cells;
955 }
956 else
957 extra_size = extra_extra = 0;
958
959 /* Create the allocated cells (loop only over visible cells here) */
960 for (j = 0; j < visible_cells; j++)
961 {
962 CellInfo *info = sizes[j].data;
963 AllocatedCell *cell;
964
965 if (info->expand)
966 {
967 sizes[j].minimum_size += extra_size;
968 if (extra_extra)
969 {
970 sizes[j].minimum_size++;
971 extra_extra--;
972 }
973 }
974
975 if (rtl)
976 cell = allocated_cell_new (info->renderer,
977 full_size - (cell_position + sizes[j].minimum_size),
978 sizes[j].minimum_size);
979 else
980 cell = allocated_cell_new (info->renderer, cell_position, sizes[j].minimum_size);
981
982 allocated_cells = g_slist_prepend (allocated_cells, cell);
983
984 cell_position += sizes[j].minimum_size;
985 cell_position += priv->spacing;
986 }
987
988 g_free (sizes);
989
990 position = cell_position;
991 }
992 }
993
994 g_free (group_allocs);
995
996 /* Note it might not be important to reverse the list here at all,
997 * we have the correct positions, no need to allocate from left to right
998 */
999 return g_slist_reverse (allocated_cells);
1000}
1001
1002
1003static void
1004ctk_cell_area_box_focus_changed (CtkCellArea *area,
1005 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
1006 CtkCellAreaBox *box)
1007{
1008 if (ctk_cell_area_get_focus_cell (area))
1009 box->priv->last_focus_cell = ctk_cell_area_get_focus_cell (area);
1010}
1011
1012/*************************************************************
1013 * GObjectClass *
1014 *************************************************************/
1015static void
1016ctk_cell_area_box_finalize (GObject *object)
1017{
1018 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (object)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_cell_area_box_get_type ()))))))
;
1019 CtkCellAreaBoxPrivate *priv = box->priv;
1020 GSList *l;
1021
1022 /* Unref/free the context list */
1023 for (l = priv->contexts; l; l = l->next)
1024 g_object_weak_unref (G_OBJECT (l->data)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (((GType) ((20) << (2))))))))
, (GWeakNotify)context_weak_notify, box);
1025
1026 g_slist_free (priv->contexts);
1027 priv->contexts = NULL((void*)0);
1028
1029 /* Free the cell grouping info */
1030 cell_groups_clear (box);
1031 g_array_free (priv->groups, TRUE(!(0)));
1032
1033 G_OBJECT_CLASS (ctk_cell_area_box_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_cell_area_box_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
1034}
1035
1036static void
1037ctk_cell_area_box_dispose (GObject *object)
1038{
1039 G_OBJECT_CLASS (ctk_cell_area_box_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_cell_area_box_parent_class)), (((GType) ((20) <<
(2))))))))
->dispose (object);
1040}
1041
1042static void
1043ctk_cell_area_box_set_property (GObject *object,
1044 guint prop_id,
1045 const GValue *value,
1046 GParamSpec *pspec)
1047{
1048 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (object)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_cell_area_box_get_type ()))))))
;
1049
1050 switch (prop_id)
1051 {
1052 case PROP_ORIENTATION:
1053 if (box->priv->orientation != g_value_get_enum (value))
1054 {
1055 box->priv->orientation = g_value_get_enum (value);
1056 /* Notify that size needs to be requested again */
1057 reset_contexts (box);
1058 g_object_notify_by_pspec (object, pspec);
1059 }
1060 break;
1061 case PROP_SPACING:
1062 ctk_cell_area_box_set_spacing (box, g_value_get_int (value));
1063 break;
1064 default:
1065 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'"
, "ctkcellareabox.c", 1065, ("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)
;
1066 break;
1067 }
1068}
1069
1070static void
1071ctk_cell_area_box_get_property (GObject *object,
1072 guint prop_id,
1073 GValue *value,
1074 GParamSpec *pspec)
1075{
1076 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (object)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_cell_area_box_get_type ()))))))
;
1077
1078 switch (prop_id)
1079 {
1080 case PROP_ORIENTATION:
1081 g_value_set_enum (value, box->priv->orientation);
1082 break;
1083 case PROP_SPACING:
1084 g_value_set_int (value, ctk_cell_area_box_get_spacing (box));
1085 break;
1086 default:
1087 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'"
, "ctkcellareabox.c", 1087, ("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)
;
1088 break;
1089 }
1090}
1091
1092/*************************************************************
1093 * CtkCellAreaClass *
1094 *************************************************************/
1095static void
1096ctk_cell_area_box_add (CtkCellArea *area,
1097 CtkCellRenderer *renderer)
1098{
1099 ctk_cell_area_box_pack_start (CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
,
1100 renderer, FALSE(0), FALSE(0), TRUE(!(0)));
1101}
1102
1103static void
1104ctk_cell_area_box_remove (CtkCellArea *area,
1105 CtkCellRenderer *renderer)
1106{
1107 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1108 CtkCellAreaBoxPrivate *priv = box->priv;
1109 GList *node;
1110
1111 if (priv->last_focus_cell == renderer)
1112 priv->last_focus_cell = NULL((void*)0);
1113
1114 node = g_list_find_custom (priv->cells, renderer,
1115 (GCompareFunc)cell_info_find);
1116
1117 if (node)
1118 {
1119 CellInfo *info = node->data;
1120
1121 cell_info_free (info);
1122
1123 priv->cells = g_list_delete_link (priv->cells, node);
1124
1125 /* Reconstruct cell groups */
1126 cell_groups_rebuild (box);
1127 }
1128 else
1129 g_warning ("Trying to remove a cell renderer that is not present CtkCellAreaBox");
1130}
1131
1132static void
1133ctk_cell_area_box_foreach (CtkCellArea *area,
1134 CtkCellCallback callback,
1135 gpointer callback_data)
1136{
1137 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1138 CtkCellAreaBoxPrivate *priv = box->priv;
1139 GList *list;
1140
1141 for (list = priv->cells; list; list = list->next)
1142 {
1143 CellInfo *info = list->data;
1144
1145 if (callback (info->renderer, callback_data))
1146 break;
1147 }
1148}
1149
1150static void
1151ctk_cell_area_box_foreach_alloc (CtkCellArea *area,
1152 CtkCellAreaContext *context,
1153 CtkWidget *widget,
1154 const CdkRectangle *cell_area,
1155 const CdkRectangle *background_area,
1156 CtkCellAllocCallback callback,
1157 gpointer callback_data)
1158{
1159 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1160 CtkCellAreaBoxPrivate *priv = box->priv;
1161 CtkCellAreaBoxContext *box_context = CTK_CELL_AREA_BOX_CONTEXT (context)((((CtkCellAreaBoxContext*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), ((_ctk_cell_area_box_context_get_type
()))))))
;
1162 GSList *allocated_cells, *l;
1163 CdkRectangle cell_alloc, cell_background;
1164 gboolean rtl;
1165
1166 rtl = (priv->orientation == CTK_ORIENTATION_HORIZONTAL &&
1167 ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
1168
1169 cell_alloc = *cell_area;
1170
1171 /* Get a list of cells with allocation sizes decided regardless
1172 * of alignments and pack order etc.
1173 */
1174 allocated_cells = get_allocated_cells (box, box_context, widget,
1175 cell_area->width, cell_area->height);
1176
1177 for (l = allocated_cells; l; l = l->next)
1178 {
1179 AllocatedCell *cell = l->data;
1180
1181 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL)
1182 {
1183 cell_alloc.x = cell_area->x + cell->position;
1184 cell_alloc.width = cell->size;
1185 }
1186 else
1187 {
1188 cell_alloc.y = cell_area->y + cell->position;
1189 cell_alloc.height = cell->size;
1190 }
1191
1192 /* Stop iterating over cells if they flow out of the render
1193 * area, this can happen because the render area can actually
1194 * be smaller than the requested area (treeview columns can
1195 * be user resizable and can be resized to be smaller than
1196 * the actual requested area).
1197 */
1198 if (cell_alloc.x > cell_area->x + cell_area->width ||
1199 cell_alloc.x + cell_alloc.width < cell_area->x ||
1200 cell_alloc.y > cell_area->y + cell_area->height)
1201 break;
1202
1203 /* Special case for the last cell (or first cell in rtl)...
1204 * let the last cell consume the remaining space in the area
1205 * (the last cell is allowed to consume the remaining space if
1206 * the space given for rendering is actually larger than allocation,
1207 * this can happen in the expander CtkTreeViewColumn where only the
1208 * deepest depth column receives the allocation... shallow columns
1209 * receive more width). */
1210 if (!l->next)
1211 {
1212 if (rtl)
1213 {
1214 /* Fill the leading space for the first cell in the area
1215 * (still last in the list)
1216 */
1217 cell_alloc.width = (cell_alloc.x - cell_area->x) + cell_alloc.width;
1218 cell_alloc.x = cell_area->x;
1219 }
1220 else
1221 {
1222 cell_alloc.width = cell_area->x + cell_area->width - cell_alloc.x;
1223 cell_alloc.height = cell_area->y + cell_area->height - cell_alloc.y;
1224 }
1225 }
1226 else
1227 {
1228 /* If the cell we are rendering doesnt fit into the remaining space,
1229 * clip it so that the underlying renderer has a chance to deal with
1230 * it (for instance text renderers get a chance to ellipsize).
1231 */
1232 if (cell_alloc.x + cell_alloc.width > cell_area->x + cell_area->width)
1233 cell_alloc.width = cell_area->x + cell_area->width - cell_alloc.x;
1234
1235 if (cell_alloc.y + cell_alloc.height > cell_area->y + cell_area->height)
1236 cell_alloc.height = cell_area->y + cell_area->height - cell_alloc.y;
1237 }
1238
1239 /* Add portions of the background_area to the cell_alloc
1240 * to create the cell_background
1241 */
1242 cell_background = cell_alloc;
1243
1244 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL)
1245 {
1246 if (l == allocated_cells)
1247 {
1248 /* Add the depth to the first cell */
1249 if (rtl)
1250 {
1251 cell_background.width += background_area->width - cell_area->width;
1252 cell_background.x = background_area->x + background_area->width - cell_background.width;
1253 }
1254 else
1255 {
1256 cell_background.width += cell_area->x - background_area->x;
1257 cell_background.x = background_area->x;
1258 }
1259 }
1260
1261 if (l->next == NULL((void*)0))
1262 {
1263 /* Grant this cell the remaining space */
1264 int remain = cell_background.x - background_area->x;
1265
1266 if (rtl)
1267 cell_background.x -= remain;
1268 else
1269 cell_background.width = background_area->width - remain;
1270 }
1271
1272 cell_background.y = background_area->y;
1273 cell_background.height = background_area->height;
1274 }
1275 else
1276 {
1277 if (l == allocated_cells)
1278 {
1279 cell_background.height += cell_background.y - background_area->y;
1280 cell_background.y = background_area->y;
1281 }
1282
1283 if (l->next == NULL((void*)0))
1284 cell_background.height =
1285 background_area->height - (cell_background.y - background_area->y);
1286
1287 cell_background.x = background_area->x;
1288 cell_background.width = background_area->width;
1289 }
1290
1291 if (callback (cell->renderer, &cell_alloc, &cell_background, callback_data))
1292 break;
1293 }
1294
1295 g_slist_free_full (allocated_cells, (GDestroyNotify)allocated_cell_free);
1296}
1297
1298static void
1299ctk_cell_area_box_apply_attributes (CtkCellArea *area,
1300 CtkTreeModel *tree_model,
1301 CtkTreeIter *iter,
1302 gboolean is_expander,
1303 gboolean is_expanded)
1304{
1305 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1306 CtkCellAreaBoxPrivate *priv = box->priv;
1307 gint i;
1308
1309 /* Call the parent class to apply the attributes */
1310 CTK_CELL_AREA_CLASS((((CtkCellAreaClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_cell_area_box_parent_class)), ((ctk_cell_area_get_type
()))))))
1311 (ctk_cell_area_box_parent_class)((((CtkCellAreaClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_cell_area_box_parent_class)), ((ctk_cell_area_get_type
()))))))
->apply_attributes (area, tree_model, iter,
1312 is_expander, is_expanded);
1313
1314 /* Update visible state for cell groups */
1315 for (i = 0; i < priv->groups->len; i++)
1316 {
1317 CellGroup *group = &g_array_index (priv->groups, CellGroup, i)(((CellGroup*) (void *) (priv->groups)->data) [(i)]);
1318 GList *list;
1319
1320 group->visible = FALSE(0);
1321
1322 for (list = group->cells; list && group->visible == FALSE(0); list = list->next)
1323 {
1324 CellInfo *info = list->data;
1325
1326 if (ctk_cell_renderer_get_visible (info->renderer))
1327 group->visible = TRUE(!(0));
1328 }
1329 }
1330}
1331
1332static void
1333ctk_cell_area_box_set_cell_property (CtkCellArea *area,
1334 CtkCellRenderer *renderer,
1335 guint prop_id,
1336 const GValue *value,
1337 GParamSpec *pspec)
1338{
1339 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1340 CtkCellAreaBoxPrivate *priv = box->priv;
1341 GList *node;
1342 CellInfo *info;
1343 gboolean rebuild = FALSE(0);
1344 gboolean val;
1345 CtkPackType pack_type;
1346
1347 node = g_list_find_custom (priv->cells, renderer,
1348 (GCompareFunc)cell_info_find);
1349 if (!node)
1350 return;
1351
1352 info = node->data;
1353
1354 switch (prop_id)
1355 {
1356 case CELL_PROP_EXPAND:
1357 val = g_value_get_boolean (value);
1358
1359 if (info->expand != val)
1360 {
1361 info->expand = val;
1362 rebuild = TRUE(!(0));
1363 }
1364 break;
1365
1366 case CELL_PROP_ALIGN:
1367 val = g_value_get_boolean (value);
1368
1369 if (info->align != val)
1370 {
1371 info->align = val;
1372 rebuild = TRUE(!(0));
1373 }
1374 break;
1375
1376 case CELL_PROP_FIXED_SIZE:
1377 val = g_value_get_boolean (value);
1378
1379 if (info->fixed != val)
1380 {
1381 info->fixed = val;
1382 rebuild = TRUE(!(0));
1383 }
1384 break;
1385
1386 case CELL_PROP_PACK_TYPE:
1387 pack_type = g_value_get_enum (value);
1388
1389 if (info->pack != pack_type)
1390 {
1391 info->pack = pack_type;
1392 rebuild = TRUE(!(0));
1393 }
1394 break;
1395 default:
1396 CTK_CELL_AREA_WARN_INVALID_CELL_PROPERTY_ID (area, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((area)); 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'"
, "ctkcellareabox.c", 1396, ("cell property id"), _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)
;
1397 break;
1398 }
1399
1400 /* Groups need to be rebuilt */
1401 if (rebuild)
1402 cell_groups_rebuild (box);
1403}
1404
1405static void
1406ctk_cell_area_box_get_cell_property (CtkCellArea *area,
1407 CtkCellRenderer *renderer,
1408 guint prop_id,
1409 GValue *value,
1410 GParamSpec *pspec)
1411{
1412 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1413 CtkCellAreaBoxPrivate *priv = box->priv;
1414 GList *node;
1415 CellInfo *info;
1416
1417 node = g_list_find_custom (priv->cells, renderer,
1418 (GCompareFunc)cell_info_find);
1419 if (!node)
1420 return;
1421
1422 info = node->data;
1423
1424 switch (prop_id)
1425 {
1426 case CELL_PROP_EXPAND:
1427 g_value_set_boolean (value, info->expand);
1428 break;
1429
1430 case CELL_PROP_ALIGN:
1431 g_value_set_boolean (value, info->align);
1432 break;
1433
1434 case CELL_PROP_FIXED_SIZE:
1435 g_value_set_boolean (value, info->fixed);
1436 break;
1437
1438 case CELL_PROP_PACK_TYPE:
1439 g_value_set_enum (value, info->pack);
1440 break;
1441 default:
1442 CTK_CELL_AREA_WARN_INVALID_CELL_PROPERTY_ID (area, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((area)); 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'"
, "ctkcellareabox.c", 1442, ("cell property id"), _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)
;
1443 break;
1444 }
1445}
1446
1447
1448static CtkCellAreaContext *
1449ctk_cell_area_box_create_context (CtkCellArea *area)
1450{
1451 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1452 CtkCellAreaBoxPrivate *priv = box->priv;
1453 CtkCellAreaContext *context =
1454 (CtkCellAreaContext *)g_object_new (CTK_TYPE_CELL_AREA_BOX_CONTEXT(_ctk_cell_area_box_context_get_type ()),
1455 "area", area, NULL((void*)0));
1456
1457 priv->contexts = g_slist_prepend (priv->contexts, context);
1458
1459 g_object_weak_ref (G_OBJECT (context)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((context)), (((GType) ((20) << (2))))))))
, (GWeakNotify)context_weak_notify, box);
1460
1461 /* Tell the new group about our cell layout */
1462 init_context_group (box, CTK_CELL_AREA_BOX_CONTEXT (context)((((CtkCellAreaBoxContext*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), ((_ctk_cell_area_box_context_get_type
()))))))
);
1463
1464 return context;
1465}
1466
1467static CtkCellAreaContext *
1468ctk_cell_area_box_copy_context (CtkCellArea *area,
1469 CtkCellAreaContext *context)
1470{
1471 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1472 CtkCellAreaBoxPrivate *priv = box->priv;
1473 CtkCellAreaContext *copy =
1474 (CtkCellAreaContext *)_ctk_cell_area_box_context_copy (CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
,
1475 CTK_CELL_AREA_BOX_CONTEXT (context)((((CtkCellAreaBoxContext*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), ((_ctk_cell_area_box_context_get_type
()))))))
);
1476
1477 priv->contexts = g_slist_prepend (priv->contexts, copy);
1478
1479 g_object_weak_ref (G_OBJECT (copy)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((copy)), (((GType) ((20) << (2))))))))
, (GWeakNotify)context_weak_notify, box);
1480
1481 return copy;
1482}
1483
1484static CtkSizeRequestMode
1485ctk_cell_area_box_get_request_mode (CtkCellArea *area)
1486{
1487 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1488 CtkCellAreaBoxPrivate *priv = box->priv;
1489
1490 return (priv->orientation) == CTK_ORIENTATION_HORIZONTAL ?
1491 CTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH :
1492 CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
1493}
1494
1495static void
1496compute_size (CtkCellAreaBox *box,
1497 CtkOrientation orientation,
1498 CtkCellAreaBoxContext *context,
1499 CtkWidget *widget,
1500 gint for_size,
1501 gint *minimum_size,
1502 gint *natural_size)
1503{
1504 CtkCellAreaBoxPrivate *priv = box->priv;
1505 CtkCellArea *area = CTK_CELL_AREA (box)((((CtkCellArea*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_cell_area_get_type ()))))))
;
1506 GList *list;
1507 gint i;
1508 gint min_size = 0;
1509 gint nat_size = 0;
1510
1511 for (i = 0; i < priv->groups->len; i++)
1512 {
1513 CellGroup *group = &g_array_index (priv->groups, CellGroup, i)(((CellGroup*) (void *) (priv->groups)->data) [(i)]);
1514 gint group_min_size = 0;
1515 gint group_nat_size = 0;
1516
1517 for (list = group->cells; list; list = list->next)
1518 {
1519 CellInfo *info = list->data;
1520 gint renderer_min_size, renderer_nat_size;
1521
1522 if (!ctk_cell_renderer_get_visible (info->renderer))
1523 continue;
1524
1525 ctk_cell_area_request_renderer (area, info->renderer, orientation, widget, for_size,
1526 &renderer_min_size, &renderer_nat_size);
1527
1528 if (orientation == priv->orientation)
1529 {
1530 if (min_size > 0)
1531 {
1532 min_size += priv->spacing;
1533 nat_size += priv->spacing;
1534 }
1535
1536 if (group_min_size > 0)
1537 {
1538 group_min_size += priv->spacing;
1539 group_nat_size += priv->spacing;
1540 }
1541
1542 min_size += renderer_min_size;
1543 nat_size += renderer_nat_size;
1544 group_min_size += renderer_min_size;
1545 group_nat_size += renderer_nat_size;
1546 }
1547 else
1548 {
1549 min_size = MAX (min_size, renderer_min_size)(((min_size) > (renderer_min_size)) ? (min_size) : (renderer_min_size
))
;
1550 nat_size = MAX (nat_size, renderer_nat_size)(((nat_size) > (renderer_nat_size)) ? (nat_size) : (renderer_nat_size
))
;
1551 group_min_size = MAX (group_min_size, renderer_min_size)(((group_min_size) > (renderer_min_size)) ? (group_min_size
) : (renderer_min_size))
;
1552 group_nat_size = MAX (group_nat_size, renderer_nat_size)(((group_nat_size) > (renderer_nat_size)) ? (group_nat_size
) : (renderer_nat_size))
;
1553 }
1554 }
1555
1556 if (orientation == CTK_ORIENTATION_HORIZONTAL)
1557 {
1558 if (for_size < 0)
1559 _ctk_cell_area_box_context_push_group_width (context, group->id, group_min_size, group_nat_size);
1560 else
1561 _ctk_cell_area_box_context_push_group_width_for_height (context, group->id, for_size,
1562 group_min_size, group_nat_size);
1563 }
1564 else
1565 {
1566 if (for_size < 0)
1567 _ctk_cell_area_box_context_push_group_height (context, group->id, group_min_size, group_nat_size);
1568 else
1569 _ctk_cell_area_box_context_push_group_height_for_width (context, group->id, for_size,
1570 group_min_size, group_nat_size);
1571 }
1572 }
1573
1574 *minimum_size = min_size;
1575 *natural_size = nat_size;
1576
1577 /* Update rtl state for focus navigation to work */
1578 priv->rtl = (priv->orientation == CTK_ORIENTATION_HORIZONTAL &&
1579 ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
1580}
1581
1582static CtkRequestedSize *
1583get_group_sizes (CtkCellArea *area,
1584 CellGroup *group,
1585 CtkOrientation orientation,
1586 CtkWidget *widget,
1587 gint *n_sizes)
1588{
1589 CtkRequestedSize *sizes;
1590 GList *l;
1591 gint i;
1592
1593 *n_sizes = count_visible_cells (group, NULL((void*)0));
1594 sizes = g_new (CtkRequestedSize, *n_sizes)((CtkRequestedSize *) g_malloc_n ((*n_sizes), sizeof (CtkRequestedSize
)))
;
25
Memory is allocated
1595
1596 for (l = group->cells, i = 0; l; l = l->next)
26
Loop condition is true. Entering loop body
1597 {
1598 CellInfo *info = l->data;
1599
1600 if (!ctk_cell_renderer_get_visible (info->renderer))
27
Assuming the condition is false
28
Taking false branch
1601 continue;
1602
1603 sizes[i].data = info;
29
Use of memory allocated with size zero
1604
1605 ctk_cell_area_request_renderer (area, info->renderer,
1606 orientation, widget, -1,
1607 &sizes[i].minimum_size,
1608 &sizes[i].natural_size);
1609
1610 i++;
1611 }
1612
1613 return sizes;
1614}
1615
1616static void
1617compute_group_size_for_opposing_orientation (CtkCellAreaBox *box,
1618 CellGroup *group,
1619 CtkWidget *widget,
1620 gint for_size,
1621 gint *minimum_size,
1622 gint *natural_size)
1623{
1624 CtkCellAreaBoxPrivate *priv = box->priv;
1625 CtkCellArea *area = CTK_CELL_AREA (box)((((CtkCellArea*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), ((ctk_cell_area_get_type ()))))))
;
1626
1627 /* Exception for single cell groups */
1628 if (group->n_cells == 1)
22
Assuming field 'n_cells' is not equal to 1
23
Taking false branch
1629 {
1630 CellInfo *info = group->cells->data;
1631
1632 ctk_cell_area_request_renderer (area, info->renderer,
1633 OPPOSITE_ORIENTATION (priv->orientation)(1 - (priv->orientation)),
1634 widget, for_size, minimum_size, natural_size);
1635 }
1636 else
1637 {
1638 CtkRequestedSize *orientation_sizes;
1639 gint n_sizes, i;
1640 gint avail_size = for_size;
1641 gint extra_size, extra_extra;
1642 gint min_size = 0, nat_size = 0;
1643
1644 orientation_sizes = get_group_sizes (area, group, priv->orientation, widget, &n_sizes);
24
Calling 'get_group_sizes'
1645
1646 /* First naturally allocate the cells in the group into the for_size */
1647 avail_size -= (n_sizes - 1) * priv->spacing;
1648 for (i = 0; i < n_sizes; i++)
1649 avail_size -= orientation_sizes[i].minimum_size;
1650
1651 if (avail_size > 0)
1652 avail_size = ctk_distribute_natural_allocation (avail_size, n_sizes, orientation_sizes);
1653 else
1654 avail_size = 0;
1655
1656 /* Calculate/distribute expand for cells */
1657 if (group->expand_cells > 0)
1658 {
1659 extra_size = avail_size / group->expand_cells;
1660 extra_extra = avail_size % group->expand_cells;
1661 }
1662 else
1663 extra_size = extra_extra = 0;
1664
1665 for (i = 0; i < n_sizes; i++)
1666 {
1667 CellInfo *info;
1668
1669 gint cell_min, cell_nat;
1670
1671 info = orientation_sizes[i].data;
1672
1673 if (info->expand)
1674 {
1675 orientation_sizes[i].minimum_size += extra_size;
1676 if (extra_extra)
1677 {
1678 orientation_sizes[i].minimum_size++;
1679 extra_extra--;
1680 }
1681 }
1682
1683 ctk_cell_area_request_renderer (area, info->renderer,
1684 OPPOSITE_ORIENTATION (priv->orientation)(1 - (priv->orientation)),
1685 widget,
1686 orientation_sizes[i].minimum_size,
1687 &cell_min, &cell_nat);
1688
1689 min_size = MAX (min_size, cell_min)(((min_size) > (cell_min)) ? (min_size) : (cell_min));
1690 nat_size = MAX (nat_size, cell_nat)(((nat_size) > (cell_nat)) ? (nat_size) : (cell_nat));
1691 }
1692
1693 *minimum_size = min_size;
1694 *natural_size = nat_size;
1695
1696 g_free (orientation_sizes);
1697 }
1698}
1699
1700static void
1701compute_size_for_opposing_orientation (CtkCellAreaBox *box,
1702 CtkCellAreaBoxContext *context,
1703 CtkWidget *widget,
1704 gint for_size,
1705 gint *minimum_size,
1706 gint *natural_size)
1707{
1708 CtkCellAreaBoxPrivate *priv = box->priv;
1709 CtkRequestedSize *orientation_sizes;
1710 gint n_groups, n_expand_groups, i;
1711 gint avail_size = for_size;
1712 gint extra_size, extra_extra;
1713 gint min_size = 0, nat_size = 0;
1714
1715 n_expand_groups = count_expand_groups (box);
1716
1717 if (priv->orientation
9.1
Field 'orientation' is not equal to CTK_ORIENTATION_HORIZONTAL
== CTK_ORIENTATION_HORIZONTAL)
10
Taking false branch
1718 orientation_sizes = _ctk_cell_area_box_context_get_widths (context, &n_groups);
1719 else
1720 orientation_sizes = _ctk_cell_area_box_context_get_heights (context, &n_groups);
1721
1722 /* First start by naturally allocating space among groups of cells */
1723 avail_size -= (n_groups - 1) * priv->spacing;
1724 for (i = 0; i < n_groups; i++)
11
Assuming 'i' is < 'n_groups'
12
Loop condition is true. Entering loop body
13
Assuming 'i' is >= 'n_groups'
14
Loop condition is false. Execution continues on line 1727
1725 avail_size -= orientation_sizes[i].minimum_size;
1726
1727 if (avail_size > 0)
15
Assuming 'avail_size' is <= 0
16
Taking false branch
1728 avail_size = ctk_distribute_natural_allocation (avail_size, n_groups, orientation_sizes);
1729 else
1730 avail_size = 0;
1731
1732 /* Calculate/distribute expand for groups */
1733 if (n_expand_groups
16.1
'n_expand_groups' is <= 0
> 0)
17
Taking false branch
1734 {
1735 extra_size = avail_size / n_expand_groups;
1736 extra_extra = avail_size % n_expand_groups;
1737 }
1738 else
1739 extra_size = extra_extra = 0;
1740
1741 /* Now we need to naturally allocate sizes for cells in each group
1742 * and push the height-for-width for each group accordingly while
1743 * accumulating the overall height-for-width for this row.
1744 */
1745 for (i = 0; i < n_groups; i++)
18
Loop condition is true. Entering loop body
1746 {
1747 CellGroup *group;
1748 gint group_min, group_nat;
1749 gint group_idx = GPOINTER_TO_INT (orientation_sizes[i].data)((gint) (glong) (orientation_sizes[i].data));
1750
1751 group = &g_array_index (priv->groups, CellGroup, group_idx)(((CellGroup*) (void *) (priv->groups)->data) [(group_idx
)])
;
1752
1753 if (group->expand_cells > 0)
19
Assuming field 'expand_cells' is <= 0
20
Taking false branch
1754 {
1755 orientation_sizes[i].minimum_size += extra_size;
1756 if (extra_extra)
1757 {
1758 orientation_sizes[i].minimum_size++;
1759 extra_extra--;
1760 }
1761 }
1762
1763 /* Now we have the allocation for the group,
1764 * request its height-for-width
1765 */
1766 compute_group_size_for_opposing_orientation (box, group, widget,
21
Calling 'compute_group_size_for_opposing_orientation'
1767 orientation_sizes[i].minimum_size,
1768 &group_min, &group_nat);
1769
1770 min_size = MAX (min_size, group_min)(((min_size) > (group_min)) ? (min_size) : (group_min));
1771 nat_size = MAX (nat_size, group_nat)(((nat_size) > (group_nat)) ? (nat_size) : (group_nat));
1772
1773 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL)
1774 {
1775 _ctk_cell_area_box_context_push_group_height_for_width (context, group_idx, for_size,
1776 group_min, group_nat);
1777 }
1778 else
1779 {
1780 _ctk_cell_area_box_context_push_group_width_for_height (context, group_idx, for_size,
1781 group_min, group_nat);
1782 }
1783 }
1784
1785 *minimum_size = min_size;
1786 *natural_size = nat_size;
1787
1788 g_free (orientation_sizes);
1789
1790 /* Update rtl state for focus navigation to work */
1791 priv->rtl = (priv->orientation == CTK_ORIENTATION_HORIZONTAL &&
1792 ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL);
1793}
1794
1795
1796
1797static void
1798ctk_cell_area_box_get_preferred_width (CtkCellArea *area,
1799 CtkCellAreaContext *context,
1800 CtkWidget *widget,
1801 gint *minimum_width,
1802 gint *natural_width)
1803{
1804 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1805 CtkCellAreaBoxContext *box_context;
1806 gint min_width, nat_width;
1807
1808 g_return_if_fail (CTK_IS_CELL_AREA_BOX_CONTEXT (context))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context)); GType __t = ((_ctk_cell_area_box_context_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CELL_AREA_BOX_CONTEXT (context)"
); return; } } while (0)
;
1809
1810 box_context = CTK_CELL_AREA_BOX_CONTEXT (context)((((CtkCellAreaBoxContext*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), ((_ctk_cell_area_box_context_get_type
()))))))
;
1811
1812 /* Compute the size of all renderers for current row data,
1813 * bumping cell alignments in the context along the way
1814 */
1815 compute_size (box, CTK_ORIENTATION_HORIZONTAL,
1816 box_context, widget, -1, &min_width, &nat_width);
1817
1818 if (minimum_width)
1819 *minimum_width = min_width;
1820
1821 if (natural_width)
1822 *natural_width = nat_width;
1823}
1824
1825static void
1826ctk_cell_area_box_get_preferred_height (CtkCellArea *area,
1827 CtkCellAreaContext *context,
1828 CtkWidget *widget,
1829 gint *minimum_height,
1830 gint *natural_height)
1831{
1832 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1833 CtkCellAreaBoxContext *box_context;
1834 gint min_height, nat_height;
1835
1836 g_return_if_fail (CTK_IS_CELL_AREA_BOX_CONTEXT (context))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context)); GType __t = ((_ctk_cell_area_box_context_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CELL_AREA_BOX_CONTEXT (context)"
); return; } } while (0)
;
1837
1838 box_context = CTK_CELL_AREA_BOX_CONTEXT (context)((((CtkCellAreaBoxContext*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), ((_ctk_cell_area_box_context_get_type
()))))))
;
1839
1840 /* Compute the size of all renderers for current row data,
1841 * bumping cell alignments in the context along the way
1842 */
1843 compute_size (box, CTK_ORIENTATION_VERTICAL,
1844 box_context, widget, -1, &min_height, &nat_height);
1845
1846 if (minimum_height)
1847 *minimum_height = min_height;
1848
1849 if (natural_height)
1850 *natural_height = nat_height;
1851}
1852
1853static void
1854ctk_cell_area_box_get_preferred_height_for_width (CtkCellArea *area,
1855 CtkCellAreaContext *context,
1856 CtkWidget *widget,
1857 gint width,
1858 gint *minimum_height,
1859 gint *natural_height)
1860{
1861 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1862 CtkCellAreaBoxContext *box_context;
1863 CtkCellAreaBoxPrivate *priv;
1864 gint min_height, nat_height;
1865
1866 g_return_if_fail (CTK_IS_CELL_AREA_BOX_CONTEXT (context))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context)); GType __t = ((_ctk_cell_area_box_context_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CELL_AREA_BOX_CONTEXT (context)"
); return; } } while (0)
;
1867
1868 box_context = CTK_CELL_AREA_BOX_CONTEXT (context)((((CtkCellAreaBoxContext*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), ((_ctk_cell_area_box_context_get_type
()))))))
;
1869 priv = box->priv;
1870
1871 if (priv->orientation == CTK_ORIENTATION_VERTICAL)
1872 {
1873 /* Add up vertical requests of height for width and push
1874 * the overall cached sizes for alignments
1875 */
1876 compute_size (box, priv->orientation, box_context, widget, width, &min_height, &nat_height);
1877 }
1878 else
1879 {
1880 /* Juice: virtually allocate cells into the for_width using the
1881 * alignments and then return the overall height for that width,
1882 * and cache it
1883 */
1884 compute_size_for_opposing_orientation (box, box_context, widget, width, &min_height, &nat_height);
1885 }
1886
1887 if (minimum_height)
1888 *minimum_height = min_height;
1889
1890 if (natural_height)
1891 *natural_height = nat_height;
1892}
1893
1894static void
1895ctk_cell_area_box_get_preferred_width_for_height (CtkCellArea *area,
1896 CtkCellAreaContext *context,
1897 CtkWidget *widget,
1898 gint height,
1899 gint *minimum_width,
1900 gint *natural_width)
1901{
1902 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1903 CtkCellAreaBoxContext *box_context;
1904 CtkCellAreaBoxPrivate *priv;
1905 gint min_width, nat_width;
1906
1907 g_return_if_fail (CTK_IS_CELL_AREA_BOX_CONTEXT (context))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context)); GType __t = ((_ctk_cell_area_box_context_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CELL_AREA_BOX_CONTEXT (context)"
); return; } } while (0)
;
1
Assuming '__inst' is non-null
2
Taking false branch
3
Assuming field 'g_class' is null
4
Assuming the condition is true
5
Taking true branch
6
Loop condition is false. Exiting loop
1908
1909 box_context = CTK_CELL_AREA_BOX_CONTEXT (context)((((CtkCellAreaBoxContext*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((context)), ((_ctk_cell_area_box_context_get_type
()))))))
;
1910 priv = box->priv;
1911
1912 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL)
7
Assuming field 'orientation' is not equal to CTK_ORIENTATION_HORIZONTAL
8
Taking false branch
1913 {
1914 /* Add up horizontal requests of width for height and push
1915 * the overall cached sizes for alignments
1916 */
1917 compute_size (box, priv->orientation, box_context, widget, height, &min_width, &nat_width);
1918 }
1919 else
1920 {
1921 /* Juice: horizontally allocate cells into the for_height using the
1922 * alignments and then return the overall width for that height,
1923 * and cache it
1924 */
1925 compute_size_for_opposing_orientation (box, box_context, widget, height, &min_width, &nat_width);
9
Calling 'compute_size_for_opposing_orientation'
1926 }
1927
1928 if (minimum_width)
1929 *minimum_width = min_width;
1930
1931 if (natural_width)
1932 *natural_width = nat_width;
1933}
1934
1935enum {
1936 FOCUS_NONE,
1937 FOCUS_PREV,
1938 FOCUS_NEXT,
1939 FOCUS_LAST_CELL
1940};
1941
1942static gboolean
1943ctk_cell_area_box_focus (CtkCellArea *area,
1944 CtkDirectionType direction)
1945{
1946 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (area)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((area)), ((ctk_cell_area_box_get_type ()))))))
;
1947 CtkCellAreaBoxPrivate *priv = box->priv;
1948 gint cycle = FOCUS_NONE;
1949 gboolean cycled_focus = FALSE(0);
1950 CtkCellRenderer *focus_cell;
1951
1952 focus_cell = ctk_cell_area_get_focus_cell (area);
1953
1954 /* Special case, when there is no activatable cell, focus
1955 * is painted around the entire area... in this case we
1956 * let focus leave the area directly.
1957 */
1958 if (focus_cell && !ctk_cell_area_is_activatable (area))
1959 {
1960 ctk_cell_area_set_focus_cell (area, NULL((void*)0));
1961 return FALSE(0);
1962 }
1963
1964 switch (direction)
1965 {
1966 case CTK_DIR_TAB_FORWARD:
1967 cycle = priv->rtl ? FOCUS_PREV : FOCUS_NEXT;
1968 break;
1969 case CTK_DIR_TAB_BACKWARD:
1970 cycle = priv->rtl ? FOCUS_NEXT : FOCUS_PREV;
1971 break;
1972 case CTK_DIR_UP:
1973 if (priv->orientation == CTK_ORIENTATION_VERTICAL || !priv->last_focus_cell)
1974 cycle = FOCUS_PREV;
1975 else if (!focus_cell)
1976 cycle = FOCUS_LAST_CELL;
1977 break;
1978 case CTK_DIR_DOWN:
1979 if (priv->orientation == CTK_ORIENTATION_VERTICAL || !priv->last_focus_cell)
1980 cycle = FOCUS_NEXT;
1981 else if (!focus_cell)
1982 cycle = FOCUS_LAST_CELL;
1983 break;
1984 case CTK_DIR_LEFT:
1985 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL || !priv->last_focus_cell)
1986 cycle = priv->rtl ? FOCUS_NEXT : FOCUS_PREV;
1987 else if (!focus_cell)
1988 cycle = FOCUS_LAST_CELL;
1989 break;
1990 case CTK_DIR_RIGHT:
1991 if (priv->orientation == CTK_ORIENTATION_HORIZONTAL || !priv->last_focus_cell)
1992 cycle = priv->rtl ? FOCUS_PREV : FOCUS_NEXT;
1993 else if (!focus_cell)
1994 cycle = FOCUS_LAST_CELL;
1995 break;
1996 default:
1997 break;
1998 }
1999
2000 if (cycle == FOCUS_LAST_CELL)
2001 {
2002 ctk_cell_area_set_focus_cell (area, priv->last_focus_cell);
2003 cycled_focus = TRUE(!(0));
2004 }
2005 else if (cycle != FOCUS_NONE)
2006 {
2007 gboolean found_cell = FALSE(0);
2008 GList *list;
2009 gint i;
2010
2011 /* If there is no focused cell, focus on the first (or last) one */
2012 if (!focus_cell)
2013 found_cell = TRUE(!(0));
2014
2015 for (i = (cycle == FOCUS_NEXT) ? 0 : priv->groups->len -1;
2016 cycled_focus == FALSE(0) && i >= 0 && i < priv->groups->len;
2017 i = (cycle == FOCUS_NEXT) ? i + 1 : i - 1)
2018 {
2019 CellGroup *group = &g_array_index (priv->groups, CellGroup, i)(((CellGroup*) (void *) (priv->groups)->data) [(i)]);
2020
2021 for (list = (cycle == FOCUS_NEXT) ? g_list_first (group->cells) : g_list_last (group->cells);
2022 cycled_focus == FALSE(0) && list; list = (cycle == FOCUS_NEXT) ? list->next : list->prev)
2023 {
2024 CellInfo *info = list->data;
2025
2026 if (info->renderer == focus_cell)
2027 found_cell = TRUE(!(0));
2028 else if (found_cell && /* Dont give focus to cells that are siblings to a focus cell */
2029 ctk_cell_area_get_focus_from_sibling (area, info->renderer) == NULL((void*)0))
2030 {
2031 ctk_cell_area_set_focus_cell (area, info->renderer);
2032 cycled_focus = TRUE(!(0));
2033 }
2034 }
2035 }
2036 }
2037
2038 if (!cycled_focus)
2039 ctk_cell_area_set_focus_cell (area, NULL((void*)0));
2040
2041 return cycled_focus;
2042}
2043
2044
2045/*************************************************************
2046 * CtkCellLayoutIface *
2047 *************************************************************/
2048static void
2049ctk_cell_area_box_cell_layout_init (CtkCellLayoutIface *iface)
2050{
2051 iface->pack_start = ctk_cell_area_box_layout_pack_start;
2052 iface->pack_end = ctk_cell_area_box_layout_pack_end;
2053 iface->reorder = ctk_cell_area_box_layout_reorder;
2054}
2055
2056static void
2057ctk_cell_area_box_layout_pack_start (CtkCellLayout *cell_layout,
2058 CtkCellRenderer *renderer,
2059 gboolean expand)
2060{
2061 ctk_cell_area_box_pack_start (CTK_CELL_AREA_BOX (cell_layout)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cell_layout)), ((ctk_cell_area_box_get_type ()))))))
, renderer, expand, FALSE(0), TRUE(!(0)));
2062}
2063
2064static void
2065ctk_cell_area_box_layout_pack_end (CtkCellLayout *cell_layout,
2066 CtkCellRenderer *renderer,
2067 gboolean expand)
2068{
2069 ctk_cell_area_box_pack_end (CTK_CELL_AREA_BOX (cell_layout)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cell_layout)), ((ctk_cell_area_box_get_type ()))))))
, renderer, expand, FALSE(0), TRUE(!(0)));
2070}
2071
2072static void
2073ctk_cell_area_box_layout_reorder (CtkCellLayout *cell_layout,
2074 CtkCellRenderer *renderer,
2075 gint position)
2076{
2077 CtkCellAreaBox *box = CTK_CELL_AREA_BOX (cell_layout)((((CtkCellAreaBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((cell_layout)), ((ctk_cell_area_box_get_type ()))))))
;
2078 CtkCellAreaBoxPrivate *priv = box->priv;
2079 GList *node;
2080
2081 node = g_list_find_custom (priv->cells, renderer,
2082 (GCompareFunc)cell_info_find);
2083
2084 if (node)
2085 {
2086 CellInfo *info;
2087
2088 info = node->data;
2089
2090 priv->cells = g_list_delete_link (priv->cells, node);
2091 priv->cells = g_list_insert (priv->cells, info, position);
2092
2093 cell_groups_rebuild (box);
2094 }
2095}
2096
2097/*************************************************************
2098 * Private interaction with CtkCellAreaBoxContext *
2099 *************************************************************/
2100gboolean
2101_ctk_cell_area_box_group_visible (CtkCellAreaBox *box,
2102 gint group_idx)
2103{
2104 CtkCellAreaBoxPrivate *priv = box->priv;
2105 CellGroup *group;
2106
2107 g_assert (group_idx >= 0 && group_idx < priv->groups->len)do { if (group_idx >= 0 && group_idx < priv->
groups->len) ; else g_assertion_message_expr ("Ctk", "ctkcellareabox.c"
, 2107, ((const char*) (__func__)), "group_idx >= 0 && group_idx < priv->groups->len"
); } while (0)
;
2108
2109 group = &g_array_index (priv->groups, CellGroup, group_idx)(((CellGroup*) (void *) (priv->groups)->data) [(group_idx
)])
;
2110
2111 return group->visible;
2112}
2113
2114
2115/*************************************************************
2116 * API *
2117 *************************************************************/
2118/**
2119 * ctk_cell_area_box_new:
2120 *
2121 * Creates a new #CtkCellAreaBox.
2122 *
2123 * Returns: a newly created #CtkCellAreaBox
2124 *
2125 * Since: 3.0
2126 */
2127CtkCellArea *
2128ctk_cell_area_box_new (void)
2129{
2130 return (CtkCellArea *)g_object_new (CTK_TYPE_CELL_AREA_BOX(ctk_cell_area_box_get_type ()), NULL((void*)0));
2131}
2132
2133/**
2134 * ctk_cell_area_box_pack_start:
2135 * @box: a #CtkCellAreaBox
2136 * @renderer: the #CtkCellRenderer to add
2137 * @expand: whether @renderer should receive extra space when the area receives
2138 * more than its natural size
2139 * @align: whether @renderer should be aligned in adjacent rows
2140 * @fixed: whether @renderer should have the same size in all rows
2141 *
2142 * Adds @renderer to @box, packed with reference to the start of @box.
2143 *
2144 * The @renderer is packed after any other #CtkCellRenderer packed
2145 * with reference to the start of @box.
2146 *
2147 * Since: 3.0
2148 */
2149void
2150ctk_cell_area_box_pack_start (CtkCellAreaBox *box,
2151 CtkCellRenderer *renderer,
2152 gboolean expand,
2153 gboolean align,
2154 gboolean fixed)
2155{
2156 CtkCellAreaBoxPrivate *priv;
2157 CellInfo *info;
2158
2159 g_return_if_fail (CTK_IS_CELL_AREA_BOX (box))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((box)); GType __t = ((ctk_cell_area_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_CELL_AREA_BOX (box)"); return; } } while (0)
;
2160 g_return_if_fail (CTK_IS_CELL_RENDERER (renderer))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((renderer)); GType __t = ((ctk_cell_renderer_get_type ())
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CELL_RENDERER (renderer)"); return
; } } while (0)
;
2161
2162 priv = box->priv;
2163
2164 if (g_list_find_custom (priv->cells, renderer,
2165 (GCompareFunc)cell_info_find))
2166 {
2167 g_warning ("Refusing to add the same cell renderer to a CtkCellAreaBox twice");
2168 return;
2169 }
2170
2171 info = cell_info_new (renderer, CTK_PACK_START, expand, align, fixed);
2172
2173 priv->cells = g_list_append (priv->cells, info);
2174
2175 cell_groups_rebuild (box);
2176}
2177
2178/**
2179 * ctk_cell_area_box_pack_end:
2180 * @box: a #CtkCellAreaBox
2181 * @renderer: the #CtkCellRenderer to add
2182 * @expand: whether @renderer should receive extra space when the area receives
2183 * more than its natural size
2184 * @align: whether @renderer should be aligned in adjacent rows
2185 * @fixed: whether @renderer should have the same size in all rows
2186 *
2187 * Adds @renderer to @box, packed with reference to the end of @box.
2188 *
2189 * The @renderer is packed after (away from end of) any other
2190 * #CtkCellRenderer packed with reference to the end of @box.
2191 *
2192 * Since: 3.0
2193 */
2194void
2195ctk_cell_area_box_pack_end (CtkCellAreaBox *box,
2196 CtkCellRenderer *renderer,
2197 gboolean expand,
2198 gboolean align,
2199 gboolean fixed)
2200{
2201 CtkCellAreaBoxPrivate *priv;
2202 CellInfo *info;
2203
2204 g_return_if_fail (CTK_IS_CELL_AREA_BOX (box))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((box)); GType __t = ((ctk_cell_area_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_CELL_AREA_BOX (box)"); return; } } while (0)
;
2205 g_return_if_fail (CTK_IS_CELL_RENDERER (renderer))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((renderer)); GType __t = ((ctk_cell_renderer_get_type ())
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_CELL_RENDERER (renderer)"); return
; } } while (0)
;
2206
2207 priv = box->priv;
2208
2209 if (g_list_find_custom (priv->cells, renderer,
2210 (GCompareFunc)cell_info_find))
2211 {
2212 g_warning ("Refusing to add the same cell renderer to a CtkCellArea twice");
2213 return;
2214 }
2215
2216 info = cell_info_new (renderer, CTK_PACK_END, expand, align, fixed);
2217
2218 priv->cells = g_list_append (priv->cells, info);
2219
2220 cell_groups_rebuild (box);
2221}
2222
2223/**
2224 * ctk_cell_area_box_get_spacing:
2225 * @box: a #CtkCellAreaBox
2226 *
2227 * Gets the spacing added between cell renderers.
2228 *
2229 * Returns: the space added between cell renderers in @box.
2230 *
2231 * Since: 3.0
2232 */
2233gint
2234ctk_cell_area_box_get_spacing (CtkCellAreaBox *box)
2235{
2236 g_return_val_if_fail (CTK_IS_CELL_AREA_BOX (box), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((box)); GType __t = ((ctk_cell_area_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_CELL_AREA_BOX (box)"); return (0); } } while (0)
;
2237
2238 return box->priv->spacing;
2239}
2240
2241/**
2242 * ctk_cell_area_box_set_spacing:
2243 * @box: a #CtkCellAreaBox
2244 * @spacing: the space to add between #CtkCellRenderers
2245 *
2246 * Sets the spacing to add between cell renderers in @box.
2247 *
2248 * Since: 3.0
2249 */
2250void
2251ctk_cell_area_box_set_spacing (CtkCellAreaBox *box,
2252 gint spacing)
2253{
2254 CtkCellAreaBoxPrivate *priv;
2255
2256 g_return_if_fail (CTK_IS_CELL_AREA_BOX (box))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((box)); GType __t = ((ctk_cell_area_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_CELL_AREA_BOX (box)"); return; } } while (0)
;
2257
2258 priv = box->priv;
2259
2260 if (priv->spacing != spacing)
2261 {
2262 priv->spacing = spacing;
2263
2264 g_object_notify (G_OBJECT (box)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((box)), (((GType) ((20) << (2))))))))
, "spacing");
2265
2266 /* Notify that size needs to be requested again */
2267 reset_contexts (box);
2268 }
2269}