1 /* Fo
2 * fo-area-normal.c: Normal block-area object
3 *
4 * Copyright (C) 2001 Sun Microsystems
5 * Copyright (C) 2007-2009 Menteith Consulting Ltd
6 *
7 * See COPYING for the status of this software.
8 */
9
10 #include "fo-utils.h"
11 #include "fo-area.h"
12 #include "fo-area-area.h"
13 #include "fo-area-area-private.h"
14 #include "fo-area-normal.h"
15
16 struct _FoAreaNormal
17 {
18 FoAreaArea parent_instance;
19 };
20
21 struct _FoAreaNormalClass
22 {
23 FoAreaAreaClass parent_class;
24 };
25
26 static void fo_area_normal_class_init (FoAreaNormalClass *klass);
27 static void fo_area_normal_finalize (GObject *object);
28
29 static void fo_area_normal_debug_dump_properties (FoArea *area,
30 gint depth);
31 static FoArea* fo_area_normal_size_request (FoArea *child);
32
33 static gpointer parent_class;
34
35 GType
fo_area_normal_get_type(void)36 fo_area_normal_get_type (void)
37 {
38 static GType object_type = 0;
39
40 if (!object_type)
41 {
42 static const GTypeInfo object_info =
43 {
44 sizeof (FoAreaNormalClass),
45 (GBaseInitFunc) NULL,
46 (GBaseFinalizeFunc) NULL,
47 (GClassInitFunc) fo_area_normal_class_init,
48 NULL, /* class_finalize */
49 NULL, /* class_data */
50 sizeof (FoAreaNormal),
51 0, /* n_preallocs */
52 NULL, /* instance_init */
53 NULL /* value_table */
54 };
55
56 object_type = g_type_register_static (FO_TYPE_AREA_AREA,
57 "FoAreaNormal",
58 &object_info, 0);
59 }
60
61 return object_type;
62 }
63
64 static void
fo_area_normal_class_init(FoAreaNormalClass * klass)65 fo_area_normal_class_init (FoAreaNormalClass *klass)
66 {
67 GObjectClass *object_class = G_OBJECT_CLASS (klass);
68
69 parent_class = g_type_class_peek_parent (klass);
70
71 object_class->finalize = fo_area_normal_finalize;
72
73 FO_AREA_CLASS (klass)->debug_dump_properties = fo_area_normal_debug_dump_properties;
74 FO_AREA_CLASS (klass)->size_request = fo_area_normal_size_request;
75 }
76
77 static void
fo_area_normal_finalize(GObject * object)78 fo_area_normal_finalize (GObject *object)
79 {
80 FoAreaNormal *fo_area_normal;
81
82 fo_area_normal = FO_AREA_NORMAL (object);
83
84 G_OBJECT_CLASS (parent_class)->finalize (object);
85 }
86
87
88 /**
89 * fo_area_normal_new:
90 *
91 * Creates a new #FoAreaNormal initialized to default value.
92 *
93 * Return value: the new #FoAreaNormal
94 **/
95 FoArea*
fo_area_normal_new(void)96 fo_area_normal_new (void)
97 {
98 return FO_AREA (g_object_new (fo_area_normal_get_type (), NULL));
99 }
100
101
102 void
fo_area_normal_debug_dump_properties(FoArea * area,gint depth)103 fo_area_normal_debug_dump_properties (FoArea *area, gint depth)
104 {
105 FoAreaNormal *normal;
106 gchar *indent = g_strnfill (depth * 2, ' ');
107
108 g_return_if_fail (area != NULL);
109 g_return_if_fail (FO_IS_AREA_NORMAL (area));
110
111 normal = FO_AREA_NORMAL (area);
112
113 g_free (indent);
114 FO_AREA_CLASS (parent_class)->debug_dump_properties (area, depth + 1);
115 }
116
117 FoArea*
fo_area_normal_add_child(FoArea * parent,FoArea * child)118 fo_area_normal_add_child (FoArea *parent, FoArea *child)
119 {
120 g_return_val_if_fail (parent != NULL, NULL);
121 g_return_val_if_fail (FO_IS_AREA_NORMAL (parent), NULL);
122 g_return_val_if_fail (child != NULL, NULL);
123
124 return fo_area_real_add_child (parent, child);
125 }
126
127 /**
128 * fo_area_normal_size_request:
129 * @child: Child area
130 *
131 * Check that the parent area of @child has sufficient space for
132 * @child. If not enough space, request that the parent has
133 * sufficient space allocated for it, then adjust @child and its
134 * siblings as necessary to fit into the resized parent area.
135 *
136 * Return value: Pointer to the last area generated from @child after
137 * any reallocation and resizing
138 **/
139 FoArea*
fo_area_normal_size_request(FoArea * child)140 fo_area_normal_size_request (FoArea *child)
141 {
142 FoArea *use_child_area;
143 FoArea *parent;
144 gdouble total_child_height = 0;
145 gdouble normal_child_available_bpdim;
146 gdouble child_height;
147 gdouble child_space_before, child_space_after;
148
149 g_return_val_if_fail (child != NULL, NULL);
150 g_return_val_if_fail (FO_IS_AREA_AREA (child), NULL);
151 g_return_val_if_fail (!FO_AREA_IS_ROOT (child), NULL);
152 g_return_val_if_fail (FO_IS_AREA_AREA (fo_area_parent (child)), NULL);
153
154 child_height = fo_area_area_get_height (child);
155 child_space_before = fo_area_area_get_space_before (child);
156 child_space_after = fo_area_area_get_space_after (child);
157
158 parent = fo_area_parent (child);
159 normal_child_available_bpdim = fo_area_get_child_available_bpdim (parent);
160
161 #if defined(LIBFO_DEBUG) && 0
162 g_message ("normal_size_request (%p):: parent: %s; generated by: %s; available_height: %f",
163 child,
164 fo_object_debug_sprintf (parent),
165 fo_object_debug_sprintf (parent->generated_by),
166 normal_child_available_bpdim);
167 g_message ("normal_size_request (%p):: child: %s; generated by: %s; height: %f; space_before: %f; space_after: %f",
168 child,
169 fo_object_debug_sprintf (child),
170 fo_object_debug_sprintf (child->generated_by),
171 child_height,
172 child_space_before,
173 child_space_after);
174 #endif
175
176 fo_area_children_foreach (parent,
177 G_TRAVERSE_ALL,
178 &fo_area_accumulate_height,
179 &total_child_height);
180 #if defined(LIBFO_DEBUG) && 0
181 g_message ("normal_size_request (%p):: child total: %f",
182 child,
183 total_child_height);
184 #endif
185
186 fo_area_area_set_height (parent,
187 total_child_height +
188 fo_area_area_get_border_before (parent) +
189 fo_area_area_get_padding_before (parent) +
190 fo_area_area_get_padding_after (parent) +
191 fo_area_area_get_border_after (parent));
192
193 /* Don't bother doing a size_request if still fit within
194 available height */
195 if (normal_child_available_bpdim < fo_area_area_get_height (parent))
196 {
197 parent = fo_area_size_request (parent);
198 normal_child_available_bpdim =
199 MAX (fo_area_get_available_height (parent) -
200 fo_area_area_get_border_before (parent) -
201 fo_area_area_get_padding_before (parent) -
202 fo_area_area_get_padding_after (parent) -
203 fo_area_area_get_border_after (parent),
204 0);
205 fo_area_set_child_available_bpdim (parent,
206 normal_child_available_bpdim);
207 #if defined(LIBFO_DEBUG) && 0
208 g_message ("normal_size_request (%p):: new parent: %s; generated by: %s; available_height: %f",
209 child,
210 fo_object_debug_sprintf (parent),
211 fo_object_debug_sprintf (parent->generated_by),
212 normal_child_available_bpdim);
213 #endif
214 }
215
216 total_child_height = 0;
217 fo_area_children_foreach (parent,
218 G_TRAVERSE_ALL,
219 &fo_area_accumulate_height,
220 &total_child_height);
221
222 #if defined(LIBFO_DEBUG) && 0
223 g_message ("normal_size_request (%p):: new child total: %f",
224 child,
225 total_child_height);
226 #endif
227
228 fo_area_set_next_x (parent,
229 fo_area_area_get_border_start (parent) +
230 fo_area_area_get_padding_start (parent));
231 fo_area_set_next_y (parent,
232 - (fo_area_area_get_border_before (parent) +
233 fo_area_area_get_padding_before (parent)));
234
235 if (total_child_height <= normal_child_available_bpdim)
236 {
237 use_child_area = fo_area_first_child (parent);
238
239 while (use_child_area)
240 {
241 fo_area_area_set_x (use_child_area,
242 fo_area_get_next_x (parent) +
243 fo_area_area_get_start_indent (use_child_area) -
244 fo_area_area_get_x (parent));
245 fo_area_area_set_y (use_child_area,
246 fo_area_get_next_y (parent));
247 fo_area_set_next_x (parent, 0);
248 fo_area_set_next_y (parent,
249 fo_area_get_next_y (parent) -
250 fo_area_area_get_height (use_child_area));
251 fo_area_set_available_height (child,
252 fo_area_area_get_height (use_child_area));
253 fo_area_set_available_width (child,
254 fo_area_get_child_available_ipdim (parent));
255
256 use_child_area = fo_area_next_sibling (use_child_area);
257 }
258
259 #if defined(LIBFO_DEBUG) && 0
260 g_message ("normal_size_request (%p):: return:: parent->last: %s; generated by: %s",
261 child,
262 fo_object_debug_sprintf (fo_area_last_child (parent)),
263 fo_object_debug_sprintf (fo_area_last_child (parent->generated_by)));
264 #endif
265 return fo_area_last_child (parent);
266 }
267 else
268 {
269 use_child_area = fo_area_first_child (parent);
270
271 while (use_child_area)
272 {
273 if (normal_child_available_bpdim >=
274 fo_area_area_get_height (use_child_area))
275 {
276 fo_area_area_set_x (use_child_area,
277 fo_area_get_next_x (parent) +
278 fo_area_area_get_start_indent (use_child_area));
279 fo_area_area_set_y (use_child_area,
280 fo_area_get_next_y (parent));
281 fo_area_set_next_x (parent, 0);
282 fo_area_set_next_y (parent,
283 fo_area_get_next_y (parent) -
284 fo_area_area_get_height (use_child_area));
285 fo_area_set_available_height (child,
286 fo_area_area_get_height (use_child_area));
287 fo_area_set_available_width (child,
288 fo_area_get_child_available_ipdim (parent));
289
290 use_child_area = fo_area_next_sibling (use_child_area);
291 }
292 else
293 {
294 #if defined(LIBFO_DEBUG) && 1
295 g_message ("normal_size_request:: splitting:: child: %s; generated by: %s",
296 fo_object_debug_sprintf (use_child_area),
297 fo_object_debug_sprintf (use_child_area->generated_by));
298 #endif
299 use_child_area = fo_area_split_before_height (use_child_area,
300 normal_child_available_bpdim -
301 fo_area_area_get_height (parent));
302 parent = fo_area_parent (use_child_area);
303 normal_child_available_bpdim = fo_area_get_child_available_bpdim (parent);
304 }
305 }
306
307 #if defined(LIBFO_DEBUG) && 0
308 g_message ("normal_size_request (%p):: total > available:: return:: parent->last: %s; generated by: %s",
309 child,
310 fo_object_debug_sprintf (fo_area_last_child (parent)),
311 fo_object_debug_sprintf (fo_area_last_child (parent->generated_by)));
312 #endif
313 return fo_area_last_child (parent);
314 }
315 }
316
317