4a305f0ec5fcb370aab217c25156b4c9236b819c
[framework/uifw/evas.git] / src / lib / canvas / evas_object_smart.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 typedef struct _Evas_Object_Smart      Evas_Object_Smart;
5 typedef struct _Evas_Smart_Callback    Evas_Smart_Callback;
6
7 struct _Evas_Object_Smart
8 {
9    DATA32            magic;
10    void             *engine_data;
11    void             *data;
12    Eina_List        *callbacks;
13    Eina_Inlist *contained;
14    Evas_Smart_Cb_Description_Array callbacks_descriptions;
15    int               walking_list;
16    Eina_Bool         deletions_waiting : 1;
17    Eina_Bool         need_recalculate : 1;
18 };
19
20 struct _Evas_Smart_Callback
21 {
22    const char *event;
23    Evas_Smart_Cb func;
24    void *func_data;
25    Evas_Callback_Priority priority;
26    char  delete_me : 1;
27 };
28
29 /* private methods for smart objects */
30 static void evas_object_smart_callbacks_clear(Evas_Object *obj);
31 static void evas_object_smart_init(Evas_Object *obj);
32 static void *evas_object_smart_new(void);
33 static void evas_object_smart_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
34 static void evas_object_smart_free(Evas_Object *obj);
35 static void evas_object_smart_render_pre(Evas_Object *obj);
36 static void evas_object_smart_render_post(Evas_Object *obj);
37
38 static unsigned int evas_object_smart_id_get(Evas_Object *obj);
39 static unsigned int evas_object_smart_visual_id_get(Evas_Object *obj);
40 static void *evas_object_smart_engine_data_get(Evas_Object *obj);
41
42 static const Evas_Object_Func object_func =
43 {
44    /* methods (compulsory) */
45    evas_object_smart_free,
46    evas_object_smart_render,
47    evas_object_smart_render_pre,
48    evas_object_smart_render_post,
49    evas_object_smart_id_get,
50    evas_object_smart_visual_id_get,
51    evas_object_smart_engine_data_get,
52    /* these are optional. NULL = nothing */
53    NULL,
54    NULL,
55    NULL,
56    NULL,
57    NULL,
58    NULL,
59    NULL,
60    NULL,
61    NULL,
62    NULL,
63    NULL,
64    NULL,
65    NULL
66 };
67
68 EVAS_MEMPOOL(_mp_obj);
69 EVAS_MEMPOOL(_mp_cb);
70
71 /* public funcs */
72 EAPI void
73 evas_object_smart_data_set(Evas_Object *obj, void *data)
74 {
75    Evas_Object_Smart *o;
76
77    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
78    return;
79    MAGIC_CHECK_END();
80    o = (Evas_Object_Smart *)(obj->object_data);
81    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
82    return;
83    MAGIC_CHECK_END();
84    o->data = data;
85 }
86
87 EAPI void *
88 evas_object_smart_data_get(const Evas_Object *obj)
89 {
90    Evas_Object_Smart *o;
91
92    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
93    return NULL;
94    MAGIC_CHECK_END();
95    o = (Evas_Object_Smart *)(obj->object_data);
96    if (!o) return NULL;
97    return o->data;
98 }
99
100 EAPI Evas_Smart *
101 evas_object_smart_smart_get(const Evas_Object *obj)
102 {
103    Evas_Object_Smart *o;
104
105    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
106    return NULL;
107    MAGIC_CHECK_END();
108    o = (Evas_Object_Smart *)(obj->object_data);
109    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
110    return NULL;
111    MAGIC_CHECK_END();
112    return obj->smart.smart;
113 }
114
115 EAPI void
116 evas_object_smart_member_add(Evas_Object *obj, Evas_Object *smart_obj)
117 {
118    Evas_Object_Smart *o;
119
120    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
121    return;
122    MAGIC_CHECK_END();
123    MAGIC_CHECK(smart_obj, Evas_Object, MAGIC_OBJ);
124    return;
125    MAGIC_CHECK_END();
126    o = (Evas_Object_Smart *)(smart_obj->object_data);
127    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
128    return;
129    MAGIC_CHECK_END();
130
131    if (obj->delete_me)
132      {
133         CRIT("Adding deleted object %p to smart obj %p", obj, smart_obj);
134         abort();
135         return;
136      }
137    if (smart_obj->delete_me)
138      {
139         CRIT("Adding object %p to deleted smart obj %p", obj, smart_obj);
140         abort();
141         return;
142      }
143    if (!smart_obj->layer)
144      {
145         CRIT("No evas surface associated with smart object (%p)", smart_obj);
146         abort();
147         return;
148      }
149    if (obj->layer && smart_obj->layer
150        && obj->layer->evas != smart_obj->layer->evas)
151      {
152         CRIT("Adding object %p from Evas (%p) from another Evas (%p)", obj, obj->layer->evas, smart_obj->layer->evas);
153         abort();
154         return;
155      }
156
157    if (obj->smart.parent == smart_obj) return;
158
159    if (obj->smart.parent) evas_object_smart_member_del(obj);
160
161    evas_object_release(obj, 1);
162    obj->layer = smart_obj->layer;
163    obj->cur.layer = obj->layer->layer;
164    obj->layer->usage++;
165    obj->smart.parent = smart_obj;
166    o->contained = eina_inlist_append(o->contained, EINA_INLIST_GET(obj));
167    evas_object_smart_member_cache_invalidate(obj);
168    obj->restack = 1;
169    evas_object_change(obj);
170    evas_object_mapped_clip_across_mark(obj);
171    if (smart_obj->smart.smart->smart_class->member_add)
172      smart_obj->smart.smart->smart_class->member_add(smart_obj, obj);
173 }
174
175 EAPI void
176 evas_object_smart_member_del(Evas_Object *obj)
177 {
178    Evas_Object_Smart *o;
179    Evas_Object *smart_obj;
180
181    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
182    return;
183    MAGIC_CHECK_END();
184
185    if (!obj->smart.parent) return;
186
187    smart_obj = obj->smart.parent;
188    if (smart_obj->smart.smart->smart_class->member_del)
189      smart_obj->smart.smart->smart_class->member_del(smart_obj, obj);
190
191    o = (Evas_Object_Smart *)(obj->smart.parent->object_data);
192    o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(obj));
193    obj->smart.parent = NULL;
194    evas_object_smart_member_cache_invalidate(obj);
195    obj->layer->usage--;
196    obj->cur.layer = obj->layer->layer;
197    evas_object_inject(obj, obj->layer->evas);
198    obj->restack = 1;
199    evas_object_change(obj);
200    evas_object_mapped_clip_across_mark(obj);
201 }
202
203 EAPI Evas_Object *
204 evas_object_smart_parent_get(const Evas_Object *obj)
205 {
206    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
207    return NULL;
208    MAGIC_CHECK_END();
209
210    return obj->smart.parent;
211 }
212
213 EAPI Eina_Bool
214 evas_object_smart_type_check(const Evas_Object *obj, const char *type)
215 {
216    const Evas_Smart_Class *sc;
217
218    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
219    return EINA_FALSE;
220    MAGIC_CHECK_END();
221
222    if (!obj->smart.smart)
223      return EINA_FALSE;
224    sc = obj->smart.smart->smart_class;
225    while (sc)
226      {
227         if (!strcmp(sc->name, type))
228           return EINA_TRUE;
229         sc = sc->parent;
230      }
231
232    return EINA_FALSE;
233 }
234
235 EAPI Eina_Bool
236 evas_object_smart_type_check_ptr(const Evas_Object *obj, const char *type)
237 {
238    const Evas_Smart_Class *sc;
239
240    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
241    return EINA_FALSE;
242    MAGIC_CHECK_END();
243
244    if (!obj->smart.smart)
245      return EINA_FALSE;
246    sc = obj->smart.smart->smart_class;
247    while (sc)
248      {
249         if (sc->name == type)
250           return EINA_TRUE;
251         sc = sc->parent;
252      }
253
254    return EINA_FALSE;
255 }
256
257 EAPI Eina_List *
258 evas_object_smart_members_get(const Evas_Object *obj)
259 {
260    Evas_Object_Smart *o;
261    Eina_List *members;
262    Eina_Inlist *member;
263
264    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
265    return NULL;
266    MAGIC_CHECK_END();
267    o = (Evas_Object_Smart *)(obj->object_data);
268    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
269    return NULL;
270    MAGIC_CHECK_END();
271
272    members = NULL;
273    for (member = o->contained; member; member = member->next)
274      members = eina_list_append(members, member);
275
276    return members;
277 }
278
279 const Eina_Inlist *
280 evas_object_smart_members_get_direct(const Evas_Object *obj)
281 {
282    Evas_Object_Smart *o;
283
284    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
285    return NULL;
286    MAGIC_CHECK_END();
287    o = (Evas_Object_Smart *)(obj->object_data);
288    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
289    return NULL;
290    MAGIC_CHECK_END();
291    return o->contained;
292 }
293
294 void
295 _evas_object_smart_members_all_del(Evas_Object *obj)
296 {
297    Evas_Object_Smart *o = (Evas_Object_Smart *)(obj->object_data);
298    while (o->contained)
299      evas_object_del((Evas_Object *)(o->contained));
300 }
301
302 EAPI Evas_Object *
303 evas_object_smart_add(Evas *e, Evas_Smart *s)
304 {
305    Evas_Object *obj;
306
307    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
308    return NULL;
309    MAGIC_CHECK_END();
310    MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
311    return NULL;
312    MAGIC_CHECK_END();
313
314    obj = evas_object_new(e);
315    if (!obj) return NULL;
316    obj->smart.smart = s;
317    obj->type = s->smart_class->name;
318    evas_object_smart_init(obj);
319    evas_object_inject(obj, e);
320
321    evas_object_smart_use(s);
322
323    if (s->smart_class->add) s->smart_class->add(obj);
324
325    return obj;
326 }
327
328 static int
329 _callback_priority_cmp(const void *_a, const void *_b)
330 {
331    const Evas_Smart_Callback *a, *b;
332    a = (const Evas_Smart_Callback *) _a;
333    b = (const Evas_Smart_Callback *) _b;
334    if (a->priority < b->priority)
335       return -1;
336    else
337       return 1;
338 }
339
340 EAPI void
341 evas_object_smart_callback_add(Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data)
342 {
343    evas_object_smart_callback_priority_add(obj, event,
344          EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
345 }
346
347 EAPI void
348 evas_object_smart_callback_priority_add(Evas_Object *obj, const char *event, Evas_Callback_Priority priority, Evas_Smart_Cb func, const void *data)
349 {
350    Evas_Object_Smart *o;
351    Evas_Smart_Callback *cb;
352
353    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
354    return;
355    MAGIC_CHECK_END();
356    o = (Evas_Object_Smart *)(obj->object_data);
357    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
358    return;
359    MAGIC_CHECK_END();
360    if (!event) return;
361    if (!func) return;
362    EVAS_MEMPOOL_INIT(_mp_cb, "evas_smart_callback", Evas_Smart_Callback, 512, );
363    cb = EVAS_MEMPOOL_ALLOC(_mp_cb, Evas_Smart_Callback);
364    if (!cb) return;
365    EVAS_MEMPOOL_PREP(_mp_cb, cb, Evas_Smart_Callback);
366    cb->event = eina_stringshare_add(event);
367    cb->func = func;
368    cb->func_data = (void *)data;
369    cb->priority = priority;
370    o->callbacks = eina_list_sorted_insert(o->callbacks, _callback_priority_cmp,
371          cb);
372 }
373
374 EAPI void *
375 evas_object_smart_callback_del(Evas_Object *obj, const char *event, Evas_Smart_Cb func)
376 {
377    Evas_Object_Smart *o;
378    Eina_List *l;
379    Evas_Smart_Callback *cb;
380
381    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
382    return NULL;
383    MAGIC_CHECK_END();
384    o = (Evas_Object_Smart *)(obj->object_data);
385    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
386    return NULL;
387    MAGIC_CHECK_END();
388    if (!event) return NULL;
389    EINA_LIST_FOREACH(o->callbacks, l, cb)
390      {
391         if ((!strcmp(cb->event, event)) && (cb->func == func))
392           {
393              void *data;
394
395              data = cb->func_data;
396              cb->delete_me = 1;
397              o->deletions_waiting = 1;
398              evas_object_smart_callbacks_clear(obj);
399              return data;
400           }
401      }
402    return NULL;
403 }
404
405 EAPI void
406 evas_object_smart_callback_call(Evas_Object *obj, const char *event, void *event_info)
407 {
408    Evas_Object_Smart *o;
409    Eina_List *l;
410    Evas_Smart_Callback *cb;
411    const char *strshare;
412
413    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
414    return;
415    MAGIC_CHECK_END();
416    o = (Evas_Object_Smart *)(obj->object_data);
417    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
418    return;
419    MAGIC_CHECK_END();
420    if (!event) return;
421    if (obj->delete_me) return;
422    o->walking_list++;
423    strshare = eina_stringshare_add(event);
424    EINA_LIST_FOREACH(o->callbacks, l, cb)
425      {
426         if (!cb->delete_me)
427           {
428              if (cb->event == strshare)
429                cb->func(cb->func_data, obj, event_info);
430           }
431         if (obj->delete_me)
432           break;
433      }
434    eina_stringshare_del(strshare);
435    o->walking_list--;
436    evas_object_smart_callbacks_clear(obj);
437 }
438
439 EAPI Eina_Bool
440 evas_object_smart_callbacks_descriptions_set(Evas_Object *obj, const Evas_Smart_Cb_Description *descriptions)
441 {
442    const Evas_Smart_Cb_Description *d;
443    Evas_Object_Smart *o;
444    unsigned int i, count = 0;
445
446    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
447    return EINA_FALSE;
448    MAGIC_CHECK_END();
449    o = (Evas_Object_Smart *)(obj->object_data);
450    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
451    return EINA_FALSE;
452    MAGIC_CHECK_END();
453
454    if ((!descriptions) || (!descriptions->name))
455      {
456         evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
457         return EINA_TRUE;
458      }
459
460    for (count = 0, d = descriptions; d->name; d++)
461      count++;
462
463    evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, count);
464    if (count == 0) return EINA_TRUE;
465
466    for (i = 0, d = descriptions; i < count; d++, i++)
467      o->callbacks_descriptions.array[i] = d;
468
469    evas_smart_cb_descriptions_fix(&o->callbacks_descriptions);
470
471    return EINA_TRUE;
472 }
473
474 EAPI void
475 evas_object_smart_callbacks_descriptions_get(const Evas_Object *obj, const Evas_Smart_Cb_Description ***class_descriptions, unsigned int *class_count, const Evas_Smart_Cb_Description ***instance_descriptions, unsigned int *instance_count)
476 {
477    Evas_Object_Smart *o;
478
479    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
480    if (class_descriptions) *class_descriptions = NULL;
481    if (class_count) *class_count = 0;
482    if (instance_descriptions) *instance_descriptions = NULL;
483    if (instance_count) *instance_count = 0;
484    return;
485    MAGIC_CHECK_END();
486    o = (Evas_Object_Smart *)(obj->object_data);
487    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
488    if (class_descriptions) *class_descriptions = NULL;
489    if (class_count) *class_count = 0;
490    if (instance_descriptions) *instance_descriptions = NULL;
491    if (instance_count) *instance_count = 0;
492    return;
493    MAGIC_CHECK_END();
494
495    if (class_descriptions)
496      *class_descriptions = obj->smart.smart->callbacks.array;
497    if (class_count)
498      *class_count = obj->smart.smart->callbacks.size;
499
500    if (instance_descriptions)
501      *instance_descriptions = o->callbacks_descriptions.array;
502    if (instance_count)
503      *instance_count = o->callbacks_descriptions.size;
504 }
505
506 EAPI void
507 evas_object_smart_callback_description_find(const Evas_Object *obj, const char *name, const Evas_Smart_Cb_Description **class_description, const Evas_Smart_Cb_Description **instance_description)
508 {
509    Evas_Object_Smart *o;
510
511    if (!name)
512      {
513         if (class_description) *class_description = NULL;
514         if (instance_description) *instance_description = NULL;
515         return;
516      }
517
518    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
519    if (class_description) *class_description = NULL;
520    if (instance_description) *instance_description = NULL;
521    return;
522    MAGIC_CHECK_END();
523    o = (Evas_Object_Smart *)(obj->object_data);
524    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
525    if (class_description) *class_description = NULL;
526    if (instance_description) *instance_description = NULL;
527    return;
528    MAGIC_CHECK_END();
529
530    if (class_description)
531      *class_description = evas_smart_cb_description_find
532         (&obj->smart.smart->callbacks, name);
533
534    if (instance_description)
535      *instance_description = evas_smart_cb_description_find
536         (&o->callbacks_descriptions, name);
537 }
538
539 EAPI void
540 evas_object_smart_need_recalculate_set(Evas_Object *obj, Eina_Bool value)
541 {
542    Evas_Object_Smart *o;
543    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
544    return;
545    MAGIC_CHECK_END();
546    o = obj->object_data;
547    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
548    return;
549    MAGIC_CHECK_END();
550
551    value = !!value;
552    if (o->need_recalculate == value)
553      return;
554
555    if (obj->recalculate_cycle > 64)
556      {
557         ERR("Object %p is not stable during recalc loop", obj);
558         return ;
559      }
560    if (obj->layer->evas->in_smart_calc)
561      obj->recalculate_cycle++;
562    o->need_recalculate = value;
563
564    if (!obj->smart.smart->smart_class->calculate) return;
565
566    /* XXX: objects can be present multiple times in calculate_objects()
567     * XXX: after a set-unset-set cycle, but it's not a problem since
568     * XXX: on _evas_render_call_smart_calculate() will check for the flag
569     * XXX: and it will be unset after the first.
570     */
571    if (o->need_recalculate)
572      {
573         Evas *e = obj->layer->evas;
574         eina_array_push(&e->calculate_objects, obj);
575      }
576    /* TODO: else, remove from array */
577 }
578
579 EAPI Eina_Bool
580 evas_object_smart_need_recalculate_get(const Evas_Object *obj)
581 {
582    Evas_Object_Smart *o;
583    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
584    return EINA_FALSE;
585    MAGIC_CHECK_END();
586    o = obj->object_data;
587    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
588    return EINA_FALSE;
589    MAGIC_CHECK_END();
590
591    return o->need_recalculate;
592 }
593
594 EAPI void
595 evas_object_smart_calculate(Evas_Object *obj)
596 {
597    Evas_Object_Smart *o;
598    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
599    return;
600    MAGIC_CHECK_END();
601    o = obj->object_data;
602    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
603    return;
604    MAGIC_CHECK_END();
605
606    if (!obj->smart.smart->smart_class->calculate)
607      return;
608
609    o->need_recalculate = 0;
610    obj->smart.smart->smart_class->calculate(obj);
611 }
612
613 EAPI void
614 evas_smart_objects_calculate(Evas *e)
615 {
616    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
617    return;
618    MAGIC_CHECK_END();
619    evas_call_smarts_calculate(e);
620 }
621
622 /**
623  * Call calculate() on all smart objects that need_recalculate.
624  *
625  * @internal
626  */
627 void
628 evas_call_smarts_calculate(Evas *e)
629 {
630    Eina_Array *calculate;
631    Evas_Object *obj;
632    Eina_Array_Iterator it;
633    unsigned int i;
634
635    e->in_smart_calc++;
636    calculate = &e->calculate_objects;
637    for (i = 0; i < eina_array_count_get(calculate); ++i)
638      {
639         Evas_Object_Smart *o;
640
641         obj = eina_array_data_get(calculate, i);
642         if (obj->delete_me)
643           continue;
644
645         o = obj->object_data;
646         if (o->need_recalculate)
647           {
648              o->need_recalculate = 0;
649              obj->smart.smart->smart_class->calculate(obj);
650           }
651      }
652    EINA_ARRAY_ITER_NEXT(calculate, i, obj, it)
653      {
654         obj->recalculate_cycle = 0;
655      }
656    e->in_smart_calc--;
657    if (e->in_smart_calc == 0) eina_array_clean(calculate);
658 }
659
660 EAPI void
661 evas_object_smart_changed(Evas_Object *obj)
662 {
663    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
664    return;
665    MAGIC_CHECK_END();
666    evas_object_change(obj);
667    evas_object_smart_need_recalculate_set(obj, 1);
668 }
669
670 /* internal calls */
671 static void
672 evas_object_smart_callbacks_clear(Evas_Object *obj)
673 {
674    Evas_Object_Smart *o;
675    Eina_List *l;
676    Evas_Smart_Callback *cb;
677
678    o = (Evas_Object_Smart *)(obj->object_data);
679
680    if (o->walking_list) return;
681    if (!o->deletions_waiting) return;
682    for (l = o->callbacks; l;)
683      {
684         cb = eina_list_data_get(l);
685         l = eina_list_next(l);
686         if (cb->delete_me)
687           {
688              o->callbacks = eina_list_remove(o->callbacks, cb);
689              if (cb->event) eina_stringshare_del(cb->event);
690              EVAS_MEMPOOL_FREE(_mp_cb, cb);
691           }
692      }
693 }
694
695 void
696 evas_object_smart_del(Evas_Object *obj)
697 {
698    Evas_Smart *s;
699
700    if (obj->delete_me) return;
701    s = obj->smart.smart;
702    if ((s) && (s->smart_class->del)) s->smart_class->del(obj);
703    if (obj->smart.parent) evas_object_smart_member_del(obj);
704    if (s) evas_object_smart_unuse(s);
705 }
706
707 void
708 evas_object_smart_cleanup(Evas_Object *obj)
709 {
710    Evas_Object_Smart *o;
711
712    if (obj->smart.parent)
713      evas_object_smart_member_del(obj);
714
715    o = (Evas_Object_Smart *)(obj->object_data);
716    if (o->magic == MAGIC_OBJ_SMART)
717      {
718         while (o->contained)
719           evas_object_smart_member_del((Evas_Object *)o->contained);
720
721         while (o->callbacks)
722           {
723              Evas_Smart_Callback *cb;
724
725              cb = o->callbacks->data;
726              o->callbacks = eina_list_remove(o->callbacks, cb);
727              if (cb->event) eina_stringshare_del(cb->event);
728              EVAS_MEMPOOL_FREE(_mp_cb, cb);
729           }
730
731         evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
732         o->data = NULL;
733      }
734
735    obj->smart.parent = NULL;
736    obj->smart.smart = NULL;
737 }
738
739 void
740 evas_object_smart_member_cache_invalidate(Evas_Object *obj)
741 {
742    Evas_Object_Smart *o;
743    Eina_Inlist *l;
744
745    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
746    return;
747    MAGIC_CHECK_END();
748
749    obj->parent_cache_valid = 0;
750
751    o = (Evas_Object_Smart *)(obj->object_data);
752    if (o->magic != MAGIC_OBJ_SMART)
753      return;
754
755    for (l = o->contained; l; l = l->next)
756      {
757         Evas_Object *obj2;
758
759         obj2 = (Evas_Object *)l;
760         evas_object_smart_member_cache_invalidate(obj2);
761      }
762 }
763
764 void
765 evas_object_smart_member_raise(Evas_Object *member)
766 {
767    Evas_Object_Smart *o;
768
769    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
770    o->contained = eina_inlist_demote(o->contained, EINA_INLIST_GET(member));
771 }
772
773 void
774 evas_object_smart_member_lower(Evas_Object *member)
775 {
776    Evas_Object_Smart *o;
777
778    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
779    o->contained = eina_inlist_promote(o->contained, EINA_INLIST_GET(member));
780 }
781
782 void
783 evas_object_smart_member_stack_above(Evas_Object *member, Evas_Object *other)
784 {
785    Evas_Object_Smart *o;
786
787    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
788    o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
789    o->contained = eina_inlist_append_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
790 }
791
792 void
793 evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *other)
794 {
795    Evas_Object_Smart *o;
796
797    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
798    o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
799    o->contained = eina_inlist_prepend_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
800 }
801
802 /* all nice and private */
803 static void
804 evas_object_smart_init(Evas_Object *obj)
805 {
806    /* alloc smart obj, setup methods and default values */
807    obj->object_data = evas_object_smart_new();
808    /* set up default settings for this kind of object */
809    obj->cur.color.r = 255;
810    obj->cur.color.g = 255;
811    obj->cur.color.b = 255;
812    obj->cur.color.a = 255;
813    obj->cur.geometry.x = 0;
814    obj->cur.geometry.y = 0;
815    obj->cur.geometry.w = 0;
816    obj->cur.geometry.h = 0;
817    obj->cur.layer = 0;
818    /* set up object-specific settings */
819    obj->prev = obj->cur;
820    /* set up methods (compulsory) */
821    obj->func = &object_func;
822 }
823
824 static void *
825 evas_object_smart_new(void)
826 {
827    Evas_Object_Smart *o;
828
829    /* alloc obj private data */
830    EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_smart", Evas_Object_Smart, 256, NULL);
831    o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Smart);
832    if (!o) return NULL;
833    EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Smart);
834    o->magic = MAGIC_OBJ_SMART;
835    return o;
836 }
837
838 static void
839 evas_object_smart_free(Evas_Object *obj)
840 {
841    Evas_Object_Smart *o;
842
843    /* frees private object data. very simple here */
844    o = (Evas_Object_Smart *)(obj->object_data);
845    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
846    return;
847    MAGIC_CHECK_END();
848    /* free obj */
849    o->magic = 0;
850    EVAS_MEMPOOL_FREE(_mp_obj, o);
851 }
852
853 static void
854 evas_object_smart_render(Evas_Object *obj __UNUSED__, void *output __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, int x __UNUSED__, int y __UNUSED__)
855 {
856    return;
857 }
858
859 static void
860 evas_object_smart_render_pre(Evas_Object *obj)
861 {
862    if (obj->pre_render_done) return;
863    if ((obj->cur.map != obj->prev.map) ||
864        (obj->cur.usemap != obj->prev.usemap))
865      {
866         evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
867         goto done;
868      }
869 done:
870    obj->pre_render_done = 1;
871 }
872
873 static void
874 evas_object_smart_render_post(Evas_Object *obj)
875 {
876    obj->prev = obj->cur;
877 }
878
879 static unsigned int evas_object_smart_id_get(Evas_Object *obj)
880 {
881    Evas_Object_Smart *o;
882
883    o = (Evas_Object_Smart *)(obj->object_data);
884    if (!o) return 0;
885    return MAGIC_OBJ_SMART;
886 }
887
888 static unsigned int evas_object_smart_visual_id_get(Evas_Object *obj)
889 {
890    Evas_Object_Smart *o;
891
892    o = (Evas_Object_Smart *)(obj->object_data);
893    if (!o) return 0;
894    return MAGIC_OBJ_CONTAINER;
895 }
896
897 static void *evas_object_smart_engine_data_get(Evas_Object *obj)
898 {
899    Evas_Object_Smart *o;
900
901    o = (Evas_Object_Smart *)(obj->object_data);
902    if (!o) return NULL;
903    return o->engine_data;
904 }