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))) + + +/** * @} */ --