sanghyeonlee pushed a commit to branch master.

http://git.enlightenment.org/core/elementary.git/commit/?id=d77143e762675754d3e528a4bd19d264f4a81445

commit d77143e762675754d3e528a4bd19d264f4a81445
Author: Shashank Pandey <shashan...@samsung.com>
Date:   Wed Sep 23 20:50:05 2015 +0900

    Elm_genlist: Add Item filtering support
    
    Summary:
    Add Filtering support in genlist based on filter function set by 
application.
    
    @feature
    
    Test Plan: Genlist filter sample added in elementary_test
    
    Reviewers: raster, shilpasingh, cedric, SanghyeonLee
    
    Subscribers: SanghyeonLee, divyesh, rajeshps, govi, prince.dubey, 
poornima.srinivasan
    
    Differential Revision: https://phab.enlightenment.org/D2514
---
 src/bin/test.c               |   2 +
 src/bin/test_genlist.c       | 148 +++++++++++++++++++++++++-
 src/lib/elm_gen.h            |  10 ++
 src/lib/elm_gen_common.h     |   2 +
 src/lib/elm_genlist.c        | 245 +++++++++++++++++++++++++++++++++++++++++--
 src/lib/elm_genlist.eo       |  25 +++++
 src/lib/elm_widget_genlist.h |  25 +++++
 7 files changed, 449 insertions(+), 8 deletions(-)

diff --git a/src/bin/test.c b/src/bin/test.c
index 8a82f1e..14296a3 100644
--- a/src/bin/test.c
+++ b/src/bin/test.c
@@ -123,6 +123,7 @@ void test_genlist_focus(void *data, Evas_Object *obj, void 
*event_info);
 void test_genlist_item_styles(void *data, Evas_Object *obj, void *event_info);
 void test_genlist_multi_select(void *data, Evas_Object *obj, void *event_info);
 void test_genlist_del(void *data, Evas_Object *obj, void *event_info);
+void test_genlist_filter(void *data, Evas_Object *obj, void *event_info);
 void test_gesture_layer(void *data, Evas_Object *obj, void *event_info);
 void test_gesture_layer2(void *data, Evas_Object *obj, void *event_info);
 void test_gesture_layer3(void *data, Evas_Object *obj, void *event_info);
@@ -693,6 +694,7 @@ add_tests:
    ADD_TEST(NULL, "Lists - Genlist", "Genlist Item Styles", 
test_genlist_item_styles);
    ADD_TEST(NULL, "Lists - Genlist", "Genlist Multi Select", 
test_genlist_multi_select);
    ADD_TEST(NULL, "Lists - Genlist", "Genlist Del", test_genlist_del);
+   ADD_TEST(NULL, "Lists - Genlist", "Genlist Filter", test_genlist_filter);
 
    //------------------------------//
 
diff --git a/src/bin/test_genlist.c b/src/bin/test_genlist.c
index e32c58b..cc3958f 100644
--- a/src/bin/test_genlist.c
+++ b/src/bin/test_genlist.c
@@ -19,6 +19,8 @@ struct _api_data
    Elm_Genlist_Item_Class *itc1;
    Elm_Genlist_Item_Class *itc2;
    void *gl;
+
+   void *filter_data;   /* The data used for filtering     */
 };
 typedef struct _api_data api_data;
 
@@ -285,7 +287,9 @@ _gl_changed(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_in
 static void
 _cleanup_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
 {
-   free(data);
+   api_data *api = (api_data *)data;
+   if (api->filter_data) free(api->filter_data);
+   free(api);
 }
 
 void
@@ -4831,3 +4835,145 @@ test_genlist_focus(void *data EINA_UNUSED,
    evas_object_show(win);
 }
 
+char *genlist_demo_names[] = {
+        "Aaliyah", "Aamir", "Aaralyn", "Aaron", "Abagail",
+        "Babitha", "Bahuratna", "Bandana", "Bulbul", "Cade", "Caldwell",
+        "Chandan", "Caster", "Dagan ", "Daulat", "Dag", "Earl", "Ebenzer",
+        "Ellison", "Elizabeth", "Filbert", "Fitzpatrick", "Florian", "Fulton",
+        "Frazer", "Gabriel", "Gage", "Galen", "Garland", "Gauhar", "Hadden",
+        "Hafiz", "Hakon", "Haleem", "Hank", "Hanuman", "Jabali ", "Jaimini",
+        "Jayadev", "Jake", "Jayatsena", "Jonathan", "Kamaal", "Jeirk",
+        "Jasper", "Jack", "Mac", "Macy", "Marlon", "Milson",
+        NULL
+};
+
+static char *
+glf_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part 
EINA_UNUSED)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "%s", 
genlist_demo_names[((int)(uintptr_t)data)%50]);
+   return strdup(buf);
+}
+
+Eina_Bool
+gl_filter_get(void *data, Evas_Object *obj EINA_UNUSED, void *key)
+{
+   if (!strlen((char *)key)) return EINA_TRUE;
+
+   if (strcasestr(genlist_demo_names[((int)(uintptr_t)data)%50], (char *)key))
+     return EINA_TRUE;
+   // Default case should return false (item fails filter hence will be hidden)
+   return EINA_FALSE;
+}
+
+static void
+_gl_filter_finished_cb(void *data, Evas_Object *obj EINA_UNUSED, void 
*event_info)
+{
+   printf("Filter finished\n");
+}
+
+void
+_entry_change_cb(void *data, Evas_Object *obj, void *event EINA_UNUSED)
+{
+   api_data *api = (api_data *)data;
+   char buf[100];
+   Eina_Iterator *filter_iter;
+   unsigned int count = 0;
+   Elm_Object_Item *item;
+
+   if (api->filter_data) free(api->filter_data);
+
+   sprintf(buf, "%s", elm_object_text_get(obj));
+   api->filter_data = strdup(buf);
+   elm_genlist_filter_set(api->gl, (void *)(api->filter_data));
+   if (buf == NULL || !strlen(buf))
+     {
+        printf("Input data string empty; returning\n");
+        return;
+     }
+   filter_iter = elm_genlist_filter_iterator_new(api->gl);
+
+   EINA_ITERATOR_FOREACH(filter_iter, item)
+     if (item) count++;
+
+   printf("Number of matches for %s is %d\n", buf, count);
+   //Iterator needs to be freed by application using eina_iterator_free
+   eina_iterator_free(filter_iter);
+
+}
+
+void
+test_genlist_filter(void *data EINA_UNUSED,
+                    Evas_Object *obj EINA_UNUSED,
+                    void *event_info EINA_UNUSED)
+{
+   Evas_Object *win, *bx, *bx2, *entry, *gl;
+   Elm_Genlist_Item_Class *itc = NULL;
+   int i;
+
+   api_data *api = calloc(1, sizeof(api_data));
+   win = elm_win_util_standard_add("genlist-filter", "Genlist filter");
+   elm_win_autodel_set(win, EINA_TRUE);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_FREE, _cleanup_cb, api);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_DEL,
+                                _gl_focus_win_del_cb, NULL);
+
+   elm_win_focus_highlight_enabled_set(win, EINA_TRUE);
+   elm_win_focus_highlight_animate_set(win, EINA_TRUE);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   entry = elm_entry_add(bx);
+   elm_entry_single_line_set(entry, EINA_TRUE);
+   evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, 0.0);
+   elm_object_part_text_set(entry, "guide", "Search.");
+   elm_box_pack_end(bx, entry);
+   evas_object_show(entry);
+
+   bx2 = elm_box_add(bx);
+   evas_object_size_hint_weight_set(bx2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(bx2, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(bx, bx2);
+   evas_object_show(bx2);
+
+   gl = elm_genlist_add(bx);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_genlist_select_mode_set(gl, ELM_OBJECT_SELECT_MODE_ALWAYS);
+   elm_genlist_mode_set(gl, ELM_LIST_COMPRESS);
+   elm_genlist_homogeneous_set(gl, EINA_TRUE);
+   elm_box_pack_end(bx2, gl);
+   api->gl = gl;
+   evas_object_show(gl);
+   evas_object_smart_callback_add(gl, "selected", _gl_focus_item_cb, 
"selected");
+   evas_object_smart_callback_add(gl, "unselected", _gl_focus_item_cb, 
"unselected");
+   evas_object_smart_callback_add(gl, "activated", _gl_focus_item_cb, 
"activated");
+   evas_object_smart_callback_add(gl, "highlighted", _gl_focus_item_cb, 
"highlighted");
+   evas_object_smart_callback_add(gl, "unhighlighted", _gl_focus_item_cb, 
"unhighlighted");
+   evas_object_smart_callback_add(gl, "filter,done", _gl_filter_finished_cb, 
NULL);
+   evas_object_event_callback_add(gl, EVAS_CALLBACK_KEY_DOWN, 
_gl_focus_key_down_cb, NULL);
+
+   itc = elm_genlist_item_class_new();
+   itc->item_style = "default";
+   itc->func.text_get = glf_text_get;
+   itc->func.content_get = NULL;
+   itc->func.filter_get = gl_filter_get;
+   itc->func.state_get = NULL;
+   itc->func.del = NULL;
+
+   for (i = 0; i < 500; i++)
+     elm_genlist_item_append(gl, itc,
+                             (void *)(long)i, NULL,
+                             ELM_GENLIST_ITEM_NONE,
+                             NULL, NULL);
+
+   evas_object_resize(win, 420, 600);
+   evas_object_show(win);
+   elm_object_focus_set(entry, EINA_TRUE);
+   evas_object_smart_callback_add(entry, "changed,user", _entry_change_cb, 
api);
+}
+
diff --git a/src/lib/elm_gen.h b/src/lib/elm_gen.h
index 976a2da..2ef3d86 100644
--- a/src/lib/elm_gen.h
+++ b/src/lib/elm_gen.h
@@ -42,6 +42,15 @@ typedef Eina_Bool                     
(*Elm_Gen_Item_State_Get_Cb)(void *data, E
  */
 typedef void                          (*Elm_Gen_Item_Del_Cb)(void *data, 
Evas_Object *obj); /**< Deletion class function for gen item classes. */
 
+/**
+ * Filter class function for Elm_Gen_Item_Class.
+ * @param data The data passed in the item creation function
+ * @param obj The base widget object
+ * @param key The key needed for item filter to be decided on
+ * @return The boolean state of filter for this element
+ */
+typedef Eina_Bool                     (*Elm_Gen_Item_Filter_Get_Cb)(void 
*data, Evas_Object *obj, void *key); /**< Filter seeking class function for gen 
item classes. */
+
 struct _Elm_Gen_Item_Class
 {
    int           version;  /**< Set by elementary if you alloc an item class 
using elm_genlist/gengrid_item_class_new(), or if you set your own class (must 
be const) then set it to ELM_GENLIST/GENGRID_ITEM_CLASS_VERSION */
@@ -56,6 +65,7 @@ struct _Elm_Gen_Item_Class
         Elm_Gen_Item_Content_Get_Cb content_get; /**< Content fetching class 
function for genlist/gengrid item classes. */
         Elm_Gen_Item_State_Get_Cb   state_get; /**< State fetching class 
function for genlist/gengrid item classes. */
         Elm_Gen_Item_Del_Cb         del; /**< Deletion class function for 
genlist/gengrid item classes. */
+        Elm_Gen_Item_Filter_Get_Cb  filter_get;  /**< Filter seeking class 
function for genlist/gengrid item classes. */
      } func;
 }; /**< #Elm_Gen_Item_Class member definitions */
 
diff --git a/src/lib/elm_gen_common.h b/src/lib/elm_gen_common.h
index a9d5de6..c980819 100644
--- a/src/lib/elm_gen_common.h
+++ b/src/lib/elm_gen_common.h
@@ -67,6 +67,8 @@ struct Elm_Gen_Item
    Eina_Bool                 flipped : 1; /**< a flag that shows the flip 
status of the item. */
    Eina_Bool                 has_contents : 1; /**< content objs have or 
previously did exist (size calcs) */
    Eina_Bool                 cursor_engine_only : 1;
+   Eina_Bool                 hide : 1; /**< flag used for hiding the items 
which do not match filter text */
+   Eina_Bool                 filtered: 1; /**<flag used to indicate whether or 
not item has been filtered */
 };
 
 #endif
diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c
index 6ebba7f..95cb440 100644
--- a/src/lib/elm_genlist.c
+++ b/src/lib/elm_genlist.c
@@ -93,7 +93,8 @@
     cmd(SIG_ITEM_UNFOCUSED, "item,unfocused", "") \
     cmd(SIG_PRESSED, "pressed", "") \
     cmd(SIG_RELEASED, "released", "") \
-    cmd(SIG_CHANGED, "changed", "")
+    cmd(SIG_CHANGED, "changed", "") \
+    cmd(SIG_FILTER_DONE, "filter,done", "")
 
 ELM_PRIV_GENLIST_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
 
@@ -157,6 +158,7 @@ static void _access_activate_cb(void *data EINA_UNUSED,
                                 Elm_Object_Item *item);
 static void _decorate_item_set(Elm_Gen_Item *);
 static void _internal_elm_genlist_clear(Evas_Object *obj);
+static Eina_Bool _item_filtered_get(Elm_Gen_Item *it);
 
 static const Elm_Action key_actions[] = {
    {"move", _key_action_move},
@@ -2244,6 +2246,12 @@ _item_block_position(Item_Block *itb,
         sd = GL_IT(it)->wsd;
         if (sd->reorder_it == it) continue;
 
+        if (!it->filtered) _item_filtered_get(it);
+        if (it->hide)
+          {
+             if (it->realized) evas_object_hide(VIEW(it));
+             continue;
+          }
         it->x = 0;
         it->y = y;
         it->item->w = itb->w;
@@ -2474,7 +2482,8 @@ _item_multi_select_up(Elm_Genlist_Data *sd)
    while (eo_prev)
      {
         ELM_GENLIST_ITEM_DATA_GET(eo_prev, prev);
-        if ((!_is_no_select(prev)) && (!elm_object_item_disabled_get(eo_prev)))
+        if ((!_is_no_select(prev)) &&
+            (!elm_object_item_disabled_get(eo_prev)) && (!prev->hide))
           break;
         eo_prev = 
EO_OBJ(ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev));
      }
@@ -2504,7 +2513,8 @@ _item_multi_select_down(Elm_Genlist_Data *sd)
    while ((eo_next))
      {
         ELM_GENLIST_ITEM_DATA_GET(eo_next, next);
-        if ((!_is_no_select(next)) && (!elm_object_item_disabled_get(eo_next)))
+        if ((!_is_no_select(next)) &&
+            (!elm_object_item_disabled_get(eo_next)) && (!next->hide))
           break;
         eo_next = 
EO_OBJ(ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next));
      }
@@ -2557,7 +2567,7 @@ _item_single_select_up(Elm_Genlist_Data *sd)
    while (prev)
      {
         if ((!_is_no_select(prev)) &&
-            (!elm_object_item_disabled_get(EO_OBJ(prev))))
+            (!elm_object_item_disabled_get(EO_OBJ(prev))) && (!prev->hide))
           break;
         prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
      }
@@ -2587,7 +2597,7 @@ _item_single_select_down(Elm_Genlist_Data *sd)
    while (next)
      {
         if ((!_is_no_select(next)) &&
-            (!elm_object_item_disabled_get(EO_OBJ(next))))
+            (!elm_object_item_disabled_get(EO_OBJ(next))) && (!next->hide))
           break;
         next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
      }
@@ -2703,7 +2713,7 @@ _item_focused_next(Evas_Object *obj, Elm_Focus_Direction 
dir)
         while ((next) &&
                ((eo_do_ret(EO_OBJ(next), tmp, elm_wdg_item_disabled_get())) ||
                (_is_no_select(next))))
-          next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
+          if (!next->hide) next = 
ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
      }
    else
      {
@@ -5050,6 +5060,13 @@ _item_block_recalc(Item_Block *itb,
      {
         sd = GL_IT(it)->wsd;
         show_me |= it->item->show_me;
+
+        if (!it->filtered) _item_filtered_get(it);
+        if (it->hide)
+          {
+             if (it->realized) evas_object_hide(VIEW(it));
+             continue;
+          }
         if (!itb->realized)
           {
              if (qadd || (itb->sd->homogeneous &&
@@ -5609,7 +5626,7 @@ _access_obj_process(Elm_Genlist_Data *sd, Eina_Bool 
is_access)
              done = EINA_TRUE;
              EINA_LIST_FOREACH(itb->items, l, it)
                {
-                  if (!it->realized) continue;
+                  if (!it->realized || it->hide) continue;
                   if (is_access) _access_widget_item_register(it);
                   else
                     _elm_access_widget_item_unregister(it->base);
@@ -5659,6 +5676,12 @@ _internal_elm_genlist_clear(Evas_Object *obj)
 
    ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
 
+   sd->filter_data = NULL;
+   if (sd->filter_queue)
+     ELM_SAFE_FREE(sd->queue_filter_enterer, ecore_idle_enterer_del);
+   ELM_SAFE_FREE(sd->filter_queue, eina_list_free);
+   ELM_SAFE_FREE(sd->filtered_list, eina_list_free);
+
    evas_event_freeze(evas_object_evas_get(sd->obj));
 
    // Do not use EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE
@@ -7343,6 +7366,214 @@ _elm_genlist_block_count_get(Eo *obj EINA_UNUSED, 
Elm_Genlist_Data *sd)
    return sd->max_items_per_block;
 }
 
+static void
+_filter_item_internal(Elm_Gen_Item *it)
+{
+   ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
+   if (sd->filter_data && it->itc->func.filter_get)
+     {
+        if (!it->itc->func.filter_get(
+               (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)),
+                WIDGET(it), sd->filter_data))
+          {
+             it->hide = EINA_TRUE;
+             it->item->block->changed = EINA_TRUE;
+          }
+        else
+          sd->filtered_count++;
+     }
+   it->filtered = EINA_TRUE;
+   sd->processed_count++;
+}
+
+static Eina_Bool
+_item_filtered_get(Elm_Gen_Item *it)
+{
+   Eina_List *l;
+   if (!it) return EINA_FALSE;
+   ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
+   if (!it->filtered)
+     {
+        l = eina_list_data_find_list(sd->filter_queue, it);
+        if (l)
+          sd->filter_queue = eina_list_remove_list(sd->queue, l);
+        l = eina_list_data_find_list(sd->queue, it);
+        if (l)
+          {
+             sd->queue = eina_list_remove_list(sd->queue, l);
+             it->item->queued = EINA_FALSE;
+             _item_process(sd, it);
+             _item_process_post(sd, it, EINA_TRUE);
+          }
+
+        _filter_item_internal(it);
+        it->item->block->changed = EINA_TRUE;
+        ELM_SAFE_FREE(sd->calc_job, ecore_job_del);
+        sd->calc_job = ecore_job_add(_calc_job, sd->obj);
+   }
+   if (!it->hide) return EINA_TRUE;
+   return EINA_FALSE;
+}
+
+static int
+_filter_queue_process(Elm_Genlist_Data *sd)
+{
+   int n;
+   Elm_Gen_Item *it;
+   double t0;
+
+   t0 = ecore_loop_time_get();
+   for (n = 0; (sd->filter_queue) && (sd->processed_count < sd->item_count); 
n++)
+     {
+        it = eina_list_data_get(sd->filter_queue);
+        //FIXME: This is added as a fail safe code for items not yet processed.
+        while (it->item->queued)
+          {
+             if ((ecore_loop_time_get() - t0) > 
(ecore_animator_frametime_get()))
+               return n;
+             sd->filter_queue = eina_list_remove_list
+                              (sd->filter_queue, sd->filter_queue);
+             sd->filter_queue = eina_list_append(sd->filter_queue, it);
+             it = eina_list_data_get(sd->filter_queue);
+          }
+        sd->filter_queue = eina_list_remove_list(sd->filter_queue, 
sd->filter_queue);
+        _filter_item_internal(it);
+        it->item->block->changed = EINA_TRUE;
+        if ((ecore_loop_time_get() - t0) > (ecore_animator_frametime_get()))
+          {
+             //At least 1 item is filtered by this time, so return n+1 for 
first loop
+             n++;
+             break;
+          }
+     }
+   return n;
+}
+
+static Eina_Bool
+_filter_process(void *data,
+              Eina_Bool *wakeup)
+{
+   Elm_Genlist_Data *sd = data;
+
+   if (_filter_queue_process(sd) > 0) *wakeup = EINA_TRUE;
+   if (!sd->filter_queue) return ECORE_CALLBACK_CANCEL;
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_item_filter_enterer(void *data)
+{
+   Eina_Bool wakeup = EINA_FALSE;
+   ELM_GENLIST_DATA_GET(data, sd);
+   Eina_Bool ok = _filter_process(sd, &wakeup);
+   if (wakeup)
+     {
+        // wake up mainloop
+        ELM_SAFE_FREE(sd->calc_job, ecore_job_del);
+        sd->calc_job = ecore_job_add(_calc_job, data);
+     }
+   if (ok == ECORE_CALLBACK_CANCEL)
+     {
+        sd->queue_idle_enterer = NULL;
+        eo_do(sd->obj, eo_event_callback_call(ELM_GENLIST_EVENT_FILTER_DONE, 
NULL));
+     }
+
+   return ok;
+}
+
+EOLIAN void
+_elm_genlist_filter_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, void 
*filter_data)
+{
+   Item_Block *itb;
+   Eina_List *l;
+   Elm_Gen_Item *it;
+
+   if (sd->filter_queue)
+     ELM_SAFE_FREE(sd->queue_filter_enterer, ecore_idle_enterer_del);
+   ELM_SAFE_FREE(sd->filter_queue, eina_list_free);
+   ELM_SAFE_FREE(sd->filtered_list, eina_list_free);
+   sd->filtered_count = 0;
+   sd->processed_count = 0;
+   sd->filter = EINA_TRUE;
+   sd->filter_data = filter_data;
+
+   EINA_INLIST_FOREACH(sd->blocks, itb)
+     {
+        if (itb->realized)
+          {
+             EINA_LIST_FOREACH(itb->items, l, it)
+               {
+                  it->filtered = EINA_FALSE;
+                  it->hide = EINA_FALSE;
+                  if (it->realized)
+                    _filter_item_internal(it);
+                  else
+                    sd->filter_queue = eina_list_append(sd->filter_queue, it);
+               }
+            itb->changed = EINA_TRUE;
+         }
+       else
+         {
+            EINA_LIST_FOREACH(itb->items, l, it)
+              {
+                 it->filtered = EINA_FALSE;
+                 it->hide = EINA_FALSE;
+                 sd->filter_queue = eina_list_append(sd->filter_queue, it);
+              }
+         }
+     }
+   _calc_job(sd->obj);
+
+   sd->queue_filter_enterer = ecore_idle_enterer_add(_item_filter_enterer,
+                                                     sd->obj);
+}
+
+static Eina_Bool
+_filter_iterator_next(Elm_Genlist_Filter *iter, void **data)
+{
+   if (!iter->current) return EINA_FALSE;
+   Elm_Gen_Item *item;
+   while (iter->current)
+     {
+        item = ELM_GENLIST_FILTER_CONTAINER_GET(iter->current, Elm_Gen_Item);
+        iter->current = iter->current->next;
+        if (_item_filtered_get(item))
+          {
+             if (data)
+               *data = EO_OBJ(item);
+             return EINA_TRUE;
+          }
+     }
+
+   return EINA_FALSE;
+}
+
+static void
+_filter_iterator_free(Elm_Genlist_Filter *it)
+{
+   free(it);
+}
+
+EOLIAN Eina_Iterator *
+_elm_genlist_filter_iterator_new(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd)
+{
+   Elm_Genlist_Filter *iter;
+   iter = calloc(1, sizeof (Elm_Genlist_Filter));
+   if (!iter) return NULL;
+
+   iter->head = sd->items;
+   iter->current = sd->items;
+
+   iter->iterator.version = EINA_ITERATOR_VERSION;
+   iter->iterator.next = FUNC_ITERATOR_NEXT(_filter_iterator_next);
+   iter->iterator.get_container = sd->obj;
+   iter->iterator.free = FUNC_ITERATOR_FREE(_filter_iterator_free);
+
+   EINA_MAGIC_SET(&iter->iterator, EINA_MAGIC_ITERATOR);
+
+   return &iter->iterator;
+}
+
 EOLIAN static void
 _elm_genlist_longpress_timeout_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, 
double timeout)
 {
diff --git a/src/lib/elm_genlist.eo b/src/lib/elm_genlist.eo
index 5ea446a..5bf03a5 100644
--- a/src/lib/elm_genlist.eo
+++ b/src/lib/elm_genlist.eo
@@ -392,6 +392,30 @@ class Elm.Genlist (Elm.Layout, Elm_Interface_Scrollable, 
Evas.Clickable_Interfac
             @out posret: int; [[The position relative to the item returned 
here.]]
          }
       }
+      @property filter {
+         set {
+            [[Set filter mode with key.
+
+              This initiates the filter mode of genlist with user/application
+              provided key. If key is NULL, the filter mode is turned off.
+
+              The filter data passed has to be managed by application itself 
and
+              should not be deleted before genlist is deleted(or while 
filtering
+              is not done.
+            ]]
+         }
+         values {
+            key: void *; [[Filter key]]
+         }
+      }
+      filter_iterator_new {
+         [[Returns an iterator over the list of filtered items.
+
+           Return NULL if filter is not set. Application must take care
+           of the case while calling the API. Must be freed after use.
+         ]]
+         return: free(own(iterator<Elm_Gen_Item *> *), eina_iterator_free); 
[[Iterator on genlist]]
+      }
       items_count @const {
          [[Return how many items are currently in a list.
 
@@ -554,6 +578,7 @@ class Elm.Genlist (Elm.Layout, Elm_Interface_Scrollable, 
Evas.Clickable_Interfac
       expanded;
       index,update;
       tree,effect,finished;
+      filter,done;
    }
 
 }
diff --git a/src/lib/elm_widget_genlist.h b/src/lib/elm_widget_genlist.h
index df034b8..92c384a 100644
--- a/src/lib/elm_widget_genlist.h
+++ b/src/lib/elm_widget_genlist.h
@@ -143,6 +143,14 @@ struct _Elm_Genlist_Data
    Elm_Genlist_Item_Move_Effect_Mode     move_effect_mode;
    int                                   reorder_fast;
 
+   Eina_List                            *filter_queue;
+   Eina_List                            *filtered_list;
+   void                                 *filter_data;
+   unsigned int                          processed_count;
+   unsigned int                          filtered_count;
+   Ecore_Idle_Enterer                   *queue_filter_enterer;
+   Eina_Bool                             filter;
+
    Eina_Bool                             focus_on_selection_enabled : 1;
    Eina_Bool                             tree_effect_enabled : 1;
    Eina_Bool                             auto_scroll_enabled : 1;
@@ -280,6 +288,23 @@ struct _Elm_Genlist_Pan_Data
 };
 
 /**
+ * Structure added to genlist for internal filter iterator implementation
+ * Can be extended to genlist as a whole in future if needed.
+ */
+typedef struct _Elm_Genlist_Filter Elm_Genlist_Filter;
+struct _Elm_Genlist_Filter
+{
+   Eina_Iterator iterator;
+   const Eina_Inlist *head;
+   const Eina_Inlist *current;
+};
+
+#define ELM_GENLIST_FILTER_CONTAINER_GET(ptr,                          \
+                                  type) ((type *)((char *)ptr - \
+                                                  offsetof(type, __in_list)))
+
+
+/**
  * @}
  */
 

-- 


Reply via email to