cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=0fd144550877ff0a6f413c025685b7e7d63e6535

commit 0fd144550877ff0a6f413c025685b7e7d63e6535
Author: Jee-Yong Um <con...@gmail.com>
Date:   Tue Nov 1 10:59:09 2016 -0700

    edje.object: implement Efl.Observer interface
    
    Summary:
    To remove duplicated lines to handle edje class (color, text, size),
    observer interface is implemented to Edje.Object.
    
    Reviewers: jpeg, cedric
    
    Reviewed By: cedric
    
    Subscribers: bu5hm4n, cedric
    
    Differential Revision: https://phab.enlightenment.org/D4359
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 src/Makefile_Efl.am                      |   3 +
 src/lib/edje/edje_load.c                 |   8 +-
 src/lib/edje/edje_main.c                 |  45 +++-
 src/lib/edje/edje_object.eo              |   4 +-
 src/lib/edje/edje_private.h              |  19 +-
 src/lib/edje/edje_smart.c                |  50 ++++
 src/lib/edje/edje_text.c                 |   8 +-
 src/lib/edje/edje_textblock_styles.c     |   6 +-
 src/lib/edje/edje_util.c                 | 441 ++++---------------------------
 src/lib/efl/Efl.h                        |   3 +
 src/lib/efl/interfaces/efl_observable.eo |  63 +++++
 src/lib/efl/interfaces/efl_observer.c    | 259 ++++++++++++++++++
 src/lib/efl/interfaces/efl_observer.eo   |  15 ++
 src/lib/efl/interfaces/efl_types.eot     |   6 +
 14 files changed, 514 insertions(+), 416 deletions(-)

diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am
index f1ef8f6..e64a588 100644
--- a/src/Makefile_Efl.am
+++ b/src/Makefile_Efl.am
@@ -50,6 +50,8 @@ efl_eolian_files = \
       lib/efl/interfaces/efl_io_writer.eo \
       lib/efl/interfaces/efl_io_buffer.eo \
       lib/efl/interfaces/efl_io_queue.eo \
+      lib/efl/interfaces/efl_observer.eo \
+      lib/efl/interfaces/efl_observable.eo \
       $(efl_eolian_legacy_files) \
       $(NULL)
 
@@ -99,6 +101,7 @@ lib/efl/interfaces/efl_io_sizer.c \
 lib/efl/interfaces/efl_io_writer.c \
 lib/efl/interfaces/efl_io_buffer.c \
 lib/efl/interfaces/efl_io_queue.c \
+lib/efl/interfaces/efl_observer.c \
 $(NULL)
 
 lib_efl_libefl_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl 
-I$(top_srcdir)/src/lib/efl @EFL_CFLAGS@ -DEFL_GFX_FILTER_BETA
diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c
index 9df4314..3751fae 100644
--- a/src/lib/edje/edje_load.c
+++ b/src/lib/edje/edje_load.c
@@ -637,7 +637,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const 
Eina_File *file, const ch
 
                   /* Register any color classes in this parts descriptions. */
                   if ((ep->default_desc) && (ep->default_desc->color_class))
-                    _edje_color_class_member_add(ed, 
ep->default_desc->color_class);
+                    efl_observable_observer_add(_edje_color_class_member, 
ep->default_desc->color_class, obj);
 
                   for (k = 0; k < ep->other.desc_count; k++)
                     {
@@ -646,7 +646,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const 
Eina_File *file, const ch
                        desc = ep->other.desc[k];
 
                        if (desc->color_class)
-                         _edje_color_class_member_add(ed, desc->color_class);
+                         efl_observable_observer_add(_edje_color_class_member, 
desc->color_class, obj);
                     }
                }
              /* sizeclass stuff */
@@ -659,7 +659,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const 
Eina_File *file, const ch
 
                   /* Register any size classes in this parts descriptions. */
                   if ((ep->default_desc) && (ep->default_desc->size_class))
-                    _edje_size_class_member_add(ed, 
ep->default_desc->size_class);
+                    efl_observable_observer_add(_edje_size_class_member, 
ep->default_desc->size_class, obj);
 
                   for (k = 0; k < ep->other.desc_count; k++)
                     {
@@ -668,7 +668,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const 
Eina_File *file, const ch
                        desc = ep->other.desc[k];
 
                        if (desc->size_class)
-                         _edje_size_class_member_add(ed, desc->size_class);
+                         efl_observable_observer_add(_edje_size_class_member, 
desc->size_class, obj);
                     }
                }
              /* build real parts */
diff --git a/src/lib/edje/edje_main.c b/src/lib/edje/edje_main.c
index 7bb4774..f6d8462 100644
--- a/src/lib/edje/edje_main.c
+++ b/src/lib/edje/edje_main.c
@@ -90,6 +90,7 @@ edje_init(void)
    _edje_message_init();
    _edje_multisense_init();
    edje_signal_init();
+   _edje_class_init();
 
    _edje_real_part_mp = eina_mempool_add("chained_mempool",
                                          "Edje_Real_Part", NULL,
@@ -130,14 +131,13 @@ shutdown_all:
    eina_mempool_del(_edje_real_part_mp);
    _edje_real_part_state_mp = NULL;
    _edje_real_part_mp = NULL;
+   _edje_class_shutdown();
    _edje_message_shutdown();
    _edje_module_shutdown();
    _edje_external_shutdown();
    _edje_box_shutdown();
    _edje_internal_proxy_shutdown();
-   _edje_text_class_members_free();
    _edje_text_class_hash_free();
-   _edje_size_class_members_free();
    _edje_size_class_hash_free();
    _edje_edd_shutdown();
    efreet_shutdown();
@@ -169,7 +169,6 @@ _edje_shutdown_core(void)
                    EINA_LOG_STATE_SHUTDOWN);
 
    _edje_file_cache_shutdown();
-   _edje_color_class_members_free();
    _edje_color_class_hash_free();
 
    eina_stringshare_del(_edje_cache_path);
@@ -182,15 +181,14 @@ _edje_shutdown_core(void)
    _edje_real_part_state_mp = NULL;
    _edje_real_part_mp = NULL;
 
+   _edje_class_shutdown();
    edje_signal_shutdown();
    _edje_multisense_shutdown();
    _edje_message_shutdown();
    _edje_module_shutdown();
    _edje_external_shutdown();
    _edje_box_shutdown();
-   _edje_text_class_members_free();
    _edje_text_class_hash_free();
-   _edje_size_class_members_free();
    _edje_size_class_hash_free();
    _edje_edd_shutdown();
 
@@ -250,6 +248,37 @@ edje_shutdown(void)
 
 /* Private Routines */
 void
+_edje_class_init(void)
+{
+   if (!_edje_color_class_member)
+     _edje_color_class_member = efl_add(EFL_OBSERVABLE_CLASS, NULL);
+   if (!_edje_text_class_member)
+     _edje_text_class_member = efl_add(EFL_OBSERVABLE_CLASS, NULL);
+   if (!_edje_size_class_member)
+     _edje_size_class_member = efl_add(EFL_OBSERVABLE_CLASS, NULL);
+}
+
+void
+_edje_class_shutdown(void)
+{
+   if (_edje_color_class_member)
+     {
+        efl_del(_edje_color_class_member);
+        _edje_color_class_member = NULL;
+     }
+   if (_edje_text_class_member)
+     {
+        efl_del(_edje_text_class_member);
+        _edje_text_class_member = NULL;
+     }
+   if (_edje_size_class_member)
+     {
+        efl_del(_edje_size_class_member);
+        _edje_size_class_member = NULL;
+     }
+}
+
+void
 _edje_del(Edje *ed)
 {
    Edje_Text_Insert_Filter_Callback *cb;
@@ -286,9 +315,9 @@ _edje_del(Edje *ed)
         free(cb);
      }
 
-   _edje_color_class_member_clean(ed);
-   _edje_text_class_members_clean(ed);
-   _edje_size_class_members_clean(ed);
+   efl_observable_observer_clean(_edje_color_class_member, ed->obj);
+   efl_observable_observer_clean(_edje_text_class_member, ed->obj);
+   efl_observable_observer_clean(_edje_size_class_member, ed->obj);
 }
 
 void
diff --git a/src/lib/edje/edje_object.eo b/src/lib/edje/edje_object.eo
index 2160275..c05cd0e 100644
--- a/src/lib/edje/edje_object.eo
+++ b/src/lib/edje/edje_object.eo
@@ -1,6 +1,7 @@
 import edje_types;
 
-class Edje.Object (Efl.Canvas.Group.Clipped, Efl.File, Efl.Container, Efl.Part)
+class Edje.Object (Efl.Canvas.Group.Clipped, Efl.File, Efl.Container, Efl.Part,
+                   Efl.Observer)
 {
    legacy_prefix: edje_object;
    eo_prefix: edje_obj;
@@ -2084,6 +2085,7 @@ class Edje.Object (Efl.Canvas.Group.Clipped, Efl.File, 
Efl.Container, Efl.Part)
       Efl.Container.content_remove;
       Efl.Container.content_part_name.get;
       Efl.Part.part;
+      Efl.Observer.update;
    }
    events {
       recalc; [[Edje re-calculated the object.]]
diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h
index 4b4b46a..3e610d2 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -2496,26 +2496,14 @@ Edje_Real_Part   *_edje_real_part_get(const Edje *ed, 
const char *part);
 Edje_Real_Part   *_edje_real_part_recursive_get(Edje **ed, const char *part);
 Edje_Color_Class *_edje_color_class_find(const Edje *ed, const char 
*color_class);
 Edje_Color_Class *_edje_color_class_recursive_find(const Edje *ed, const char 
*color_class);
-void              _edje_color_class_member_add(Edje *ed, const char 
*color_class);
-void              _edje_color_class_member_del(Edje *ed, const char 
*color_class);
-void              _edje_color_class_member_clean(Edje *ed);
 void              _edje_color_class_on_del(Edje *ed, Edje_Part *ep);
-void              _edje_color_class_members_free(void);
 void              _edje_color_class_hash_free(void);
 
 const char       * _edje_find_alias(Eina_Hash *aliased, char *src, int 
*length);
 Edje_Text_Class  *_edje_text_class_find(Edje *ed, const char *text_class);
-void              _edje_text_class_member_add(Edje *ed, const char 
*text_class);
-void              _edje_text_class_member_del(Edje *ed, const char 
*text_class);
-void              _edje_text_class_members_free(void);
 void              _edje_text_class_hash_free(void);
-void              _edje_text_class_members_clean(Edje *ed);
 Edje_Size_Class  *_edje_size_class_find(Edje *ed, const char *size_class);
-void              _edje_size_class_member_add(Edje *ed, const char 
*size_class);
-void              _edje_size_class_member_del(Edje *ed, const char 
*size_class);
-void              _edje_size_class_members_free(void);
 void              _edje_size_class_hash_free(void);
-void              _edje_size_class_members_clean(Edje *ed);
 Edje             *_edje_fetch(const Evas_Object *obj) EINA_PURE;
 int               _edje_util_freeze(Edje *ed);
 int               _edje_util_thaw(Edje *ed);
@@ -2895,6 +2883,13 @@ void _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int 
flags, Edje_Calc_Params
 void _edje_user_definition_remove(Edje_User_Defined *eud, Evas_Object *child);
 void _edje_user_definition_free(Edje_User_Defined *eud);
 
+extern Efl_Observable *_edje_color_class_member;
+extern Efl_Observable *_edje_text_class_member;
+extern Efl_Observable *_edje_size_class_member;
+
+void _edje_class_init(void);
+void _edje_class_shutdown(void);
+
 void _scale_set(Eo *obj, void *_pd, va_list *list);
 void _scale_get(Eo *obj, void *_pd, va_list *list);
 void _base_scale_get(Eo *obj, void *_pd, va_list *list);
diff --git a/src/lib/edje/edje_smart.c b/src/lib/edje/edje_smart.c
index 7e8105a..b769f59 100644
--- a/src/lib/edje/edje_smart.c
+++ b/src/lib/edje/edje_smart.c
@@ -490,4 +490,54 @@ _edje_object_efl_canvas_object_paragraph_direction_set(Eo 
*obj, Edje *ed, Evas_B
    efl_canvas_group_need_recalculate_set(obj, 1);
 }
 
+EOLIAN static void
+_edje_object_efl_observer_update(Eo *obj EINA_UNUSED, Edje *ed, Efl_Object 
*obs, const char *key, void *data)
+{
+   if (!obs) return;
+
+   ed->dirty = EINA_TRUE;
+   ed->recalc_call = EINA_TRUE;
+
+   if ((obs == _edje_color_class_member) || (obs == _edje_size_class_member))
+     {
+#ifdef EDJE_CALC_CACHE
+        ed->all_part_change = EINA_TRUE;
+#endif
+     }
+   else if (obs == _edje_text_class_member)
+     {
+        _edje_textblock_styles_cache_free(ed, key);
+        _edje_textblock_style_all_update(ed);
+#ifdef EDJE_CALC_CACHE
+        ed->text_part_change = EINA_TRUE;
+#endif
+     }
+
+   _edje_recalc(ed);
+
+   if (obs == _edje_color_class_member)
+     {
+        if (data)
+          _edje_emit(ed, (const char *)data, key);
+
+        if ((ed->file) && (ed->file->color_tree))
+          {
+             Edje_Color_Tree_Node *ctn = NULL;
+             Eina_List *l = NULL;
+             char *name;
+
+             EINA_LIST_FOREACH(ed->file->color_tree, l, ctn)
+               {
+                  if (!strcmp(ctn->name, key) && (ctn->color_classes))
+                    {
+                       EINA_LIST_FOREACH(ctn->color_classes, l, name)
+                         
efl_observable_observers_update(_edje_color_class_member, name, data);
+
+                       break;
+                    }
+               }
+          }
+     }
+}
+
 #include "edje_object.eo.c"
diff --git a/src/lib/edje/edje_text.c b/src/lib/edje/edje_text.c
index f622714..517cdab 100644
--- a/src/lib/edje/edje_text.c
+++ b/src/lib/edje/edje_text.c
@@ -82,14 +82,14 @@ _edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep)
    /* if text class exists for this part, add the edje to the tc member list */
    desc = (Edje_Part_Description_Text *)pt->default_desc;
    if ((pt->default_desc) && (desc->text.text_class))
-     _edje_text_class_member_add(ed, desc->text.text_class);
+     efl_observable_observer_add(_edje_text_class_member, 
desc->text.text_class, ed->obj);
 
    /* If any other classes exist add them */
    for (i = 0; i < pt->other.desc_count; ++i)
      {
         desc = (Edje_Part_Description_Text *)pt->other.desc[i];
         if ((desc) && (desc->text.text_class))
-          _edje_text_class_member_add(ed, desc->text.text_class);
+          efl_observable_observer_add(_edje_text_class_member, 
desc->text.text_class, ed->obj);
      }
 }
 
@@ -105,13 +105,13 @@ _edje_text_part_on_del(Edje *ed, Edje_Part *pt)
 
    desc = (Edje_Part_Description_Text *)pt->default_desc;
    if ((pt->default_desc) && (desc->text.text_class))
-     _edje_text_class_member_del(ed, desc->text.text_class);
+     efl_observable_observer_del(_edje_text_class_member, 
desc->text.text_class, ed->obj);
 
    for (i = 0; i < pt->other.desc_count; ++i)
      {
         desc = (Edje_Part_Description_Text *)pt->other.desc[i];
         if (desc->text.text_class)
-          _edje_text_class_member_del(ed, desc->text.text_class);
+          efl_observable_observer_del(_edje_text_class_member, 
desc->text.text_class, ed->obj);
      }
 }
 
diff --git a/src/lib/edje/edje_textblock_styles.c 
b/src/lib/edje/edje_textblock_styles.c
index 9b9d921..e4d1851 100644
--- a/src/lib/edje/edje_textblock_styles.c
+++ b/src/lib/edje/edje_textblock_styles.c
@@ -310,7 +310,7 @@ _edje_textblock_style_member_add(Edje *ed, Edje_Style *stl)
      {
         if (tag->text_class)
           {
-             _edje_text_class_member_add(ed, tag->text_class);
+             efl_observable_observer_add(_edje_text_class_member, 
tag->text_class, ed->obj);
 
              /* Newly added text_class member should be updated
                 according to the latest text_class's status. */
@@ -377,7 +377,7 @@ _edje_textblock_styles_del(Edje *ed, Edje_Part *pt)
         EINA_LIST_FOREACH(stl->tags, l, tag)
           {
              if (tag->text_class)
-               _edje_text_class_member_del(ed, tag->text_class);
+               efl_observable_observer_del(_edje_text_class_member, 
tag->text_class, ed->obj);
           }
      }
 
@@ -403,7 +403,7 @@ _edje_textblock_styles_del(Edje *ed, Edje_Part *pt)
              EINA_LIST_FOREACH(stl->tags, l, tag)
                {
                   if (tag->text_class)
-                    _edje_text_class_member_del(ed, tag->text_class);
+                    efl_observable_observer_del(_edje_text_class_member, 
tag->text_class, ed->obj);
                }
           }
      }
diff --git a/src/lib/edje/edje_util.c b/src/lib/edje/edje_util.c
index 4432821..83c37d5 100644
--- a/src/lib/edje/edje_util.c
+++ b/src/lib/edje/edje_util.c
@@ -17,13 +17,12 @@ struct _Edje_Box_Layout
 };
 
 static Eina_Hash *_edje_color_class_hash = NULL;
-static Eina_Hash *_edje_color_class_member_hash = NULL;
-
 static Eina_Hash *_edje_text_class_hash = NULL;
-static Eina_Hash *_edje_text_class_member_hash = NULL;
-
 static Eina_Hash *_edje_size_class_hash = NULL;
-static Eina_Hash *_edje_size_class_member_hash = NULL;
+
+Efl_Observable *_edje_color_class_member = NULL;
+Efl_Observable *_edje_text_class_member = NULL;
+Efl_Observable *_edje_size_class_member = NULL;
 
 static Eina_Rbtree *_edje_box_layout_registry = NULL;
 
@@ -156,116 +155,6 @@ _edje_user_def_del_cb(void *data, Evas *e EINA_UNUSED, 
Evas_Object *child EINA_U
    _edje_user_definition_free(eud);
 }
 
-static void
-_edje_class_member_add(Edje *ed, Eina_Hash **ghash, const char *class)
-{
-   Eina_Hash *members;
-   Edje_Refcount *er;
-
-   if ((!ed) || (!ghash) || (!class)) return;
-
-   if (!*ghash) *ghash = eina_hash_string_superfast_new(NULL);
-
-   members = eina_hash_find(*ghash, class);
-   if (!members)
-     {
-        members = eina_hash_pointer_new(NULL);
-        eina_hash_add(*ghash, class, members);
-     }
-
-   er = eina_hash_find(members, &ed);
-   if (!er)
-     {
-        er = calloc(1, sizeof (Edje_Refcount));
-        er->ed = ed;
-        EINA_REFCOUNT_INIT(er);
-
-        eina_hash_direct_add(members, &er->ed, er);
-     }
-   else
-     {
-        EINA_REFCOUNT_REF(er);
-     }
-}
-
-static void
-_edje_class_member_del(Edje *ed, Eina_Hash **ghash, const char *class)
-{
-   Edje_Refcount *lookup;
-   Eina_Hash *members;
-
-   if ((!ed) || (!ghash) || (!class)) return;
-   members = eina_hash_find(*ghash, class);
-   if (!members) return;
-
-   lookup = eina_hash_find(members, &ed);
-   if (!lookup) return;
-
-   EINA_REFCOUNT_UNREF(lookup)
-   {
-      eina_hash_del(members, &lookup->ed, lookup);
-      free(lookup);
-
-      if (eina_hash_population(members) == 0)
-        {
-           eina_hash_del(*ghash, class, members);
-           eina_hash_free(members);
-        }
-   }
-}
-
-static void
-_edje_class_members_free(Eina_Hash **ghash)
-{
-   Eina_Iterator *it;
-   Eina_Hash *members;
-
-   if (!ghash || !*ghash) return;
-
-   it = eina_hash_iterator_data_new(*ghash);
-   EINA_ITERATOR_FOREACH(it, members)
-     {
-        Eina_Iterator *it2;
-        Edje_Refcount *er;
-
-        it2 = eina_hash_iterator_data_new(members);
-        EINA_ITERATOR_FOREACH(it2, er)
-          free(er);
-        eina_iterator_free(it2);
-
-        eina_hash_free(members);
-     }
-   eina_iterator_free(it);
-
-   eina_hash_free(*ghash);
-   *ghash = NULL;
-}
-
-static void
-_edje_class_members_clean(Edje *ed, Eina_Hash *ghash)
-{
-   Eina_Iterator *it;
-   Eina_Hash *members;
-
-   if (!ed || !ghash) return;
-
-   it = eina_hash_iterator_data_new(ghash);
-   EINA_ITERATOR_FOREACH(it, members)
-     {
-        Edje_Refcount *lookup;
-
-        lookup = eina_hash_find(members, &ed);
-        if (!lookup) continue;
-
-        EINA_REFCOUNT_UNREF(lookup)
-        {
-           eina_hash_del(members, &lookup->ed, lookup);
-           free(lookup);
-        }
-     }
-   eina_iterator_free(it);
-}
-
 /************************** API Routines **************************/
 
 #define FASTFREEZE 1
@@ -749,41 +638,6 @@ _edje_color_class_get_internal(Edje_Color_Class *cc, 
Edje_Color_Class_Mode mode,
      }
 }
 
-static void
-_edje_color_class_apply(const char *color_class, const char *parent)
-{
-   Eina_Hash *members;
-   Eina_Iterator *it;
-   Edje_Refcount *er;
-   Edje_Color_Tree_Node *ctn;
-   Eina_List *l, *ll;
-   char *name;
-
-   members = eina_hash_find(_edje_color_class_member_hash, color_class);
-   if (!members) return;
-   it = eina_hash_iterator_data_new(members);
-   EINA_ITERATOR_FOREACH(it, er)
-     {
-        er->ed->dirty = EINA_TRUE;
-        er->ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-        er->ed->all_part_change = EINA_TRUE;
-#endif
-        _edje_recalc(er->ed);
-        _edje_emit(er->ed, "color_class,set", parent);
-
-        if (!er->ed->file) continue;
-
-        EINA_LIST_FOREACH(er->ed->file->color_tree, l, ctn)
-          {
-             if ((!strcmp(ctn->name, color_class)) && (ctn->color_classes))
-                EINA_LIST_FOREACH(ctn->color_classes, ll, name)
-                  _edje_color_class_apply(name, parent);
-          }
-     }
-   eina_iterator_free(it);
-}
-
 EAPI Eina_Bool
 edje_color_class_set(const char *color_class, int r, int g, int b, int a, int 
r2, int g2, int b2, int a2, int r3, int g3, int b3, int a3)
 {
@@ -809,7 +663,7 @@ _edje_object_global_color_class_set(Efl_Class *klass 
EINA_UNUSED, void *pd EINA_
    int_ret = _edje_color_class_set_internal(_edje_color_class_hash, 
color_class, mode, r, g, b, a, &need_update);
 
    if ((int_ret) && (need_update))
-     _edje_color_class_apply(color_class, color_class);
+     efl_observable_observers_update(_edje_color_class_member, color_class, 
"color_class,set");
 
    return int_ret;
 }
@@ -844,9 +698,6 @@ EAPI void
 edje_color_class_del(const char *color_class)
 {
    Edje_Color_Class *cc;
-   Eina_Hash *members;
-   Eina_Iterator *it;
-   Edje_Refcount *er;
 
    if (!color_class) return;
 
@@ -857,20 +708,7 @@ edje_color_class_del(const char *color_class)
    eina_stringshare_del(cc->name);
    free(cc);
 
-   members = eina_hash_find(_edje_color_class_member_hash, color_class);
-   if (!members) return;
-   it = eina_hash_iterator_data_new(members);
-   EINA_ITERATOR_FOREACH(it, er)
-     {
-        er->ed->dirty = EINA_TRUE;
-        er->ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-        er->ed->all_part_change = EINA_TRUE;
-#endif
-        _edje_recalc(er->ed);
-        _edje_emit(er->ed, "color_class,del", color_class);
-     }
-   eina_iterator_free(it);
+   efl_observable_observers_update(_edje_color_class_member, color_class, 
"color_class,del");
 }
 
 Eina_List *
@@ -900,42 +738,40 @@ static Eina_Bool
 _edje_color_class_active_iterator_next(Eina_Iterator *it, void **data)
 {
    Edje_Active_Color_Class_Iterator *et = (void *)it;
-   Eina_Hash_Tuple *tuple = NULL;
-   Edje_Refcount *er = NULL;
-   Eina_Iterator *ith;
+   Efl_Observable_Tuple *tuple = NULL;
+   Efl_Observer *o;
+   Edje *ed;
    Edje_Color_Class *cc = NULL;
-   Eina_Bool r = EINA_FALSE;
 
    if (!eina_iterator_next(et->classes, (void **)&tuple)) return EINA_FALSE;
    if (!tuple) return EINA_FALSE;
 
-   ith = eina_hash_iterator_data_new(tuple->data);
-   if (!eina_iterator_next(ith, (void **)&er)) goto on_error;
+   if (!eina_iterator_next(tuple->data, (void **)&o)) return EINA_FALSE;
+
+   ed = efl_data_scope_get(o, EDJE_OBJECT_CLASS);
+   if (!ed) return EINA_FALSE;
 
    /*
       We actually need to ask on an object to get the correct value.
       It is being assumed that the color key are the same for all object here.
       This can some times not be the case, but for now we should be fine.
     */
-   cc = _edje_color_class_find(er->ed, tuple->key);
-   if (!cc) goto on_error;
+   cc = _edje_color_class_find(ed, tuple->key);
+   if (!cc) return EINA_FALSE;
    et->cc = *cc;
 
    /*
       Any of the Edje object referenced should have a file with a valid
       description for this color class. Let's bet on that for now.
     */
-   if (er->ed->file)
-     cc = eina_hash_find(er->ed->file->color_hash, tuple->key);
-   if (!cc) goto on_error;
+   if (ed->file)
+     cc = eina_hash_find(ed->file->color_hash, tuple->key);
+   if (!cc) return EINA_FALSE;
    et->cc.desc = cc->desc;
 
    *data = &et->cc;
-   r = EINA_TRUE;
 
- on_error:
-   eina_iterator_free(ith);
-   return r;
+   return EINA_TRUE;
 }
 
 static void *
@@ -959,12 +795,12 @@ edje_color_class_active_iterator_new(void)
 {
    Edje_Active_Color_Class_Iterator *it;
 
-   if (!_edje_color_class_member_hash) return NULL;
+   if (!_edje_color_class_member) return NULL;
    it = calloc(1, sizeof (Edje_Active_Color_Class_Iterator));
    if (!it) return NULL;
 
    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
-   it->classes = eina_hash_iterator_tuple_new(_edje_color_class_member_hash);
+   it->classes = efl_observable_iterator_tuple_new(_edje_color_class_member);
 
    it->iterator.version = EINA_ITERATOR_VERSION;
    it->iterator.next = _edje_color_class_active_iterator_next;
@@ -1218,9 +1054,6 @@ on_error:
 EAPI Eina_Bool
 edje_text_class_set(const char *text_class, const char *font, Evas_Font_Size 
size)
 {
-   Eina_Hash *members;
-   Eina_Iterator *it;
-   Edje_Refcount *er;
    Edje_Text_Class *tc;
 
    if (!text_class) return EINA_FALSE;
@@ -1257,20 +1090,8 @@ edje_text_class_set(const char *text_class, const char 
*font, Evas_Font_Size siz
      }
 
    /* Tell all members of the text class to recalc */
-   members = eina_hash_find(_edje_text_class_member_hash, text_class);
-   it = eina_hash_iterator_data_new(members);
-   EINA_ITERATOR_FOREACH(it, er)
-     {
-        er->ed->dirty = EINA_TRUE;
-        er->ed->recalc_call = EINA_TRUE;
-        _edje_textblock_styles_cache_free(er->ed, text_class);
-        _edje_textblock_style_all_update(er->ed);
-#ifdef EDJE_CALC_CACHE
-        er->ed->text_part_change = EINA_TRUE;
-#endif
-        _edje_recalc(er->ed);
-     }
-   eina_iterator_free(it);
+   efl_observable_observers_update(_edje_text_class_member, text_class, NULL);
+
    return EINA_TRUE;
 }
 
@@ -1302,9 +1123,6 @@ EAPI void
 edje_text_class_del(const char *text_class)
 {
    Edje_Text_Class *tc;
-   Eina_Hash *members;
-   Eina_Iterator *it;
-   Edje_Refcount *er;
 
    if (!text_class) return;
 
@@ -1316,19 +1134,7 @@ edje_text_class_del(const char *text_class)
    eina_stringshare_del(tc->font);
    free(tc);
 
-   members = eina_hash_find(_edje_text_class_member_hash, text_class);
-   it = eina_hash_iterator_data_new(members);
-   EINA_ITERATOR_FOREACH(it, er)
-     {
-        er->ed->dirty = EINA_TRUE;
-        _edje_textblock_styles_cache_free(er->ed, text_class);
-        _edje_textblock_style_all_update(er->ed);
-#ifdef EDJE_CALC_CACHE
-        er->ed->text_part_change = EINA_TRUE;
-#endif
-        _edje_recalc(er->ed);
-     }
-   eina_iterator_free(it);
+   efl_observable_observers_update(_edje_text_class_member, text_class, NULL);
 }
 
 Eina_List *
@@ -1355,33 +1161,31 @@ static Eina_Bool
 _edje_text_class_active_iterator_next(Eina_Iterator *it, void **data)
 {
    Edje_Active_Text_Class_Iterator *et = (void *)it;
-   Eina_Hash_Tuple *tuple = NULL;
-   Edje_Refcount *er = NULL;
-   Eina_Iterator *ith;
+   Efl_Observable_Tuple *tuple = NULL;
+   Efl_Observer *o;
+   Edje *ed;
    Edje_Text_Class *tc;
-   Eina_Bool r = EINA_FALSE;
 
    if (!eina_iterator_next(et->classes, (void **)&tuple)) return EINA_FALSE;
    if (!tuple) return EINA_FALSE;
 
-   ith = eina_hash_iterator_data_new(tuple->data);
-   if (!eina_iterator_next(ith, (void **)&er)) goto on_error;
+   if (!eina_iterator_next(tuple->data, (void **)&o)) return EINA_FALSE;
+
+   ed = efl_data_scope_get(o, EDJE_OBJECT_CLASS);
+   if (!ed) return EINA_FALSE;
 
    /*
       We actually need to ask on an object to get the correct value.
       It is being assumed that the size key are the same for all object here.
       This can some times not be the case, but for now we should be fine.
     */
-   tc = _edje_text_class_find(er->ed, tuple->key);
-   if (!tc) goto on_error;
+   tc = _edje_text_class_find(ed, tuple->key);
+   if (!tc) return EINA_FALSE;
    et->tc = *tc;
 
    *data = &et->tc;
-   r = EINA_TRUE;
 
- on_error:
-   eina_iterator_free(ith);
-   return r;
+   return EINA_TRUE;
 }
 
 static void *
@@ -1405,12 +1209,12 @@ edje_text_class_active_iterator_new(void)
 {
    Edje_Active_Text_Class_Iterator *it;
 
-   if (!_edje_text_class_member_hash) return NULL;
+   if (!_edje_text_class_member) return NULL;
    it = calloc(1, sizeof (Edje_Active_Text_Class_Iterator));
    if (!it) return NULL;
 
    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
-   it->classes = eina_hash_iterator_tuple_new(_edje_text_class_member_hash);
+   it->classes = efl_observable_iterator_tuple_new(_edje_text_class_member);
 
    it->iterator.version = EINA_ITERATOR_VERSION;
    it->iterator.next = _edje_text_class_active_iterator_next;
@@ -1489,14 +1293,7 @@ _edje_object_text_class_set(Eo *obj EINA_UNUSED, Edje 
*ed, const char *text_clas
                                      text_class, font, size);
      }
 
-   ed->dirty = EINA_TRUE;
-   ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-   ed->text_part_change = EINA_TRUE;
-#endif
-   _edje_textblock_styles_cache_free(ed, text_class);
-   _edje_textblock_style_all_update(ed);
-   _edje_recalc(ed);
+   efl_observer_update(obj, _edje_text_class_member, text_class, NULL);
 
    return EINA_TRUE;
 }
@@ -1543,14 +1340,7 @@ _edje_object_text_class_del(Eo *obj EINA_UNUSED, Edje 
*ed, const char *text_clas
           edje_object_text_class_del(rp->typedata.swallow->swallowed_object, 
text_class);
      }
 
-   ed->dirty = EINA_TRUE;
-   ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-   ed->text_part_change = EINA_TRUE;
-#endif
-   _edje_textblock_styles_cache_free(ed, text_class);
-   _edje_textblock_style_all_update(ed);
-   _edje_recalc(ed);
+   efl_observer_update(obj, _edje_text_class_member, text_class, NULL);
 }
 
 typedef struct _Edje_File_Text_Class_Iterator Edje_File_Text_Class_Iterator;
@@ -1630,9 +1420,6 @@ on_error:
 EAPI Eina_Bool
 edje_size_class_set(const char *size_class, Evas_Coord minw, Evas_Coord minh, 
Evas_Coord maxw, Evas_Coord maxh)
 {
-   Eina_Hash *members;
-   Eina_Iterator *it;
-   Edje_Refcount *er;
    Edje_Size_Class *sc;
 
    if (!size_class) return EINA_FALSE;
@@ -1672,18 +1459,8 @@ edje_size_class_set(const char *size_class, Evas_Coord 
minw, Evas_Coord minh, Ev
      }
 
    /* Tell all members of the size class to recalc */
-   members = eina_hash_find(_edje_size_class_member_hash, size_class);
-   it = eina_hash_iterator_data_new(members);
-   EINA_ITERATOR_FOREACH(it, er)
-     {
-        er->ed->dirty = EINA_TRUE;
-        er->ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-        er->ed->all_part_change = EINA_TRUE;
-#endif
-        _edje_recalc(er->ed);
-     }
-   eina_iterator_free(it);
+   efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
+
    return EINA_TRUE;
 }
 
@@ -1719,9 +1496,6 @@ EAPI void
 edje_size_class_del(const char *size_class)
 {
    Edje_Size_Class *sc;
-   Eina_Hash *members;
-   Eina_Iterator *it;
-   Edje_Refcount *er;
 
    if (!size_class) return;
 
@@ -1732,18 +1506,7 @@ edje_size_class_del(const char *size_class)
    eina_stringshare_del(sc->name);
    free(sc);
 
-   members = eina_hash_find(_edje_size_class_member_hash, size_class);
-   it = eina_hash_iterator_data_new(members);
-   EINA_ITERATOR_FOREACH(it, er)
-     {
-        er->ed->dirty = EINA_TRUE;
-        er->ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-        er->ed->all_part_change = EINA_TRUE;
-#endif
-        _edje_recalc(er->ed);
-     }
-   eina_iterator_free(it);
+   efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
 }
 
 Eina_List *
@@ -1770,33 +1533,31 @@ static Eina_Bool
 _edje_size_class_active_iterator_next(Eina_Iterator *it, void **data)
 {
    Edje_Active_Size_Class_Iterator *et = (void *)it;
-   Eina_Hash_Tuple *tuple = NULL;
-   Edje_Refcount *er = NULL;
-   Eina_Iterator *ith;
+   Efl_Observable_Tuple *tuple = NULL;
+   Efl_Observer *o;
+   Edje *ed;
    Edje_Size_Class *sc;
-   Eina_Bool r = EINA_FALSE;
 
    if (!eina_iterator_next(et->classes, (void **)&tuple)) return EINA_FALSE;
    if (!tuple) return EINA_FALSE;
 
-   ith = eina_hash_iterator_data_new(tuple->data);
-   if (!eina_iterator_next(ith, (void **)&er)) goto on_error;
+   if (!eina_iterator_next(tuple->data, (void **)&o)) return EINA_FALSE;
+
+   ed = efl_data_scope_get(o, EDJE_OBJECT_CLASS);
+   if (!ed) return EINA_FALSE;
 
    /*
       We actually need to ask on an object to get the correct value.
       It is being assumed that the size key are the same for all object here.
       This can some times not be the case, but for now we should be fine.
     */
-   sc = _edje_size_class_find(er->ed, tuple->key);
-   if (!sc) goto on_error;
+   sc = _edje_size_class_find(ed, tuple->key);
+   if (!sc) return EINA_FALSE;
    et->sc = *sc;
 
    *data = &et->sc;
-   r = EINA_TRUE;
 
- on_error:
-   eina_iterator_free(ith);
-   return r;
+   return EINA_TRUE;
 }
 
 static void *
@@ -1820,12 +1581,12 @@ edje_size_class_active_iterator_new(void)
 {
    Edje_Active_Size_Class_Iterator *it;
 
-   if (!_edje_size_class_member_hash) return NULL;
+   if (!_edje_size_class_member) return NULL;
    it = calloc(1, sizeof (Edje_Active_Size_Class_Iterator));
    if (!it) return NULL;
 
    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
-   it->classes = eina_hash_iterator_tuple_new(_edje_size_class_member_hash);
+   it->classes = efl_observable_iterator_tuple_new(_edje_size_class_member);
 
    it->iterator.version = EINA_ITERATOR_VERSION;
    it->iterator.next = _edje_size_class_active_iterator_next;
@@ -1902,12 +1663,7 @@ _edje_object_size_class_set(Eo *obj EINA_UNUSED, Edje 
*ed, const char *size_clas
                                      size_class, minw, minh, maxw, maxh);
      }
 
-   ed->dirty = EINA_TRUE;
-   ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-   ed->all_part_change = EINA_TRUE;
-#endif
-   _edje_recalc(ed);
+   efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
 
    return EINA_TRUE;
 }
@@ -1958,12 +1714,7 @@ _edje_object_size_class_del(Eo *obj EINA_UNUSED, Edje 
*ed, const char *size_clas
           edje_object_size_class_del(rp->typedata.swallow->swallowed_object, 
size_class);
      }
 
-   ed->dirty = EINA_TRUE;
-   ed->recalc_call = EINA_TRUE;
-#ifdef EDJE_CALC_CACHE
-   ed->all_part_change = EINA_TRUE;
-#endif
-   _edje_recalc(ed);
+   efl_observable_observers_update(_edje_size_class_member, size_class, NULL);
 }
 
 typedef struct _Edje_File_Size_Class_Iterator Edje_File_Size_Class_Iterator;
@@ -6138,32 +5889,6 @@ _edje_color_class_recursive_find(const Edje *ed, const 
char *color_class)
    return NULL;
 }
 
-void
-_edje_color_class_member_add(Edje *ed, const char *color_class)
-{
-   _edje_class_member_add(ed, &_edje_color_class_member_hash, color_class);
-}
-
-void
-_edje_color_class_member_del(Edje *ed, const char *color_class)
-{
-   if ((!ed) || (!color_class)) return;
-
-   _edje_class_member_del(ed, &_edje_color_class_member_hash, color_class);
-}
-
-void
-_edje_color_class_members_free(void)
-{
-   _edje_class_members_free(&_edje_color_class_member_hash);
-}
-
-void
-_edje_color_class_member_clean(Edje *ed)
-{
-   _edje_class_members_clean(ed, _edje_color_class_member_hash);
-}
-
 static Eina_Bool
 color_class_hash_list_free(const Eina_Hash *hash EINA_UNUSED, const void *key 
EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
 {
@@ -6190,11 +5915,11 @@ _edje_color_class_on_del(Edje *ed, Edje_Part *ep)
    unsigned int i;
 
    if ((ep->default_desc) && (ep->default_desc->color_class))
-     _edje_color_class_member_del(ed, ep->default_desc->color_class);
+     efl_observable_observer_del(_edje_color_class_member, 
ep->default_desc->color_class, ed->obj);
 
    for (i = 0; i < ep->other.desc_count; ++i)
      if (ep->other.desc[i]->color_class)
-       _edje_color_class_member_del(ed, ep->other.desc[i]->color_class);
+       efl_observable_observer_del(_edje_color_class_member, 
ep->other.desc[i]->color_class, ed->obj);
 }
 
 Edje_Text_Class *
@@ -6220,32 +5945,6 @@ _edje_text_class_find(Edje *ed, const char *text_class)
    return NULL;
 }
 
-void
-_edje_text_class_member_add(Edje *ed, const char *text_class)
-{
-   _edje_class_member_add(ed, &_edje_text_class_member_hash, text_class);
-}
-
-void
-_edje_text_class_member_del(Edje *ed, const char *text_class)
-{
-   if ((!ed) || (!text_class)) return;
-
-   _edje_class_member_del(ed, &_edje_text_class_member_hash, text_class);
-}
-
-void
-_edje_text_class_members_free(void)
-{
-   _edje_class_members_free(&_edje_text_class_member_hash);
-}
-
-void
-_edje_text_class_members_clean(Edje *ed)
-{
-   _edje_class_members_clean(ed, _edje_text_class_member_hash);
-}
-
 static Eina_Bool
 text_class_hash_list_free(const Eina_Hash *hash EINA_UNUSED, const void *key 
EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
 {
@@ -6290,32 +5989,6 @@ _edje_size_class_find(Edje *ed, const char *size_class)
    return NULL;
 }
 
-void
-_edje_size_class_member_add(Edje *ed, const char *size_class)
-{
-   _edje_class_member_add(ed, &_edje_size_class_member_hash, size_class);
-}
-
-void
-_edje_size_class_member_del(Edje *ed, const char *size_class)
-{
-   if ((!ed) || (!size_class)) return;
-
-   _edje_class_member_del(ed, &_edje_size_class_member_hash, size_class);
-}
-
-void
-_edje_size_class_members_free(void)
-{
-   _edje_class_members_free(&_edje_size_class_member_hash);
-}
-
-void
-_edje_size_class_members_clean(Edje *ed)
-{
-   _edje_class_members_clean(ed, _edje_size_class_member_hash);
-}
-
 static Eina_Bool
 size_class_hash_list_free(const Eina_Hash *hash EINA_UNUSED, const void *key 
EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
 {
diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h
index 142950ae..afcb314 100644
--- a/src/lib/efl/Efl.h
+++ b/src/lib/efl/Efl.h
@@ -53,6 +53,9 @@ typedef struct tm Efl_Time;
 
 #ifdef EFL_BETA_API_SUPPORT
 
+#include "interfaces/efl_observer.eo.h"
+#include "interfaces/efl_observable.eo.h"
+
 #include "interfaces/efl_types.eot.h"
 
 #include <Efl_Model_Common.h>
diff --git a/src/lib/efl/interfaces/efl_observable.eo 
b/src/lib/efl/interfaces/efl_observable.eo
new file mode 100644
index 0000000..7accb4c
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_observable.eo
@@ -0,0 +1,63 @@
+class Efl.Observable (Efl.Object) {
+   methods {
+      observer_add {
+         [[Add an observer to a group of observers.
+
+           Note: Observers that observe this observable are grouped by the $key
+           and an observer can belong to multiple groups at the same time.
+
+           @since 1.19]]
+         params {
+            @in key: string; [[A key to classify observer groups]]
+            @in obs: Efl.Observer; [[An observer object]]
+         }
+      }
+      observer_del {
+         [[Delete an observer from a group of observers.
+
+           See also @.observer_add().
+
+           @since 1.19]]
+         params {
+            @in key: string; [[A key to classify observer groups]]
+            @in obs: Efl.Observer; [[An observer object]]
+         }
+      }
+      observer_clean {
+         [[Clear an observer from all groups of observers.
+
+           @since 1.19]]
+         params {
+            @in obs: Efl.Observer; [[An observer object]]
+         }
+      }
+      observers_iterator_new {
+         [[Return a new iterator associated with a group of observers.
+
+           @since 1.19]]
+         return: free(own(iterator<Efl.Observer>), eina_iterator_free);
+         params {
+            @in key: string; [[A key to classify observer groups]]
+         }
+      }
+      observers_update {
+         [[Update all observers in a group by calling their update() method.
+
+           @since 1.19]]
+         params {
+            @in key: string; [[A key to classify observer groups]]
+            @in data: void_ptr; [[Required data to update observer]]
+         }
+      }
+      iterator_tuple_new {
+         [[Return a new iterator associated to this observable.
+
+           @since 1.19]]
+         return: free(own(iterator<Efl.Observable.Tuple>), eina_iterator_free);
+      }
+   }
+   implements {
+      Efl.Object.constructor;
+      Efl.Object.destructor;
+   }
+}
diff --git a/src/lib/efl/interfaces/efl_observer.c 
b/src/lib/efl/interfaces/efl_observer.c
new file mode 100644
index 0000000..eb2ca92
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_observer.c
@@ -0,0 +1,259 @@
+#include "config.h"
+#include "Efl.h"
+
+typedef struct
+{
+   Eina_Hash *observers;
+} Efl_Observable_Data;
+
+typedef struct
+{
+   EINA_REFCOUNT;
+
+   Efl_Observer *o;
+} Efl_Observer_Refcount;
+
+EOLIAN static Eo *
+_efl_observable_efl_object_constructor(Efl_Object *obj, Efl_Observable_Data 
*pd)
+{
+   pd->observers = 
eina_hash_string_superfast_new((Eina_Free_Cb)eina_hash_free);
+
+   obj = efl_constructor(efl_super(obj, EFL_OBSERVABLE_CLASS));
+
+   return obj;
+}
+
+EOLIAN static void
+_efl_observable_efl_object_destructor(Eo *obj, Efl_Observable_Data *pd)
+{
+   eina_hash_free(pd->observers);
+
+   efl_destructor(efl_super(obj, EFL_OBSERVABLE_CLASS));
+}
+
+EOLIAN static void
+_efl_observable_observer_add(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, 
const char *key, Efl_Observer *obs)
+{
+   Eina_Hash *observers;
+   Efl_Observer_Refcount *or;
+
+   if (!key) return;
+
+   observers = eina_hash_find(pd->observers, key);
+   if (!observers)
+     {
+        observers = eina_hash_pointer_new(free);
+        eina_hash_add(pd->observers, key, observers);
+     }
+
+   or = eina_hash_find(observers, &obs);
+   if (!or)
+     {
+        or = calloc(1, sizeof(Efl_Observer_Refcount));
+        or->o = obs;
+        EINA_REFCOUNT_INIT(or);
+
+        eina_hash_direct_add(observers, &or->o, or);
+     }
+   else
+     {
+        EINA_REFCOUNT_REF(or);
+     }
+}
+
+EOLIAN static void
+_efl_observable_observer_del(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, 
const char *key, Efl_Observer *obs)
+{
+   Eina_Hash *observers;
+   Efl_Observer_Refcount *or;
+
+   if (!key) return;
+
+   observers = eina_hash_find(pd->observers, key);
+   if (!observers) return;
+
+   or = eina_hash_find(observers, &obs);
+   if (!or) return;
+
+   EINA_REFCOUNT_UNREF(or)
+     {
+        eina_hash_del(observers, &or->o, or);
+
+        if (eina_hash_population(observers) == 0)
+          {
+             eina_hash_del(pd->observers, key, observers);
+          }
+     }
+}
+
+EOLIAN static void
+_efl_observable_observer_clean(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, 
Efl_Observer *obs)
+{
+   Eina_Iterator *it;
+   Eina_Hash *observers;
+
+   it = eina_hash_iterator_data_new(pd->observers);
+   EINA_ITERATOR_FOREACH(it, observers)
+     {
+        Efl_Observer_Refcount *or;
+
+        or = eina_hash_find(observers, &obs);
+        if (!or) continue;
+
+        EINA_REFCOUNT_UNREF(or)
+          {
+             eina_hash_del(observers, &obs, or);
+          }
+     }
+   eina_iterator_free(it);
+}
+
+typedef struct
+{
+   Eina_Iterator iterator;
+   Eina_Iterator *classes;
+} Efl_Observer_Iterator;
+
+static Eina_Bool
+_efl_observable_observers_iterator_next(Eina_Iterator *it, void **data)
+{
+   Efl_Observer_Iterator *et = (void *)it;
+   Efl_Observer_Refcount *or = NULL;
+
+   if (!eina_iterator_next(et->classes, (void **)&or)) return EINA_FALSE;
+   if (!or) return EINA_FALSE;
+
+   *data = or->o;
+
+   return EINA_TRUE;
+}
+
+static void *
+_efl_observable_observers_iterator_container(Eina_Iterator *it EINA_UNUSED)
+{
+   return NULL;
+}
+
+static void
+_efl_observable_observers_iterator_free(Eina_Iterator *it)
+{
+   Efl_Observer_Iterator *et = (void *)it;
+
+   eina_iterator_free(et->classes);
+   EINA_MAGIC_SET(&et->iterator, 0);
+   free(et);
+}
+
+EOLIAN static Eina_Iterator *
+_efl_observable_observers_iterator_new(Eo *obj EINA_UNUSED, 
Efl_Observable_Data *pd, const char *key)
+{
+   Eina_Hash *observers;
+   Efl_Observer_Iterator *it;
+
+   observers = eina_hash_find(pd->observers, key);
+   if (!observers) return NULL;
+
+   it = calloc(1, sizeof(Efl_Observer_Iterator));
+   if (!it) return NULL;
+
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+   it->classes = eina_hash_iterator_data_new(observers);
+
+   it->iterator.version = EINA_ITERATOR_VERSION;
+   it->iterator.next = _efl_observable_observers_iterator_next;
+   it->iterator.get_container = _efl_observable_observers_iterator_container;
+   it->iterator.free = _efl_observable_observers_iterator_free;
+
+   return &it->iterator;
+}
+
+EOLIAN static void
+_efl_observable_observers_update(Eo *obj, Efl_Observable_Data *pd EINA_UNUSED, 
const char *key, void *data)
+{
+   Eina_Iterator *it;
+   Efl_Observer *o;
+
+   it = efl_observable_observers_iterator_new(obj, key);
+   if (!it) return;
+
+   EINA_ITERATOR_FOREACH(it, o)
+     {
+        efl_observer_update(o, obj, key, data);
+     }
+}
+
+typedef struct
+{
+   Eina_Iterator iterator;
+   Eina_Iterator *classes;
+   Efl_Observable *obs;
+   Eina_List *tuples;
+} Efl_Observable_Iterator;
+
+static Eina_Bool
+_efl_observable_iterator_tuple_next(Eina_Iterator *it, void **data)
+{
+   Efl_Observable_Iterator *et = (void *)it;
+   Efl_Observable_Tuple *tuple;
+   const char *key;
+
+   if (!eina_iterator_next(et->classes, (void **)&key)) return EINA_FALSE;
+   if (!key) return EINA_FALSE;
+
+   tuple = calloc(1, sizeof(Efl_Observable_Tuple));
+   if (!tuple) return EINA_FALSE;
+
+   tuple->key = key;
+   tuple->data = efl_observable_observers_iterator_new(et->obs, key);
+
+   et->tuples = eina_list_append(et->tuples, tuple);
+   *data = tuple;
+
+   return EINA_TRUE;
+}
+
+static void *
+_efl_observable_iterator_tuple_container(Eina_Iterator *it EINA_UNUSED)
+{
+   return NULL;
+}
+
+static void
+_efl_observable_iterator_tuple_free(Eina_Iterator *it)
+{
+   Efl_Observable_Iterator *et = (void *)it;
+   Efl_Observable_Tuple *tuple;
+
+   eina_iterator_free(et->classes);
+   EINA_LIST_FREE(et->tuples, tuple)
+     {
+        if (tuple->data)
+          eina_iterator_free(tuple->data);
+        free(tuple);
+     }
+   EINA_MAGIC_SET(&et->iterator, 0);
+   free(et);
+}
+
+EOLIAN static Eina_Iterator *
+_efl_observable_iterator_tuple_new(Eo *obj, Efl_Observable_Data *pd)
+{
+   Efl_Observable_Iterator *it;
+
+   it = calloc(1, sizeof(Efl_Observable_Iterator));
+   if (!it) return NULL;
+
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+   it->classes = eina_hash_iterator_key_new(pd->observers);
+   it->obs = obj;
+
+   it->iterator.version = EINA_ITERATOR_VERSION;
+   it->iterator.next = _efl_observable_iterator_tuple_next;
+   it->iterator.get_container = _efl_observable_iterator_tuple_container;
+   it->iterator.free = _efl_observable_iterator_tuple_free;
+
+   return &it->iterator;
+}
+
+#include "efl_observable.eo.c"
+#include "efl_observer.eo.c"
diff --git a/src/lib/efl/interfaces/efl_observer.eo 
b/src/lib/efl/interfaces/efl_observer.eo
new file mode 100644
index 0000000..a0d4ffe
--- /dev/null
+++ b/src/lib/efl/interfaces/efl_observer.eo
@@ -0,0 +1,15 @@
+interface Efl.Observer {
+   methods {
+      update @virtual_pure {
+         [[Update observer according to the changes of observable object.
+
+           @since 1.19]]
+         params {
+            /* FIXME: obs should be Efl.Observable, but cyclic dependency 
error occurs. */
+            @in obs: Efl.Object; [[An observable object]]
+            @in key: string; [[A key to classify observer groups]]
+            @in data: void_ptr; [[Required data to update the observer, 
usually passed by observable object]]
+         }
+      }
+   }
+}
diff --git a/src/lib/efl/interfaces/efl_types.eot 
b/src/lib/efl/interfaces/efl_types.eot
index 0625dc3..988f7ab 100644
--- a/src/lib/efl/interfaces/efl_types.eot
+++ b/src/lib/efl/interfaces/efl_types.eot
@@ -38,3 +38,9 @@ struct Efl.Version
                      vanilla (upstream) EFL. Contains $EFL_VERSION_FLAVOR.]]
    build_id: string; [[Contains $EFL_BUILD_ID.]]
 }
+
+struct Efl.Observable.Tuple
+{
+   key: string;
+   data: free(own(iterator<Efl.Observer>), eina_iterator_free);
+}

-- 


Reply via email to