1 #define EFL_CANVAS_GROUP_PROTECTED
2
3 #include "evas_common_private.h"
4 #include "evas_private.h"
5 #include <errno.h>
6
7 #define MY_CLASS EVAS_TABLE_CLASS
8
9 #define MY_CLASS_NAME "Evas_Table"
10 #define MY_CLASS_NAME_LEGACY "Evas_Object_Table"
11
12 typedef struct _Evas_Table_Data Evas_Table_Data;
13 typedef struct _Evas_Object_Table_Option Evas_Object_Table_Option;
14 typedef struct _Evas_Object_Table_Cache Evas_Object_Table_Cache;
15 typedef struct _Evas_Object_Table_Iterator Evas_Object_Table_Iterator;
16 typedef struct _Evas_Object_Table_Accessor Evas_Object_Table_Accessor;
17
18 struct _Evas_Object_Table_Option
19 {
20 Evas_Object *obj;
21 unsigned short col, row, colspan, rowspan, end_col, end_row;
22 struct {
23 Evas_Coord w, h;
24 } min, max;
25 struct {
26 double h, v;
27 } align;
28 struct {
29 Evas_Coord l, r, t, b;
30 } pad;
31 Eina_Bool expand_h : 1; /* XXX required? */
32 Eina_Bool expand_v : 1; /* XXX required? */
33 Eina_Bool fill_h : 1;
34 Eina_Bool fill_v : 1;
35 };
36
37 struct _Evas_Object_Table_Cache
38 {
39 int ref;
40 struct {
41 struct {
42 double h, v;
43 } weights;
44 struct {
45 int h, v;
46 } expands;
47 struct {
48 Evas_Coord w, h;
49 } min;
50 } total;
51 struct {
52 double *h, *v;
53 } weights;
54 struct {
55 Evas_Coord *h, *v;
56 } sizes;
57 struct {
58 Eina_Bool *h, *v;
59 } expands;
60 double ___pad; // padding to make sure doubles at end can be aligned
61 };
62
63 struct _Evas_Table_Data
64 {
65 Eina_List *children;
66 struct {
67 Evas_Coord h, v;
68 } pad;
69 struct {
70 double h, v;
71 } align;
72 struct {
73 int cols, rows;
74 } size;
75 Evas_Object_Table_Cache *cache;
76 Evas_Object_Table_Homogeneous_Mode homogeneous;
77 Eina_Bool hints_changed : 1;
78 Eina_Bool expand_h : 1;
79 Eina_Bool expand_v : 1;
80 Eina_Bool is_mirrored : 1;
81 };
82
83 struct _Evas_Object_Table_Iterator
84 {
85 Eina_Iterator iterator;
86
87 Eina_Iterator *real_iterator;
88 const Evas_Object *table;
89 };
90
91 struct _Evas_Object_Table_Accessor
92 {
93 Eina_Accessor accessor;
94
95 Eina_Accessor *real_accessor;
96 const Evas_Object *table;
97 };
98
99 #define EVAS_OBJECT_TABLE_DATA_GET(o, ptr) \
100 Evas_Table_Data *ptr = efl_data_scope_get(o, MY_CLASS)
101
102 #define EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, ptr) \
103 EVAS_OBJECT_TABLE_DATA_GET(o, ptr); \
104 if (!ptr) \
105 { \
106 ERR("No widget data for object %p (%s)", \
107 o, evas_object_type_get(o)); \
108 return; \
109 }
110
111 #define EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
112 EVAS_OBJECT_TABLE_DATA_GET(o, ptr); \
113 if (!ptr) \
114 { \
115 ERR("No widget data for object %p (%s)", \
116 o, evas_object_type_get(o)); \
117 return val; \
118 }
119
120 static const char EVAS_OBJECT_TABLE_OPTION_KEY[] = "|EvTb";
121
122 static Eina_Bool
_evas_object_table_iterator_next(Evas_Object_Table_Iterator * it,void ** data)123 _evas_object_table_iterator_next(Evas_Object_Table_Iterator *it, void **data)
124 {
125 Evas_Object_Table_Option *opt;
126
127 if (!eina_iterator_next(it->real_iterator, (void **)&opt))
128 return EINA_FALSE;
129 if (data) *data = opt->obj;
130 return EINA_TRUE;
131 }
132
133 static Evas_Object *
_evas_object_table_iterator_get_container(Evas_Object_Table_Iterator * it)134 _evas_object_table_iterator_get_container(Evas_Object_Table_Iterator *it)
135 {
136 return (Evas_Object *)it->table;
137 }
138
139 static void
_evas_object_table_iterator_free(Evas_Object_Table_Iterator * it)140 _evas_object_table_iterator_free(Evas_Object_Table_Iterator *it)
141 {
142 eina_iterator_free(it->real_iterator);
143 free(it);
144 }
145
146 static Eina_Bool
_evas_object_table_accessor_get_at(Evas_Object_Table_Accessor * it,unsigned int idx,void ** data)147 _evas_object_table_accessor_get_at(Evas_Object_Table_Accessor *it, unsigned int idx, void **data)
148 {
149 Evas_Object_Table_Option *opt = NULL;
150
151 if (!eina_accessor_data_get(it->real_accessor, idx, (void **)&opt))
152 return EINA_FALSE;
153 if (data) *data = opt->obj;
154 return EINA_TRUE;
155 }
156
157 static Evas_Object *
_evas_object_table_accessor_get_container(Evas_Object_Table_Accessor * it)158 _evas_object_table_accessor_get_container(Evas_Object_Table_Accessor *it)
159 {
160 return (Evas_Object *)it->table;
161 }
162
163 static void
_evas_object_table_accessor_free(Evas_Object_Table_Accessor * it)164 _evas_object_table_accessor_free(Evas_Object_Table_Accessor *it)
165 {
166 eina_accessor_free(it->real_accessor);
167 free(it);
168 }
169
170 static Evas_Object_Table_Cache *
_evas_object_table_cache_alloc(int cols,int rows)171 _evas_object_table_cache_alloc(int cols, int rows)
172 {
173 Evas_Object_Table_Cache *cache;
174 int size;
175
176 size = sizeof(Evas_Object_Table_Cache) +
177 ((cols + rows) *
178 (sizeof(double) + sizeof(Evas_Coord) + sizeof(Eina_Bool)));
179 cache = malloc(size);
180 if (!cache)
181 {
182 ERR("Could not allocate table cache %dx%d (%d bytes): %s",
183 cols, rows, size, strerror(errno));
184 return NULL;
185 }
186
187 cache->ref = 1;
188 cache->weights.h = (double *)(cache + 1);
189 cache->weights.v = (double *)(cache->weights.h + cols);
190 cache->sizes.h = (Evas_Coord *)(cache->weights.v + rows);
191 cache->sizes.v = (Evas_Coord *)(cache->sizes.h + cols);
192 cache->expands.h = (Eina_Bool *)(cache->sizes.v + rows);
193 cache->expands.v = (Eina_Bool *)(cache->expands.h + cols);
194
195 return cache;
196 }
197
198 static void
_evas_object_table_cache_free(Evas_Object_Table_Cache * cache)199 _evas_object_table_cache_free(Evas_Object_Table_Cache *cache)
200 {
201 cache->ref--;
202 if (cache->ref == 0) free(cache);
203 }
204
205 static void
_evas_object_table_cache_reset(Evas_Table_Data * priv)206 _evas_object_table_cache_reset(Evas_Table_Data *priv)
207 {
208 Evas_Object_Table_Cache *c = priv->cache;
209 int size;
210
211 if (!c) return;
212 c->total.expands.v = 0;
213 c->total.expands.h = 0;
214 c->total.min.w = 0;
215 c->total.min.h = 0;
216
217 size = ((priv->size.rows + priv->size.cols) *
218 (sizeof(double) + sizeof(Evas_Coord) + sizeof(Eina_Bool)));
219 memset(c + 1, 0, size);
220 }
221
222 static void
_evas_object_table_cache_invalidate(Evas_Table_Data * priv)223 _evas_object_table_cache_invalidate(Evas_Table_Data *priv)
224 {
225 priv->hints_changed = 1;
226 if (priv->cache)
227 {
228 _evas_object_table_cache_free(priv->cache);
229 priv->cache = NULL;
230 }
231 }
232
233 static Evas_Object_Table_Option *
_evas_object_table_option_get(Evas_Object * o)234 _evas_object_table_option_get(Evas_Object *o)
235 {
236 return evas_object_data_get(o, EVAS_OBJECT_TABLE_OPTION_KEY);
237 }
238
239 static void
_evas_object_table_option_set(Evas_Object * o,const Evas_Object_Table_Option * opt)240 _evas_object_table_option_set(Evas_Object *o, const Evas_Object_Table_Option *opt)
241 {
242 evas_object_data_set(o, EVAS_OBJECT_TABLE_OPTION_KEY, opt);
243 }
244
245 static Evas_Object_Table_Option *
_evas_object_table_option_del(Evas_Object * o)246 _evas_object_table_option_del(Evas_Object *o)
247 {
248 return evas_object_data_del(o, EVAS_OBJECT_TABLE_OPTION_KEY);
249 }
250
251 static void
_on_child_invalidate(void * data,const Efl_Event * event)252 _on_child_invalidate(void *data, const Efl_Event *event)
253 {
254 Evas_Object *table = data;
255 evas_object_table_unpack(table, event->object);
256 }
257
258 static void
_on_child_hints_changed(void * data,const Efl_Event * event EINA_UNUSED)259 _on_child_hints_changed(void *data, const Efl_Event *event EINA_UNUSED)
260 {
261 Evas_Object *table = data;
262 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(table, priv);
263 _evas_object_table_cache_invalidate(priv);
264 evas_object_smart_changed(table);
265 }
266
267 EFL_CALLBACKS_ARRAY_DEFINE(evas_object_table_callbacks,
268 { EFL_EVENT_INVALIDATE, _on_child_invalidate },
269 { EFL_GFX_ENTITY_EVENT_HINTS_CHANGED, _on_child_hints_changed }
270 );
271
272 static void
_evas_object_table_child_connect(Evas_Object * o,Evas_Object * child)273 _evas_object_table_child_connect(Evas_Object *o, Evas_Object *child)
274 {
275 efl_event_callback_array_add(child, evas_object_table_callbacks(), o);
276 }
277
278 static void
_evas_object_table_child_disconnect(Evas_Object * o,Evas_Object * child)279 _evas_object_table_child_disconnect(Evas_Object *o, Evas_Object *child)
280 {
281 efl_event_callback_array_del(child, evas_object_table_callbacks(), o);
282 }
283
284 static void
_evas_object_table_calculate_cell(const Evas_Object_Table_Option * opt,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)285 _evas_object_table_calculate_cell(const Evas_Object_Table_Option *opt, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
286 {
287 Evas_Coord cw, ch;
288
289 *w -= opt->pad.l + opt->pad.r;
290 if (*w < opt->min.w)
291 cw = opt->min.w;
292 else if ((opt->max.w > -1) && (*w > opt->max.w))
293 cw = opt->max.w;
294 else if (opt->fill_h)
295 cw = *w;
296 else
297 cw = opt->min.w;
298
299 *h -= opt->pad.t + opt->pad.b;
300 if (*h < opt->min.h)
301 ch = opt->min.h;
302 else if ((opt->max.h > -1) && (*h > opt->max.h))
303 ch = opt->max.h;
304 else if (opt->fill_v)
305 ch = *h;
306 else
307 ch = opt->min.h;
308
309 *x += opt->pad.l;
310 if (cw != *w)
311 {
312 *x += (*w - cw) * opt->align.h;
313 *w = cw;
314 }
315
316 *y += opt->pad.t;
317 if (ch != *h)
318 {
319 *y += (*h - ch) * opt->align.v;
320 *h = ch;
321 }
322 }
323
324 static void
_evas_object_table_calculate_hints_homogeneous(Evas_Object * o,Evas_Table_Data * priv)325 _evas_object_table_calculate_hints_homogeneous(Evas_Object *o, Evas_Table_Data *priv)
326 {
327 Eina_List *l;
328 Evas_Object_Table_Option *opt;
329 Evas_Coord minw, minh, o_minw, o_minh;
330 Eina_Bool expand_h, expand_v;
331
332 o_minw = 0;
333 o_minh = 0;
334 minw = 0;
335 minh = 0;
336 expand_h = 0;
337 expand_v = 0;
338
339 EINA_LIST_FOREACH(priv->children, l, opt)
340 {
341 Evas_Object *child = opt->obj;
342 Evas_Coord child_minw, child_minh, cell_minw, cell_minh;
343 double weightw, weighth;
344
345 evas_object_size_hint_combined_min_get(child, &opt->min.w, &opt->min.h);
346 evas_object_size_hint_max_get(child, &opt->max.w, &opt->max.h);
347 evas_object_size_hint_padding_get
348 (child, &opt->pad.l, &opt->pad.r, &opt->pad.t, &opt->pad.b);
349 evas_object_size_hint_align_get(child, &opt->align.h, &opt->align.v);
350 evas_object_size_hint_weight_get(child, &weightw, &weighth);
351
352 child_minw = opt->min.w + opt->pad.l + opt->pad.r;
353 child_minh = opt->min.h + opt->pad.t + opt->pad.b;
354
355 cell_minw = (child_minw + opt->colspan - 1) / opt->colspan;
356 cell_minh = (child_minh + opt->rowspan - 1) / opt->rowspan;
357
358 opt->expand_h = 0;
359 if ((weightw > 0.0) &&
360 ((opt->max.w < 0) ||
361 ((opt->max.w > -1) && (opt->min.w < opt->max.w))))
362 {
363 opt->expand_h = 1;
364 expand_h = 1;
365 }
366
367 opt->expand_v = 0;
368 if ((weighth > 0.0) &&
369 ((opt->max.h < 0) ||
370 ((opt->max.h > -1) && (opt->min.h < opt->max.h))))
371 {
372 opt->expand_v = 1;
373 expand_v = 1;
374 }
375
376 opt->fill_h = 0;
377 if (opt->align.h < 0.0)
378 {
379 opt->align.h = 0.5;
380 opt->fill_h = 1;
381 }
382 opt->fill_v = 0;
383 if (opt->align.v < 0.0)
384 {
385 opt->align.v = 0.5;
386 opt->fill_v = 1;
387 }
388
389 /* greatest mininum values, with paddings */
390 if (minw < cell_minw)
391 minw = cell_minw;
392 if (minh < cell_minh)
393 minh = cell_minh;
394 /* greatest mininum values, without paddings */
395 if (o_minw < opt->min.w)
396 o_minw = opt->min.w;
397 if (o_minh < opt->min.h)
398 o_minh = opt->min.h;
399 }
400
401 if (priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM)
402 {
403 if (o_minw < 1)
404 {
405 ERR("homogeneous table based on item size but no "
406 "horizontal minimum size specified! Using expand.");
407 expand_h = 1;
408 }
409 if (o_minh < 1)
410 {
411 ERR("homogeneous table based on item size but no "
412 "vertical minimum size specified! Using expand.");
413 expand_v = 1;
414 }
415 }
416
417 minw = priv->size.cols * (minw + priv->pad.h) - priv->pad.h;
418 minh = priv->size.rows * (minh + priv->pad.v) - priv->pad.v;
419
420 priv->hints_changed = 0;
421 priv->expand_h = expand_h;
422 priv->expand_v = expand_v;
423
424 if ((minw > 0 ) || (minh > 0))
425 evas_object_size_hint_min_set(o, minw, minh);
426
427 // XXX hint max?
428 }
429
430 static void
_evas_object_table_calculate_layout_homogeneous_sizes_item(const Evas_Object * o,const Evas_Table_Data * priv,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h)431 _evas_object_table_calculate_layout_homogeneous_sizes_item(const Evas_Object *o, const Evas_Table_Data *priv, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
432 {
433 Evas_Coord minw, minh;
434 Eina_Bool expand_h, expand_v;
435
436 evas_object_size_hint_combined_min_get(o, &minw, &minh);
437 expand_h = priv->expand_h;
438 expand_v = priv->expand_v;
439
440 if (*w < minw)
441 expand_h = 0;
442 if (!expand_h)
443 {
444 *x += (*w - minw) * priv->align.h;
445 *w = minw;
446 }
447
448 if (*h < minh)
449 expand_v = 0;
450 if (!expand_v)
451 {
452 *y += (*h - minh) * priv->align.v;
453 *h = minh;
454 }
455 }
456
457 static void
_evas_object_table_calculate_layout_homogeneous_sizes(const Evas_Object * o,const Evas_Table_Data * priv,Evas_Coord * x,Evas_Coord * y,Evas_Coord * w,Evas_Coord * h,Evas_Coord * cellw,Evas_Coord * cellh)458 _evas_object_table_calculate_layout_homogeneous_sizes(const Evas_Object *o, const Evas_Table_Data *priv, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h, Evas_Coord *cellw, Evas_Coord *cellh)
459 {
460 evas_object_geometry_get(o, x, y, w, h);
461 if (priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM)
462 _evas_object_table_calculate_layout_homogeneous_sizes_item
463 (o, priv, x, y, w, h);
464
465 *cellw = (*w + priv->size.cols - 1) / priv->size.cols;
466 *cellh = (*h + priv->size.rows - 1) / priv->size.rows;
467 }
468
469 static void
_evas_object_table_calculate_layout_homogeneous(Evas_Object * o,Evas_Table_Data * priv)470 _evas_object_table_calculate_layout_homogeneous(Evas_Object *o, Evas_Table_Data *priv)
471 {
472 Evas_Coord x = 0, y = 0, w = 0, h = 0, ww, hh, cellw = 0, cellh = 0;
473 Eina_List *l;
474 Evas_Object_Table_Option *opt;
475
476 _evas_object_table_calculate_layout_homogeneous_sizes
477 (o, priv, &x, &y, &w, &h, &cellw, &cellh);
478
479 ww = w - ((priv->size.cols - 1) * priv->pad.h);
480 hh = h - ((priv->size.rows - 1) * priv->pad.v);
481
482 if (ww < 0) ww = 0;
483 if (hh < 0) hh = 0;
484
485 EINA_LIST_FOREACH(priv->children, l, opt)
486 {
487 Evas_Object *child = opt->obj;
488 Evas_Coord cx, cy, cw, ch, cox, coy, cow, coh;
489
490 cx = x + ((opt->col * ww) / priv->size.cols);
491 cw = x + (((opt->col + opt->colspan) * ww) / priv->size.cols) - cx;
492 cw += (opt->colspan - 1) * priv->pad.v;
493 cy = y + ((opt->row * hh) / priv->size.rows);
494 ch = y + (((opt->row + opt->rowspan) * hh) / priv->size.rows) - cy;
495 ch += (opt->rowspan - 1) * priv->pad.h;
496
497 cx += (opt->col) * priv->pad.h;
498 cy += (opt->row) * priv->pad.v;
499
500 cox = cx;
501 coy = cy;
502 cow = cw;
503 coh = ch;
504
505 _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch);
506 if (cw > cow)
507 {
508 cx = cox;
509 cw = cow;
510 }
511 if (ch > coh)
512 {
513 cy = coy;
514 ch = coh;
515 }
516
517 if (priv->is_mirrored)
518 evas_object_geometry_set(opt->obj, x + w - (cx - x + cw), cy, cw, ch);
519 else
520 evas_object_geometry_set(child, cx, cy, cw, ch);
521 }
522 }
523
524 static void
_evas_object_table_smart_calculate_homogeneous(Evas_Object * o,Evas_Table_Data * priv)525 _evas_object_table_smart_calculate_homogeneous(Evas_Object *o, Evas_Table_Data *priv)
526 {
527 if (priv->hints_changed)
528 _evas_object_table_calculate_hints_homogeneous(o, priv);
529 _evas_object_table_calculate_layout_homogeneous(o, priv);
530 }
531
532 static int
_evas_object_table_count_expands(const Eina_Bool * expands,int start,int end)533 _evas_object_table_count_expands(const Eina_Bool *expands, int start, int end)
534 {
535 const Eina_Bool *itr = expands + start, *itr_end = expands + end;
536 int count = 0;
537
538 for (; itr < itr_end; itr++)
539 {
540 if (*itr)
541 count++;
542 }
543
544 return count;
545 }
546
547 static Evas_Coord
_evas_object_table_sum_sizes(const Evas_Coord * sizes,int start,int end)548 _evas_object_table_sum_sizes(const Evas_Coord *sizes, int start, int end)
549 {
550 const Evas_Coord *itr = sizes + start, *itr_end = sizes + end;
551 Evas_Coord sum = 0;
552
553 for (; itr < itr_end; itr++)
554 sum += *itr;
555
556 return sum;
557 }
558
559 static void
_evas_object_table_sizes_calc_noexpand(Evas_Coord * sizes,int start,int end,Evas_Coord space)560 _evas_object_table_sizes_calc_noexpand(Evas_Coord *sizes, int start, int end, Evas_Coord space)
561 {
562 Evas_Coord *itr = sizes + start, *itr_end = sizes + end - 1;
563 Evas_Coord step;
564 int units;
565
566 /* XXX move to fixed point math and spread errors among cells */
567 units = end - start;
568 step = space / units;
569 for (; itr < itr_end; itr++)
570 *itr += step;
571
572 *itr += space - step * (units - 1);
573 }
574
575 static void
_evas_object_table_sizes_calc_expand(Evas_Coord * sizes,int start,int end,Evas_Coord space,const Eina_Bool * expands,int expand_count,double * weights,double weighttot)576 _evas_object_table_sizes_calc_expand(Evas_Coord *sizes, int start, int end, Evas_Coord space, const Eina_Bool *expands, int expand_count, double *weights, double weighttot)
577 {
578 Evas_Coord *itr = sizes + start, *itr_end = sizes + end;
579 const Eina_Bool *itr_expand = expands + start;
580 Evas_Coord step = 0, last_space = 0;
581 int total = 0, i = start;
582
583 /* XXX move to fixed point math and spread errors among cells */
584 if (weighttot > 0.0)
585 {
586 step = space / expand_count;
587 last_space = space - step * (expand_count - 1);
588 }
589
590 for (; itr < itr_end; itr++, itr_expand++, i++)
591 {
592 if (weighttot <= 0.0)
593 {
594 if (*itr_expand)
595 {
596 expand_count--;
597 if (expand_count > 0)
598 *itr += step;
599 else
600 {
601 *itr += last_space;
602 break;
603 }
604 }
605 }
606 else
607 {
608 if (*itr_expand)
609 {
610 expand_count--;
611 if (expand_count > 0)
612 {
613 step = (weights[i] / weighttot) * space;
614 *itr += step;
615 total += step;
616 }
617 else
618 {
619 *itr += space - total;
620 break;
621 }
622 }
623 }
624 }
625 }
626
627 static void
_evas_object_table_calculate_hints_regular(Evas_Object * o,Evas_Table_Data * priv)628 _evas_object_table_calculate_hints_regular(Evas_Object *o, Evas_Table_Data *priv)
629 {
630 Evas_Object_Table_Option *opt;
631 Evas_Object_Table_Cache *c;
632 Eina_List *l;
633 double totweightw = 0.0, totweighth = 0.0;
634 int i;
635
636 if (!priv->cache)
637 {
638 priv->cache = _evas_object_table_cache_alloc
639 (priv->size.cols, priv->size.rows);
640 if (!priv->cache)
641 return;
642 }
643 c = priv->cache;
644 c->ref++;
645 _evas_object_table_cache_reset(priv);
646
647 /* cache interesting data */
648 memset(c->expands.h, 1, priv->size.cols * sizeof(Eina_Bool));
649 memset(c->expands.v, 1, priv->size.rows * sizeof(Eina_Bool));
650 EINA_LIST_FOREACH(priv->children, l, opt)
651 {
652 Evas_Object *child = opt->obj;
653 double weightw, weighth;
654
655 evas_object_size_hint_combined_min_get(child, &opt->min.w, &opt->min.h);
656 evas_object_size_hint_max_get(child, &opt->max.w, &opt->max.h);
657 evas_object_size_hint_padding_get
658 (child, &opt->pad.l, &opt->pad.r, &opt->pad.t, &opt->pad.b);
659 evas_object_size_hint_align_get(child, &opt->align.h, &opt->align.v);
660 evas_object_size_hint_weight_get(child, &weightw, &weighth);
661
662 opt->expand_h = 0;
663 if ((weightw > 0.0) &&
664 ((opt->max.w < 0) ||
665 ((opt->max.w > -1) && (opt->min.w < opt->max.w))))
666 opt->expand_h = 1;
667
668 opt->expand_v = 0;
669 if ((weighth > 0.0) &&
670 ((opt->max.h < 0) ||
671 ((opt->max.h > -1) && (opt->min.h < opt->max.h))))
672 opt->expand_v = 1;
673
674 opt->fill_h = 0;
675 if (opt->align.h < 0.0)
676 {
677 opt->align.h = 0.5;
678 opt->fill_h = 1;
679 }
680 opt->fill_v = 0;
681 if (opt->align.v < 0.0)
682 {
683 opt->align.v = 0.5;
684 opt->fill_v = 1;
685 }
686
687 if (!opt->expand_h)
688 memset(c->expands.h + opt->col, 0, opt->colspan * sizeof(Eina_Bool));
689 else
690 {
691 for (i = opt->col; i < opt->col + opt->colspan; i++)
692 c->weights.h[i] += (weightw / (double)opt->colspan);
693 }
694 if (!opt->expand_v)
695 memset(c->expands.v + opt->row, 0, opt->rowspan * sizeof(Eina_Bool));
696 else
697 {
698 for (i = opt->row; i < opt->row + opt->rowspan; i++)
699 c->weights.v[i] += (weighth / (double)opt->rowspan);
700 }
701 }
702 for (i = 0; i < priv->size.cols; i++) totweightw += c->weights.h[i];
703 for (i = 0; i < priv->size.rows; i++) totweighth += c->weights.v[i];
704
705 /* calculate sizes for each row and column */
706 EINA_LIST_FOREACH(priv->children, l, opt)
707 {
708 Evas_Coord tot, need;
709
710 /* handle horizontal */
711 tot = _evas_object_table_sum_sizes(c->sizes.h, opt->col, opt->end_col);
712 need = opt->min.w + opt->pad.l + opt->pad.r;
713 if (tot < need)
714 {
715 Evas_Coord space = need - tot;
716 int count;
717
718 count = _evas_object_table_count_expands
719 (c->expands.h, opt->col, opt->end_col);
720
721 if (count > 0)
722 _evas_object_table_sizes_calc_expand
723 (c->sizes.h, opt->col, opt->end_col, space,
724 c->expands.h, count, c->weights.h, totweightw);
725 else
726 _evas_object_table_sizes_calc_noexpand
727 (c->sizes.h, opt->col, opt->end_col, space);
728 }
729
730 /* handle vertical */
731 tot = _evas_object_table_sum_sizes(c->sizes.v, opt->row, opt->end_row);
732 need = opt->min.h + opt->pad.t + opt->pad.b;
733 if (tot < opt->min.h)
734 {
735 Evas_Coord space = need - tot;
736 int count;
737
738 count = _evas_object_table_count_expands
739 (c->expands.v, opt->row, opt->end_row);
740
741 if (count > 0)
742 _evas_object_table_sizes_calc_expand
743 (c->sizes.v, opt->row, opt->end_row, space,
744 c->expands.v, count, c->weights.v, totweighth);
745 else
746 _evas_object_table_sizes_calc_noexpand
747 (c->sizes.v, opt->row, opt->end_row, space);
748 }
749 }
750
751 c->total.weights.h = totweightw;
752 c->total.weights.v = totweighth;
753
754 c->total.expands.h = _evas_object_table_count_expands
755 (c->expands.h, 0, priv->size.cols);
756 c->total.expands.v = _evas_object_table_count_expands
757 (c->expands.v, 0, priv->size.rows);
758
759 c->total.min.w = _evas_object_table_sum_sizes
760 (c->sizes.h, 0, priv->size.cols);
761 c->total.min.h = _evas_object_table_sum_sizes
762 (c->sizes.v, 0, priv->size.rows);
763
764 c->total.min.w += priv->pad.h * (priv->size.cols - 1);
765 c->total.min.h += priv->pad.v * (priv->size.rows - 1);
766
767 if ((c->total.min.w > 0) || (c->total.min.h > 0))
768 evas_object_size_hint_min_set(o, c->total.min.w, c->total.min.h);
769 _evas_object_table_cache_free(c);
770 // XXX hint max?
771 }
772
773 static void
_evas_object_table_calculate_layout_regular(Evas_Object * o,Evas_Table_Data * priv)774 _evas_object_table_calculate_layout_regular(Evas_Object *o, Evas_Table_Data *priv)
775 {
776 Evas_Object_Table_Option *opt;
777 Evas_Object_Table_Cache *c;
778 Eina_List *l;
779 Evas_Coord *cols = NULL, *rows = NULL;
780 Evas_Coord x, y, w, h;
781 Evas_Coord totw;
782
783 c = priv->cache;
784 if (!c) return;
785
786 c->ref++;
787 evas_object_geometry_get(o, &x, &y, &w, &h);
788 totw = w;
789
790 /* handle horizontal */
791 if ((c->total.expands.h <= 0) || (c->total.min.w >= w))
792 {
793 x += (w - c->total.min.w) * priv->align.h;
794 w = c->total.min.w;
795 cols = c->sizes.h;
796 }
797 else
798 {
799 int size = priv->size.cols * sizeof(Evas_Coord);
800 cols = malloc(size);
801 if (!cols)
802 {
803 ERR("Could not allocate temp columns (%d bytes): %s",
804 size, strerror(errno));
805 goto end;
806 }
807 memcpy(cols, c->sizes.h, size);
808 _evas_object_table_sizes_calc_expand
809 (cols, 0, priv->size.cols, w - c->total.min.w,
810 c->expands.h, c->total.expands.h, c->weights.h, c->total.weights.h);
811 }
812
813 /* handle vertical */
814 if ((c->total.expands.v <= 0) || (c->total.min.h >= h))
815 {
816 y += (h - c->total.min.h) * priv->align.v;
817 h = c->total.min.h;
818 rows = c->sizes.v;
819 }
820 else
821 {
822 int size = priv->size.rows * sizeof(Evas_Coord);
823 rows = malloc(size);
824 if (!rows)
825 {
826 ERR("could not allocate temp rows (%d bytes): %s",
827 size, strerror(errno));
828 goto end;
829 }
830 memcpy(rows, c->sizes.v, size);
831 _evas_object_table_sizes_calc_expand
832 (rows, 0, priv->size.rows, h - c->total.min.h,
833 c->expands.v, c->total.expands.v, c->weights.v, c->total.weights.v);
834 }
835
836 EINA_LIST_FOREACH(priv->children, l, opt)
837 {
838 Evas_Object *child = opt->obj;
839 Evas_Coord cx, cy, cw, ch;
840
841 cx = x + opt->col * (priv->pad.h);
842 cx += _evas_object_table_sum_sizes(cols, 0, opt->col);
843 cw = (opt->colspan - 1) * priv->pad.h;
844 cw += _evas_object_table_sum_sizes(cols, opt->col, opt->end_col);
845
846 cy = y + opt->row * (priv->pad.v);
847 cy += _evas_object_table_sum_sizes(rows, 0, opt->row);
848 ch = (opt->rowspan - 1) * priv->pad.v;
849 ch += _evas_object_table_sum_sizes(rows, opt->row, opt->end_row);
850
851 _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch);
852
853 if (priv->is_mirrored)
854 evas_object_geometry_set(opt->obj, x + w + 2 * (0.5 - priv->align.h) * (totw - w) - (cx - x + cw), cy, cw, ch);
855 else
856 evas_object_geometry_set(child, cx, cy, cw, ch);
857 }
858
859 end:
860 if (priv->cache)
861 {
862 if (cols != c->sizes.h)
863 {
864 if (cols) free(cols);
865 }
866 if (rows != c->sizes.v)
867 {
868 if (rows) free(rows);
869 }
870 }
871 _evas_object_table_cache_free(c);
872 }
873
874 static void
_evas_object_table_smart_calculate_regular(Evas_Object * o,Evas_Table_Data * priv)875 _evas_object_table_smart_calculate_regular(Evas_Object *o, Evas_Table_Data *priv)
876 {
877 if (priv->hints_changed)
878 _evas_object_table_calculate_hints_regular(o, priv);
879 _evas_object_table_calculate_layout_regular(o, priv);
880 }
881
882 EOLIAN static void
_evas_table_efl_canvas_group_group_add(Eo * obj,Evas_Table_Data * priv)883 _evas_table_efl_canvas_group_group_add(Eo *obj, Evas_Table_Data *priv)
884 {
885 priv->pad.h = 0;
886 priv->pad.v = 0;
887 priv->align.h = 0.5;
888 priv->align.v = 0.5;
889 priv->size.cols = 0;
890 priv->size.rows = 0;
891 priv->cache = NULL;
892 priv->homogeneous = EVAS_OBJECT_TABLE_HOMOGENEOUS_NONE;
893 priv->hints_changed = 1;
894 priv->expand_h = 0;
895 priv->expand_v = 0;
896
897 efl_canvas_group_add(efl_super(obj, MY_CLASS));
898 }
899
900 EOLIAN static void
_evas_table_efl_canvas_group_group_del(Eo * obj,Evas_Table_Data * priv)901 _evas_table_efl_canvas_group_group_del(Eo *obj, Evas_Table_Data *priv)
902 {
903 Eina_List *l;
904
905 l = priv->children;
906 while (l)
907 {
908 Evas_Object_Table_Option *opt = l->data;
909 _evas_object_table_child_disconnect(obj, opt->obj);
910 _evas_object_table_option_del(opt->obj);
911 free(opt);
912 l = eina_list_remove_list(l, l);
913 }
914
915 if (priv->cache)
916 {
917 _evas_object_table_cache_free(priv->cache);
918 priv->cache = NULL;
919 }
920
921 efl_canvas_group_del(efl_super(obj, MY_CLASS));
922 }
923
924 EOLIAN static void
_evas_table_efl_gfx_entity_size_set(Eo * obj,Evas_Table_Data * _pd EINA_UNUSED,Eina_Size2D sz)925 _evas_table_efl_gfx_entity_size_set(Eo *obj, Evas_Table_Data *_pd EINA_UNUSED, Eina_Size2D sz)
926 {
927 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
928 return;
929
930 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
931 evas_object_smart_changed(obj);
932 }
933
934 EOLIAN static void
_evas_table_efl_gfx_entity_position_set(Eo * obj,Evas_Table_Data * _pd EINA_UNUSED,Eina_Position2D pos)935 _evas_table_efl_gfx_entity_position_set(Eo *obj, Evas_Table_Data *_pd EINA_UNUSED, Eina_Position2D pos)
936 {
937 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
938 return;
939
940 efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
941 evas_object_smart_changed(obj);
942 }
943
944 EOLIAN static void
_evas_table_efl_canvas_group_group_calculate(Eo * o,Evas_Table_Data * priv)945 _evas_table_efl_canvas_group_group_calculate(Eo *o, Evas_Table_Data *priv)
946 {
947 Evas *e;
948
949 if ((priv->size.cols < 1) || (priv->size.rows < 1))
950 {
951 DBG("Nothing to do: cols=%d, rows=%d",
952 priv->size.cols, priv->size.rows);
953 return;
954 }
955
956 e = evas_object_evas_get(o);
957 evas_event_freeze(e);
958
959 if (priv->homogeneous)
960 _evas_object_table_smart_calculate_homogeneous(o, priv);
961 else
962 _evas_object_table_smart_calculate_regular(o, priv);
963
964 evas_event_thaw(e);
965 evas_event_thaw_eval(e);
966 }
967
968 EAPI Evas_Object *
evas_object_table_add(Evas * evas)969 evas_object_table_add(Evas *evas)
970 {
971 evas = evas_find(evas);
972 EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(evas, EVAS_CANVAS_CLASS), NULL);
973 return efl_add(MY_CLASS, evas, efl_canvas_object_legacy_ctor(efl_added));
974 }
975
976 EOLIAN static Eo *
_evas_table_efl_object_constructor(Eo * obj,Evas_Table_Data * class_data EINA_UNUSED)977 _evas_table_efl_object_constructor(Eo *obj, Evas_Table_Data *class_data EINA_UNUSED)
978 {
979 efl_canvas_group_clipped_set(obj, EINA_TRUE);
980 obj = efl_constructor(efl_super(obj, MY_CLASS));
981 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
982
983 return obj;
984 }
985
986 EOLIAN static Evas_Object*
_evas_table_add_to(Eo * parent,Evas_Table_Data * _pd EINA_UNUSED)987 _evas_table_add_to(Eo *parent, Evas_Table_Data *_pd EINA_UNUSED)
988 {
989 Evas_Object *ret;
990 Evas *evas;
991
992 evas = evas_object_evas_get(parent);
993 ret = evas_object_table_add(evas);
994 evas_object_smart_member_add(ret, parent);
995
996 return ret;
997 }
998
999 EOLIAN static void
_evas_table_homogeneous_set(Eo * o,Evas_Table_Data * priv,Evas_Object_Table_Homogeneous_Mode homogeneous)1000 _evas_table_homogeneous_set(Eo *o, Evas_Table_Data *priv, Evas_Object_Table_Homogeneous_Mode homogeneous)
1001 {
1002 if (priv->homogeneous == homogeneous)
1003 return;
1004 priv->homogeneous = homogeneous;
1005 _evas_object_table_cache_invalidate(priv);
1006 evas_object_smart_changed(o);
1007 }
1008
1009 EOLIAN static Evas_Object_Table_Homogeneous_Mode
_evas_table_homogeneous_get(const Eo * o EINA_UNUSED,Evas_Table_Data * priv)1010 _evas_table_homogeneous_get(const Eo *o EINA_UNUSED, Evas_Table_Data *priv)
1011 {
1012 return priv->homogeneous;
1013 }
1014
1015 EOLIAN static void
_evas_table_align_set(Eo * o,Evas_Table_Data * priv,double horizontal,double vertical)1016 _evas_table_align_set(Eo *o, Evas_Table_Data *priv, double horizontal, double vertical)
1017 {
1018 if ((EINA_DBL_EQ(priv->align.h, horizontal)) &&
1019 (EINA_DBL_EQ(priv->align.v, vertical)))
1020 return;
1021 priv->align.h = horizontal;
1022 priv->align.v = vertical;
1023 evas_object_smart_changed(o);
1024 }
1025
1026 EOLIAN static void
_evas_table_align_get(const Eo * o EINA_UNUSED,Evas_Table_Data * priv,double * horizontal,double * vertical)1027 _evas_table_align_get(const Eo *o EINA_UNUSED, Evas_Table_Data *priv, double *horizontal, double *vertical)
1028 {
1029 if (priv)
1030 {
1031 if (horizontal) *horizontal = priv->align.h;
1032 if (vertical) *vertical = priv->align.v;
1033 }
1034 else
1035 {
1036 if (horizontal) *horizontal = 0.5;
1037 if (vertical) *vertical = 0.5;
1038 }
1039 }
1040
1041 EOLIAN static void
_evas_table_padding_set(Eo * o,Evas_Table_Data * priv,Evas_Coord horizontal,Evas_Coord vertical)1042 _evas_table_padding_set(Eo *o, Evas_Table_Data *priv, Evas_Coord horizontal, Evas_Coord vertical)
1043 {
1044 if (priv->pad.h == horizontal && priv->pad.v == vertical)
1045 return;
1046 priv->pad.h = horizontal;
1047 priv->pad.v = vertical;
1048 _evas_object_table_cache_invalidate(priv);
1049 evas_object_smart_changed(o);
1050 }
1051
1052 EOLIAN static void
_evas_table_padding_get(const Eo * o EINA_UNUSED,Evas_Table_Data * priv,Evas_Coord * horizontal,Evas_Coord * vertical)1053 _evas_table_padding_get(const Eo *o EINA_UNUSED, Evas_Table_Data *priv, Evas_Coord *horizontal, Evas_Coord *vertical)
1054 {
1055 if (priv)
1056 {
1057 if (horizontal) *horizontal = priv->pad.h;
1058 if (vertical) *vertical = priv->pad.v;
1059 }
1060 else
1061 {
1062 if (horizontal) *horizontal = 0;
1063 if (vertical) *vertical = 0;
1064 }
1065 }
1066
1067 EOLIAN static Eina_Bool
_evas_table_pack_get(const Eo * o EINA_UNUSED,Evas_Table_Data * _pd EINA_UNUSED,Evas_Object * child,unsigned short * col,unsigned short * row,unsigned short * colspan,unsigned short * rowspan)1068 _evas_table_pack_get(const Eo *o EINA_UNUSED, Evas_Table_Data *_pd EINA_UNUSED, Evas_Object *child, unsigned short *col, unsigned short *row, unsigned short *colspan, unsigned short *rowspan)
1069 {
1070 Evas_Object_Table_Option *opt;
1071
1072 opt = _evas_object_table_option_get(child);
1073 if (!opt)
1074 {
1075 if (col) *col = 0;
1076 if (row) *row = 0;
1077 if (colspan) *colspan = 0;
1078 if (rowspan) *rowspan = 0;
1079 return EINA_FALSE;
1080 }
1081 if (col) *col = opt->col;
1082 if (row) *row = opt->row;
1083 if (colspan) *colspan = opt->colspan;
1084 if (rowspan) *rowspan = opt->rowspan;
1085
1086 return EINA_TRUE;
1087 }
1088
1089 EOLIAN static Eina_Bool
_evas_table_pack(Eo * o,Evas_Table_Data * priv,Evas_Object * child,unsigned short col,unsigned short row,unsigned short colspan,unsigned short rowspan)1090 _evas_table_pack(Eo *o, Evas_Table_Data *priv, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
1091 {
1092 Eina_Bool optalloc = EINA_FALSE;
1093
1094 Evas_Object_Table_Option *opt;
1095
1096 if (colspan < 1)
1097 {
1098 ERR("colspan < 1");
1099 return EINA_FALSE;
1100 }
1101 if ((0xffff - col) < colspan)
1102 {
1103 ERR("col + colspan > 0xffff");
1104 return EINA_FALSE;
1105 }
1106 if ((col + colspan) >= 0x7ffff)
1107 {
1108 WRN("col + colspan getting rather large (>32767)");
1109 }
1110 if (rowspan < 1)
1111 {
1112 ERR("rowspan < 1");
1113 return EINA_FALSE;
1114 }
1115 if ((0xffff - row) < rowspan)
1116 {
1117 ERR("row + rowspan > 0xffff");
1118 return EINA_FALSE;
1119 }
1120 if ((row + rowspan) >= 0x7ffff)
1121 {
1122 WRN("row + rowspan getting rather large (>32767)");
1123 }
1124
1125 opt = _evas_object_table_option_get(child);
1126 if (opt)
1127 {
1128 if (evas_object_smart_parent_get(child) != o)
1129 {
1130 CRI("cannot pack child of one table into another table!");
1131 return EINA_FALSE;
1132 }
1133 }
1134 else
1135 {
1136 opt = malloc(sizeof(*opt));
1137 if (!opt)
1138 {
1139 ERR("could not allocate table option data.");
1140 return EINA_FALSE;
1141 }
1142 optalloc = EINA_TRUE;
1143 }
1144
1145 opt->obj = child;
1146 opt->col = col;
1147 opt->row = row;
1148 opt->colspan = colspan;
1149 opt->rowspan = rowspan;
1150 opt->end_col = col + colspan;
1151 opt->end_row = row + rowspan;
1152
1153 if (!optalloc)
1154 {
1155 Eina_Bool need_shrink = EINA_FALSE;
1156
1157 if (priv->size.cols < opt->end_col)
1158 priv->size.cols = opt->end_col;
1159 else
1160 need_shrink = EINA_TRUE;
1161 if (priv->size.rows < opt->end_row)
1162 priv->size.rows = opt->end_row;
1163 else
1164 need_shrink = EINA_TRUE;
1165
1166 if (need_shrink)
1167 {
1168 Eina_List *l;
1169 Evas_Object_Table_Option *opt2;
1170 int max_row = 0, max_col = 0;
1171
1172 EINA_LIST_FOREACH(priv->children, l, opt2)
1173 {
1174 if (max_col < opt2->end_col) max_col = opt2->end_col;
1175 if (max_row < opt2->end_row) max_row = opt2->end_row;
1176 }
1177 priv->size.cols = max_col;
1178 priv->size.rows = max_row;
1179 }
1180 }
1181 else
1182 {
1183 opt->min.w = 0;
1184 opt->min.h = 0;
1185 opt->max.w = 0;
1186 opt->max.h = 0;
1187 opt->align.h = 0.5;
1188 opt->align.v = 0.5;
1189 opt->pad.l = 0;
1190 opt->pad.r = 0;
1191 opt->pad.t = 0;
1192 opt->pad.b = 0;
1193 opt->expand_h = 0;
1194 opt->expand_v = 0;
1195
1196 priv->children = eina_list_append(priv->children, opt);
1197
1198 if (priv->size.cols < opt->end_col)
1199 priv->size.cols = opt->end_col;
1200 if (priv->size.rows < opt->end_row)
1201 priv->size.rows = opt->end_row;
1202
1203 _evas_object_table_option_set(child, opt);
1204 evas_object_smart_member_add(child, o);
1205 _evas_object_table_child_connect(o, child);
1206 }
1207 _evas_object_table_cache_invalidate(priv);
1208 evas_object_smart_changed(o);
1209
1210 return EINA_TRUE;
1211 }
1212
1213 static void
_evas_object_table_remove_opt(Evas_Table_Data * priv,Evas_Object_Table_Option * opt)1214 _evas_object_table_remove_opt(Evas_Table_Data *priv, Evas_Object_Table_Option *opt)
1215 {
1216 Eina_List *l;
1217 int max_row, max_col, was_greatest;
1218
1219 max_row = 0;
1220 max_col = 0;
1221 was_greatest = 0;
1222 l = priv->children;
1223 while (l)
1224 {
1225 Evas_Object_Table_Option *cur_opt = l->data;
1226
1227 if (cur_opt != opt)
1228 {
1229 if (max_col < cur_opt->end_col)
1230 max_col = cur_opt->end_col;
1231 if (max_row < cur_opt->end_row)
1232 max_row = cur_opt->end_row;
1233
1234 l = l->next;
1235 }
1236 else
1237 {
1238 Eina_List *tmp = l->next;
1239 priv->children = eina_list_remove_list(priv->children, l);
1240
1241 if ((priv->size.cols > opt->end_col) &&
1242 (priv->size.rows > opt->end_row))
1243 break;
1244 else
1245 {
1246 was_greatest = 1;
1247 l = tmp;
1248 }
1249 }
1250 }
1251
1252 if (was_greatest)
1253 {
1254 priv->size.cols = max_col;
1255 priv->size.rows = max_row;
1256 }
1257 }
1258
1259 EOLIAN static Eina_Bool
_evas_table_unpack(Eo * o,Evas_Table_Data * priv,Evas_Object * child)1260 _evas_table_unpack(Eo *o, Evas_Table_Data *priv, Evas_Object *child)
1261 {
1262 Evas_Object_Table_Option *opt;
1263
1264 if (o != evas_object_smart_parent_get(child))
1265 {
1266 ERR("cannot unpack child from incorrect table!");
1267 return EINA_FALSE;
1268 }
1269
1270 opt = _evas_object_table_option_del(child);
1271 if (!opt)
1272 {
1273 ERR("cannot unpack child with no packing option!");
1274 return EINA_FALSE;
1275 }
1276
1277 _evas_object_table_child_disconnect(o, child);
1278 _evas_object_table_remove_opt(priv, opt);
1279 evas_object_smart_member_del(child);
1280 free(opt);
1281 _evas_object_table_cache_invalidate(priv);
1282 evas_object_smart_changed(o);
1283
1284 return EINA_TRUE;
1285 }
1286
1287 EOLIAN static void
_evas_table_clear(Eo * o,Evas_Table_Data * priv,Eina_Bool clear)1288 _evas_table_clear(Eo *o, Evas_Table_Data *priv, Eina_Bool clear)
1289 {
1290 Evas_Object_Table_Option *opt;
1291 Evas *e;
1292
1293 e = evas_object_evas_get(o);
1294 evas_event_freeze(e);
1295
1296 EINA_LIST_FREE(priv->children, opt)
1297 {
1298 _evas_object_table_child_disconnect(o, opt->obj);
1299 _evas_object_table_option_del(opt->obj);
1300 evas_object_smart_member_del(opt->obj);
1301 if (clear)
1302 evas_object_del(opt->obj);
1303 free(opt);
1304 }
1305 priv->size.cols = 0;
1306 priv->size.rows = 0;
1307 _evas_object_table_cache_invalidate(priv);
1308 evas_object_smart_changed(o);
1309
1310 evas_event_thaw(e);
1311 }
1312
1313 EOLIAN static void
_evas_table_col_row_size_get(const Eo * o EINA_UNUSED,Evas_Table_Data * priv,int * cols,int * rows)1314 _evas_table_col_row_size_get(const Eo *o EINA_UNUSED, Evas_Table_Data *priv, int *cols, int *rows)
1315 {
1316 if (priv)
1317 {
1318 if (cols) *cols = priv->size.cols;
1319 if (rows) *rows = priv->size.rows;
1320 }
1321 else
1322 {
1323 if (cols) *cols = -1;
1324 if (rows) *rows = -1;
1325 }
1326 }
1327
1328 EOLIAN static Eina_Iterator*
_evas_table_iterator_new(const Eo * o,Evas_Table_Data * priv)1329 _evas_table_iterator_new(const Eo *o, Evas_Table_Data *priv)
1330 {
1331 Evas_Object_Table_Iterator *it;
1332
1333 if (!priv->children)
1334 {
1335 return NULL;
1336 }
1337
1338 it = calloc(1, sizeof(Evas_Object_Table_Iterator));
1339 if (!it)
1340 {
1341 return NULL;
1342 }
1343
1344 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1345
1346 it->real_iterator = eina_list_iterator_new(priv->children);
1347 it->table = o;
1348
1349 it->iterator.next = FUNC_ITERATOR_NEXT(_evas_object_table_iterator_next);
1350 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_evas_object_table_iterator_get_container);
1351 it->iterator.free = FUNC_ITERATOR_FREE(_evas_object_table_iterator_free);
1352
1353 return &it->iterator;
1354 }
1355
1356 EOLIAN static Eina_Accessor*
_evas_table_accessor_new(const Eo * o,Evas_Table_Data * priv)1357 _evas_table_accessor_new(const Eo *o, Evas_Table_Data *priv)
1358 {
1359 Evas_Object_Table_Accessor *it;
1360
1361 if (!priv->children) return NULL;
1362
1363 it = calloc(1, sizeof(Evas_Object_Table_Accessor));
1364 if (!it) return NULL;
1365
1366 EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
1367
1368 it->real_accessor = eina_list_accessor_new(priv->children);
1369 it->table = o;
1370
1371 it->accessor.get_at = FUNC_ACCESSOR_GET_AT(_evas_object_table_accessor_get_at);
1372 it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(_evas_object_table_accessor_get_container);
1373 it->accessor.free = FUNC_ACCESSOR_FREE(_evas_object_table_accessor_free);
1374
1375 return &it->accessor;
1376 }
1377
1378 EOLIAN static Eina_List*
_evas_table_children_get(const Eo * o EINA_UNUSED,Evas_Table_Data * priv)1379 _evas_table_children_get(const Eo *o EINA_UNUSED, Evas_Table_Data *priv)
1380 {
1381 Eina_List *new_list = NULL, *l;
1382 Evas_Object_Table_Option *opt;
1383
1384 EINA_LIST_FOREACH(priv->children, l, opt)
1385 new_list = eina_list_append(new_list, opt->obj);
1386
1387 return new_list;
1388 }
1389
1390 EOLIAN static int
_evas_table_count(Eo * o EINA_UNUSED,Evas_Table_Data * priv)1391 _evas_table_count(Eo *o EINA_UNUSED, Evas_Table_Data *priv)
1392 {
1393 return eina_list_count(priv->children);
1394 }
1395
1396 EOLIAN static Evas_Object *
_evas_table_child_get(const Eo * o EINA_UNUSED,Evas_Table_Data * priv,unsigned short col,unsigned short row)1397 _evas_table_child_get(const Eo *o EINA_UNUSED, Evas_Table_Data *priv, unsigned short col, unsigned short row)
1398 {
1399 Eina_List *l;
1400 Evas_Object_Table_Option *opt;
1401
1402 EINA_LIST_FOREACH(priv->children, l, opt)
1403 if (opt->col == col && opt->row == row)
1404 return opt->obj;
1405 return NULL;
1406 }
1407
1408 EOLIAN static Eina_Bool
_evas_table_efl_ui_i18n_mirrored_get(const Eo * o EINA_UNUSED,Evas_Table_Data * priv)1409 _evas_table_efl_ui_i18n_mirrored_get(const Eo *o EINA_UNUSED, Evas_Table_Data *priv)
1410 {
1411 return priv->is_mirrored;
1412 }
1413
1414 EAPI Eina_Bool
evas_object_table_mirrored_get(const Eo * obj)1415 evas_object_table_mirrored_get(const Eo *obj)
1416 {
1417 return efl_ui_mirrored_get(obj);
1418 }
1419
1420 EOLIAN static void
_evas_table_efl_ui_i18n_mirrored_set(Eo * o,Evas_Table_Data * priv,Eina_Bool mirrored)1421 _evas_table_efl_ui_i18n_mirrored_set(Eo *o, Evas_Table_Data *priv, Eina_Bool mirrored)
1422 {
1423 if (priv->is_mirrored != mirrored)
1424 {
1425 priv->is_mirrored = mirrored;
1426 efl_canvas_group_calculate(o);
1427 }
1428 }
1429
1430 EAPI void
evas_object_table_mirrored_set(Eo * obj,Eina_Bool mirrored)1431 evas_object_table_mirrored_set(Eo *obj, Eina_Bool mirrored)
1432 {
1433 efl_ui_mirrored_set(obj, mirrored);
1434 }
1435
1436 EOLIAN static void
_evas_table_class_constructor(Efl_Class * klass)1437 _evas_table_class_constructor(Efl_Class *klass)
1438 {
1439 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1440 }
1441
1442 /* Internal EO APIs and hidden overrides */
1443
1444 #define EVAS_TABLE_EXTRA_OPS \
1445 EFL_CANVAS_GROUP_ADD_DEL_OPS(evas_table)
1446
1447 #include "canvas/evas_table_eo.c"
1448