tasn pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=6b12ae1e03e93a10b0120aa15d1ff40b022ec189

commit 6b12ae1e03e93a10b0120aa15d1ff40b022ec189
Author: Youngbok Shin <youngb.s...@samsung.com>
Date:   Tue Jan 12 13:20:19 2016 +0000

    edje: Reduce duplicated item obj creations and deletions.
    
    Summary:
    When text is changed, all of objects for item tag are deleted
    and recreated. It is unnecessary work and can cause performance
    issues. Actually, many of application developers wonder why
    item provider callback functions are called every text changes.
    @fix
    
    Test Plan:
    Run elementary_test -to "entry emoticon"
    When you make a very little change on text,
    36 emoticon objects are recreated.
    
    Reviewers: woohyun, jaehwan, herdsman, tasn
    
    Reviewed By: tasn
    
    Subscribers: cedric, jpeg
    
    Differential Revision: https://phab.enlightenment.org/D3537
---
 src/lib/edje/edje_entry.c | 112 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 103 insertions(+), 9 deletions(-)

diff --git a/src/lib/edje/edje_entry.c b/src/lib/edje/edje_entry.c
index ffcbc11..34f98a0 100644
--- a/src/lib/edje/edje_entry.c
+++ b/src/lib/edje/edje_entry.c
@@ -12,6 +12,7 @@ static Eina_Bool _edje_entry_imf_retrieve_selection_cb(void 
*data, Ecore_IMF_Con
 typedef struct _Entry  Entry;
 typedef struct _Sel    Sel;
 typedef struct _Anchor Anchor;
+typedef struct _Item_Obj Item_Obj;
 
 static void _edje_entry_imf_cursor_location_set(Entry *en);
 static void _edje_entry_imf_cursor_info_set(Entry *en);
@@ -35,6 +36,7 @@ struct _Entry
    Eina_List             *anchorlist;
    Eina_List             *itemlist;
    Eina_List             *seq;
+   Item_Obj              *item_objs;
    char                  *selection;
    Edje_Input_Panel_Lang  input_panel_lang;
    Eina_Bool              composing : 1;
@@ -70,6 +72,14 @@ struct _Anchor
    Eina_Bool              item : 1;
 };
 
+struct _Item_Obj
+{
+   EINA_INLIST;
+   Anchor                *an;
+   char                  *name;
+   Evas_Object           *obj;
+};
+
 #ifdef HAVE_ECORE_IMF
 static void
 _preedit_clear(Entry *en)
@@ -914,6 +924,89 @@ _edje_anchor_mouse_out_cb(void *data, Evas *e EINA_UNUSED, 
Evas_Object *obj EINA
 }
 
 static void
+_item_obj_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Item_Obj *io = data;
+   Anchor *an = io->an;
+   Entry *en;
+
+   if (!an)
+     {
+        ERR("Failed to free item object struct. Anchor is NULL!");
+        return;
+     }
+
+   en = an->en;
+   en->item_objs = (Item_Obj 
*)eina_inlist_remove(EINA_INLIST_GET(en->item_objs),
+                                                  EINA_INLIST_GET(io));
+   io->an = NULL;
+   free(io->name);
+   free(io);
+}
+
+static Evas_Object *
+_item_obj_get(Anchor *an, Evas_Object *o, Evas_Object *smart, Evas_Object 
*clip)
+{
+   Evas_Object *obj;
+   Item_Obj *io;
+   Entry *en = an->en;
+   Edje *ed = en->ed;
+
+   EINA_INLIST_FOREACH(en->item_objs, io)
+     {
+        if (!io->an && io->name && !strcmp(an->name, io->name))
+          {
+             io->an = an;
+             return io->obj;
+          }
+     }
+
+   io = calloc(1, sizeof(Item_Obj));
+
+   obj = ed->item_provider.func
+      (ed->item_provider.data, smart,
+       en->rp->part->name, an->name);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _item_obj_del_cb, 
io);
+   evas_object_smart_member_add(obj, smart);
+   evas_object_stack_above(obj, o);
+   evas_object_clip_set(obj, clip);
+   evas_object_pass_events_set(obj, EINA_TRUE);
+   evas_object_show(obj);
+
+   io->an = an;
+   io->name = strdup(an->name);
+   io->obj = obj;
+   en->item_objs = (Item_Obj 
*)eina_inlist_append(EINA_INLIST_GET(en->item_objs),
+                                                  EINA_INLIST_GET(io));
+
+   return io->obj;
+}
+
+static void
+_unused_item_objs_free(Entry *en)
+{
+   Item_Obj *io;
+   Eina_Inlist *l;
+
+   EINA_INLIST_FOREACH_SAFE(en->item_objs, l, io)
+     {
+        if (!io->an)
+          {
+             if (io->obj)
+               {
+                  evas_object_event_callback_del_full(io->obj, 
EVAS_CALLBACK_DEL, _item_obj_del_cb, io);
+                  evas_object_del(io->obj);
+               }
+
+             en->item_objs = (Item_Obj 
*)eina_inlist_remove(EINA_INLIST_GET(en->item_objs),
+                                                            
EINA_INLIST_GET(io));
+             free(io->name);
+             free(io);
+          }
+     }
+}
+
+static void
 _anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry 
*en)
 {
    Eina_List *l, *ll, *range = NULL;
@@ -944,14 +1037,7 @@ _anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, 
Evas_Object *o, Entry *en)
 
                   if (ed->item_provider.func)
                     {
-                       ob = ed->item_provider.func
-                           (ed->item_provider.data, smart,
-                           en->rp->part->name, an->name);
-                       evas_object_smart_member_add(ob, smart);
-                       evas_object_stack_above(ob, o);
-                       evas_object_clip_set(ob, clip);
-                       evas_object_pass_events_set(ob, EINA_TRUE);
-                       evas_object_show(ob);
+                       ob = _item_obj_get(an, o, smart, clip);
                        sel->obj = ob;
                     }
                }
@@ -1058,6 +1144,8 @@ _anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, 
Evas_Object *o, Entry *en)
                }
           }
      }
+
+   _unused_item_objs_free(en);
 }
 
 static void
@@ -1100,6 +1188,8 @@ _anchors_need_update(Edje_Real_Part *rp)
 static void
 _anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o 
EINA_UNUSED, Entry *en)
 {
+   Item_Obj *io;
+
    while (en->anchorlist)
      {
         free(en->anchorlist->data);
@@ -1119,7 +1209,7 @@ _anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, 
Evas_Object *o EINA_UNUSED,
              Sel *sel = an->sel->data;
              if (sel->obj_bg) evas_object_del(sel->obj_bg);
              if (sel->obj_fg) evas_object_del(sel->obj_fg);
-             if (sel->obj) evas_object_del(sel->obj);
+             if (!an->item && sel->obj) evas_object_del(sel->obj);
              free(sel);
              an->sel = eina_list_remove_list(an->sel, an->sel);
           }
@@ -1129,6 +1219,9 @@ _anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, 
Evas_Object *o EINA_UNUSED,
         free(an);
         en->anchors = eina_list_remove_list(en->anchors, en->anchors);
      }
+
+   EINA_INLIST_FOREACH(en->item_objs, io)
+      io->an = NULL;
 }
 
 /* FIXME: This is horrible. It's just a copy&paste (with some adjustments)
@@ -2671,6 +2764,7 @@ _edje_entry_real_part_shutdown(Edje *ed, Edje_Real_Part 
*rp)
    rp->typedata.text->entry_data = NULL;
    _sel_clear(ed, en->cursor, rp->object, en);
    _anchors_clear(en->cursor, rp->object, en);
+   _unused_item_objs_free(en);
 #ifdef HAVE_ECORE_IMF
    _preedit_clear(en);
 #endif

-- 


Reply via email to