aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/canvas/evas_object_grid.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/canvas/evas_object_grid.c')
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_grid.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/canvas/evas_object_grid.c b/libraries/evas/src/lib/canvas/evas_object_grid.c
new file mode 100644
index 0000000..ac96f04
--- /dev/null
+++ b/libraries/evas/src/lib/canvas/evas_object_grid.c
@@ -0,0 +1,465 @@
1#include <errno.h>
2#include "evas_common.h"
3
4typedef struct _Evas_Object_Grid_Data Evas_Object_Grid_Data;
5typedef struct _Evas_Object_Grid_Option Evas_Object_Grid_Option;
6typedef struct _Evas_Object_Grid_Iterator Evas_Object_Grid_Iterator;
7typedef struct _Evas_Object_Grid_Accessor Evas_Object_Grid_Accessor;
8
9struct _Evas_Object_Grid_Option
10{
11 Evas_Object *obj;
12 Eina_List *l;
13 int x, y, w, h;
14};
15
16struct _Evas_Object_Grid_Data
17{
18 Evas_Object_Smart_Clipped_Data base;
19 Eina_List *children;
20 struct {
21 int w, h;
22 } size;
23 Eina_Bool is_mirrored : 1;
24};
25
26struct _Evas_Object_Grid_Iterator
27{
28 Eina_Iterator iterator;
29
30 Eina_Iterator *real_iterator;
31 const Evas_Object *grid;
32};
33
34struct _Evas_Object_Grid_Accessor
35{
36 Eina_Accessor accessor;
37
38 Eina_Accessor *real_accessor;
39 const Evas_Object *grid;
40};
41
42#define EVAS_OBJECT_GRID_DATA_GET(o, ptr) \
43 Evas_Object_Grid_Data *ptr = evas_object_smart_data_get(o)
44
45#define EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, ptr) \
46 EVAS_OBJECT_GRID_DATA_GET(o, ptr); \
47 if (!ptr) \
48 { \
49 CRIT("no widget data for object %p (%s)", \
50 o, evas_object_type_get(o)); \
51 abort(); \
52 return; \
53 }
54
55#define EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
56 EVAS_OBJECT_GRID_DATA_GET(o, ptr); \
57 if (!ptr) \
58 { \
59 CRIT("No widget data for object %p (%s)", \
60 o, evas_object_type_get(o)); \
61 abort(); \
62 return val; \
63 }
64
65static const char EVAS_OBJECT_GRID_OPTION_KEY[] = "|EvGd";
66
67static Eina_Bool
68_evas_object_grid_iterator_next(Evas_Object_Grid_Iterator *it, void **data)
69{
70 Evas_Object_Grid_Option *opt;
71
72 if (!eina_iterator_next(it->real_iterator, (void **)&opt))
73 return EINA_FALSE;
74 if (data) *data = opt->obj;
75 return EINA_TRUE;
76}
77
78static Evas_Object *
79_evas_object_grid_iterator_get_container(Evas_Object_Grid_Iterator *it)
80{
81 return (Evas_Object *)it->grid;
82}
83
84static void
85_evas_object_grid_iterator_free(Evas_Object_Grid_Iterator *it)
86{
87 eina_iterator_free(it->real_iterator);
88 free(it);
89}
90
91static Eina_Bool
92_evas_object_grid_accessor_get_at(Evas_Object_Grid_Accessor *it, unsigned int idx, void **data)
93{
94 Evas_Object_Grid_Option *opt = NULL;
95
96 if (!eina_accessor_data_get(it->real_accessor, idx, (void **)&opt))
97 return EINA_FALSE;
98 if (data) *data = opt->obj;
99 return EINA_TRUE;
100}
101
102static Evas_Object *
103_evas_object_grid_accessor_get_container(Evas_Object_Grid_Accessor *it)
104{
105 return (Evas_Object *)it->grid;
106}
107
108static void
109_evas_object_grid_accessor_free(Evas_Object_Grid_Accessor *it)
110{
111 eina_accessor_free(it->real_accessor);
112 free(it);
113}
114
115static Evas_Object_Grid_Option *
116_evas_object_grid_option_get(Evas_Object *o)
117{
118 return evas_object_data_get(o, EVAS_OBJECT_GRID_OPTION_KEY);
119}
120
121static void
122_evas_object_grid_option_set(Evas_Object *o, const Evas_Object_Grid_Option *opt)
123{
124 evas_object_data_set(o, EVAS_OBJECT_GRID_OPTION_KEY, opt);
125}
126
127static Evas_Object_Grid_Option *
128_evas_object_grid_option_del(Evas_Object *o)
129{
130 return evas_object_data_del(o, EVAS_OBJECT_GRID_OPTION_KEY);
131}
132
133static void
134_on_child_del(void *data, Evas *evas __UNUSED__, Evas_Object *child, void *einfo __UNUSED__)
135{
136 Evas_Object *grid = data;
137 evas_object_grid_unpack(grid, child);
138}
139
140static void
141_evas_object_grid_child_connect(Evas_Object *o, Evas_Object *child)
142{
143 evas_object_event_callback_add
144 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
145}
146
147static void
148_evas_object_grid_child_disconnect(Evas_Object *o, Evas_Object *child)
149{
150 evas_object_event_callback_del_full
151 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
152}
153
154EVAS_SMART_SUBCLASS_NEW("Evas_Object_Grid", _evas_object_grid,
155 Evas_Smart_Class, Evas_Smart_Class,
156 evas_object_smart_clipped_class_get, NULL)
157
158static void
159_evas_object_grid_smart_add(Evas_Object *o)
160{
161 EVAS_SMART_DATA_ALLOC(o, Evas_Object_Grid_Data)
162
163 priv->size.w = 100;
164 priv->size.h = 100;
165
166 _evas_object_grid_parent_sc->add(o);
167}
168
169static void
170_evas_object_grid_smart_del(Evas_Object *o)
171{
172 EVAS_OBJECT_GRID_DATA_GET(o, priv);
173 Eina_List *l;
174
175 l = priv->children;
176 while (l)
177 {
178 Evas_Object_Grid_Option *opt = l->data;
179 _evas_object_grid_child_disconnect(o, opt->obj);
180 _evas_object_grid_option_del(opt->obj);
181 free(opt);
182 l = eina_list_remove_list(l, l);
183 }
184 _evas_object_grid_parent_sc->del(o);
185}
186
187static void
188_evas_object_grid_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
189{
190 Evas_Coord ow, oh;
191 evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
192 if ((ow == w) && (oh == h)) return;
193 evas_object_smart_changed(o);
194}
195
196static void
197_evas_object_grid_smart_calculate(Evas_Object *o)
198{
199 Eina_List *l;
200 Evas_Object_Grid_Option *opt;
201 Evas_Coord x, y, w, h, vw, vh, t;
202 Eina_Bool mirror;
203
204 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
205 if (!priv) return;
206 if (!priv->children) return;
207 evas_object_geometry_get(o, &x, &y, &w, &h);
208 mirror = priv->is_mirrored;
209 vw = priv->size.w;
210 vh = priv->size.h;
211 EINA_LIST_FOREACH(priv->children, l, opt)
212 {
213 Evas_Coord x1, y1, x2, y2;
214
215 x1 = x + ((w * opt->x) / vw);
216 y1 = y + ((h * opt->y) / vh);
217 x2 = x + ((w * (opt->x + opt->w)) / vw);
218 y2 = y + ((h * (opt->y + opt->h)) / vh);
219 if (mirror)
220 {
221 t = x1; x1 = x2; x2 = t;
222 t = y1; y1 = y2; y2 = t;
223 }
224 evas_object_move(opt->obj, x1, y1);
225 evas_object_resize(opt->obj, x2 - x1, y2 - y1);
226 }
227}
228
229static void
230_evas_object_grid_smart_set_user(Evas_Smart_Class *sc)
231{
232 sc->add = _evas_object_grid_smart_add;
233 sc->del = _evas_object_grid_smart_del;
234 sc->resize = _evas_object_grid_smart_resize;
235 sc->calculate = _evas_object_grid_smart_calculate;
236}
237
238EAPI Evas_Object *
239evas_object_grid_add(Evas *evas)
240{
241 return evas_object_smart_add(evas, _evas_object_grid_smart_class_new());
242}
243
244EAPI Evas_Object *
245evas_object_grid_add_to(Evas_Object *parent)
246{
247 Evas *evas;
248 Evas_Object *o;
249
250 evas = evas_object_evas_get(parent);
251 o = evas_object_grid_add(evas);
252 evas_object_smart_member_add(o, parent);
253 return o;
254}
255
256EAPI void
257evas_object_grid_size_set(Evas_Object *o, int w, int h)
258{
259 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
260 if ((priv->size.w == w) && (priv->size.h == h)) return;
261 priv->size.w = w;
262 priv->size.h = h;
263 evas_object_smart_changed(o);
264}
265
266EAPI void
267evas_object_grid_size_get(const Evas_Object *o, int *w, int *h)
268{
269 if (w) *w = 0;
270 if (h) *h = 0;
271 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
272 if (w) *w = priv->size.w;
273 if (h) *h = priv->size.h;
274}
275
276EAPI Eina_Bool
277evas_object_grid_pack(Evas_Object *o, Evas_Object *child, int x, int y, int w, int h)
278{
279 Evas_Object_Grid_Option *opt;
280 Eina_Bool newobj = EINA_FALSE;
281
282 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, 0);
283
284 opt = _evas_object_grid_option_get(child);
285 if (!opt)
286 {
287 opt = malloc(sizeof(*opt));
288 if (!opt)
289 {
290 ERR("could not allocate grid option data.");
291 return EINA_FALSE;
292 }
293 newobj = EINA_TRUE;
294 }
295
296 opt->x = x;
297 opt->y = y;
298 opt->w = w;
299 opt->h = h;
300
301 if (newobj)
302 {
303 opt->obj = child;
304 priv->children = eina_list_append(priv->children, opt);
305 opt->l = eina_list_last(priv->children);
306 _evas_object_grid_option_set(child, opt);
307 evas_object_smart_member_add(child, o);
308 _evas_object_grid_child_connect(o, child);
309 }
310 // FIXME: we could keep a changed list
311 evas_object_smart_changed(o);
312 return EINA_TRUE;
313}
314
315static void
316_evas_object_grid_remove_opt(Evas_Object_Grid_Data *priv, Evas_Object_Grid_Option *opt)
317{
318 priv->children = eina_list_remove_list(priv->children, opt->l);
319 opt->l = NULL;
320}
321
322EAPI Eina_Bool
323evas_object_grid_unpack(Evas_Object *o, Evas_Object *child)
324{
325 Evas_Object_Grid_Option *opt;
326
327 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, 0);
328
329 if (o != evas_object_smart_parent_get(child))
330 {
331 ERR("cannot unpack child from incorrect grid!");
332 return EINA_FALSE;
333 }
334
335 opt = _evas_object_grid_option_del(child);
336 if (!opt)
337 {
338 ERR("cannot unpack child with no packing option!");
339 return EINA_FALSE;
340 }
341
342 _evas_object_grid_child_disconnect(o, child);
343 _evas_object_grid_remove_opt(priv, opt);
344 evas_object_smart_member_del(child);
345 free(opt);
346 return EINA_TRUE;
347}
348
349EAPI void
350evas_object_grid_clear(Evas_Object *o, Eina_Bool clear)
351{
352 Evas_Object_Grid_Option *opt;
353
354 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
355
356 EINA_LIST_FREE(priv->children, opt)
357 {
358 _evas_object_grid_child_disconnect(o, opt->obj);
359 _evas_object_grid_option_del(opt->obj);
360 evas_object_smart_member_del(opt->obj);
361 if (clear)
362 evas_object_del(opt->obj);
363 free(opt);
364 }
365}
366
367EAPI Eina_Bool
368evas_object_grid_pack_get(Evas_Object *o, Evas_Object *child, int *x, int *y, int *w, int *h)
369{
370 Evas_Object_Grid_Option *opt;
371
372 if (x) *x = 0;
373 if (y) *y = 0;
374 if (w) *w = 0;
375 if (h) *h = 0;
376 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, 0);
377 opt = _evas_object_grid_option_get(child);
378 if (!opt) return 0;
379 if (x) *x = opt->x;
380 if (y) *y = opt->y;
381 if (w) *w = opt->w;
382 if (h) *h = opt->h;
383 return 1;
384}
385
386EAPI Eina_Iterator *
387evas_object_grid_iterator_new(const Evas_Object *o)
388{
389 Evas_Object_Grid_Iterator *it;
390
391 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
392
393 if (!priv->children) return NULL;
394
395 it = calloc(1, sizeof(Evas_Object_Grid_Iterator));
396 if (!it) return NULL;
397
398 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
399
400 it->real_iterator = eina_list_iterator_new(priv->children);
401 it->grid = o;
402
403 it->iterator.next = FUNC_ITERATOR_NEXT(_evas_object_grid_iterator_next);
404 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_evas_object_grid_iterator_get_container);
405 it->iterator.free = FUNC_ITERATOR_FREE(_evas_object_grid_iterator_free);
406
407 return &it->iterator;
408}
409
410EAPI Eina_Accessor *
411evas_object_grid_accessor_new(const Evas_Object *o)
412{
413 Evas_Object_Grid_Accessor *it;
414
415 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
416
417 if (!priv->children) return NULL;
418
419 it = calloc(1, sizeof(Evas_Object_Grid_Accessor));
420 if (!it) return NULL;
421
422 EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
423
424 it->real_accessor = eina_list_accessor_new(priv->children);
425 it->grid = o;
426
427 it->accessor.get_at = FUNC_ACCESSOR_GET_AT(_evas_object_grid_accessor_get_at);
428 it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(_evas_object_grid_accessor_get_container);
429 it->accessor.free = FUNC_ACCESSOR_FREE(_evas_object_grid_accessor_free);
430
431 return &it->accessor;
432}
433
434EAPI Eina_List *
435evas_object_grid_children_get(const Evas_Object *o)
436{
437 Eina_List *new_list = NULL, *l;
438 Evas_Object_Grid_Option *opt;
439
440 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
441
442 EINA_LIST_FOREACH(priv->children, l, opt)
443 new_list = eina_list_append(new_list, opt->obj);
444
445 return new_list;
446}
447
448EAPI Eina_Bool
449evas_object_grid_mirrored_get(const Evas_Object *obj)
450{
451 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(obj, priv, EINA_FALSE);
452 return priv->is_mirrored;
453}
454
455EAPI void
456evas_object_grid_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
457{
458 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(obj, priv);
459 mirrored = !!mirrored;
460 if (priv->is_mirrored != mirrored)
461 {
462 priv->is_mirrored = mirrored;
463 _evas_object_grid_smart_calculate(obj);
464 }
465}