From: SangHyeon Lee Date: Thu, 27 Oct 2016 05:31:51 +0000 (+0900) Subject: genlist: apply reusable content feature X-Git-Tag: submit/tizen/20161101.043805^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=93057fecc83893db6e03c4a214d153e0a39e065d;p=platform%2Fupstream%2Felementary.git genlist: apply reusable content feature Apply genlist item reusable content feature into tizen. This patch is merged commit from upstream patches. Change-Id: I88e411db28bb91833036afc2bed85adf8a2faa2f Signed-off-by: SangHyeon Lee --- diff --git a/src/bin/test_genlist.c b/src/bin/test_genlist.c index d7e33de..62751ff 100644 --- a/src/bin/test_genlist.c +++ b/src/bin/test_genlist.c @@ -213,6 +213,35 @@ Eina_Bool gl_state_get(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, con return EINA_FALSE; } +Evas_Object *gl_reusable_content_get(void *data EINA_UNUSED, Evas_Object *obj, const char *part, Evas_Object *old) +{ + if (old && !strcmp(part, "elm.swallow.end")) + { + // Reuse old content + // Here need to add initializing and state changing + // for cached content. + // printf("content reuse for cached content %p, %s\n", old, part); + return old; + } + else + { + // Create new content object for non-reused part. + //printf("content create in reuse %p, %s\n", old, part); + char buf[PATH_MAX]; + Evas_Object *ic = elm_icon_add(obj); + if (!strcmp(part, "elm.swallow.end")) + snprintf(buf, sizeof(buf), "%s/images/bubble.png", elm_app_data_dir_get()); + else + snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get()); + elm_image_file_set(ic, buf, NULL); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + return ic; + } + + // If return NULL value, content_get will be called to get new content. + // return NULL; +} + static void gl_sel(void *data, Evas_Object *obj, void *event_info) { @@ -400,9 +429,12 @@ test_genlist(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i api->itc1 = elm_genlist_item_class_new(); api->itc1->item_style = "default"; api->itc1->func.text_get = gl_text_get1; - api->itc1->func.content_get = gl_content_get; + api->itc1->func.content_get = NULL; // gl_content_get; api->itc1->func.state_get = gl_state_get; api->itc1->func.del = NULL; + // use content_reuse function for reusing + // repeated content objects instead of content_get + api->itc1->func.reusable_content_get = gl_reusable_content_get; bt_50 = elm_button_add(win); elm_object_text_set(bt_50, "Go to 50"); diff --git a/src/lib/elm_gen.h b/src/lib/elm_gen.h index a69c992..6d43429 100644 --- a/src/lib/elm_gen.h +++ b/src/lib/elm_gen.h @@ -63,6 +63,19 @@ typedef void (*Elm_Gen_Item_Del_Cb)(void *data, Evas_Ob */ typedef Eina_Bool (*Elm_Gen_Item_Filter_Get_Cb)(void *data, Evas_Object *obj, void *key); /**< Filter seeking class function for gen item classes. */ +/** + * Reusable content get class function for Elm_Gen_Item_Class. + * @param data The data passed in the item creation function + * @param obj The base widget object + * @param part The part name of the swallow + * @param old The old content object for reusing + * @return The content object to swallow + * + * @since 1.18 + */ +typedef Evas_Object *(*Elm_Gen_Item_Reusable_Content_Get_Cb)(void *data, Evas_Object *obj, const char *part, Evas_Object *old); /**< Cache Pop 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 */ @@ -81,10 +94,11 @@ struct _Elm_Gen_Item_Class 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. */ + Elm_Gen_Item_Reusable_Content_Get_Cb reusable_content_get; /**< Reusable content get class function for gen item classes. */ } func; }; /**< #Elm_Gen_Item_Class member definitions */ -#define ELM_GEN_ITEM_CLASS_VERSION 2 +#define ELM_GEN_ITEM_CLASS_VERSION 3 #define ELM_GEN_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_VERSION, 0, 0 typedef enum diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c index 9cad7f5..f3ac96c 100644 --- a/src/lib/elm_genlist.c +++ b/src/lib/elm_genlist.c @@ -362,36 +362,42 @@ _item_content_realize(Elm_Gen_Item *it, Eina_Bool tmp; Evas_Object *content; char buf[256]; + Eina_List *source; + const char *key; if (!parts) { EINA_LIST_FREE(*contents, content) evas_object_del(content); } - if (it->itc->func.content_get) + if ((!it->itc->func.content_get) && + ((it->itc->version < 3) || (!it->itc->func.reusable_content_get))) return; + + source = elm_widget_stringlist_get(edje_object_data_get(target, src)); + + EINA_LIST_FREE(source, key) { - Eina_List *source; - const char *key; + if (parts && fnmatch(parts, key, FNM_PERIOD)) + continue; - source = elm_widget_stringlist_get(edje_object_data_get(target, src)); + Evas_Object *old = NULL; + old = edje_object_part_swallow_get(target, key); - EINA_LIST_FREE(source, key) + // Reuse content by popping from the cache + content = NULL; + if (it->itc->func.reusable_content_get) + content = it->itc->func.reusable_content_get( + (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key, old); + if (!content) { - if (parts && fnmatch(parts, key, FNM_PERIOD)) - continue; - - Evas_Object *old = edje_object_part_swallow_get(target, key); - if (old) - { - *contents = eina_list_remove(*contents, old); - evas_object_del(old); - } - content = NULL; + // Call the content get if (it->itc->func.content_get) content = it->itc->func.content_get ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); - if (!content) continue; - + if (!content) goto out; + } + if (content != old) + { // FIXME: cause elm_layout sizing eval is delayed by smart calc, // genlist cannot get actual min size of edje. // This is workaround code to set min size directly. @@ -406,27 +412,33 @@ _item_content_realize(Elm_Gen_Item *it, evas_object_size_hint_min_set(content, minw, minh); } - *contents = eina_list_append(*contents, content); - if (!edje_object_part_swallow(target, key, content)) { ERR("%s (%p) can not be swallowed into %s", evas_object_type_get(content), content, key); - evas_object_hide(content); - continue; + evas_object_del(content); + goto out; } elm_widget_sub_object_add(WIDGET(it), content); - if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get())) - elm_widget_disabled_set(content, EINA_TRUE); + } + *contents = eina_list_append(*contents, content); - snprintf(buf, sizeof(buf), "elm,state,%s,visible", key); - edje_object_signal_emit(target, buf, "elm"); + if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get())) + elm_widget_disabled_set(content, EINA_TRUE); - if (_elm_config->atspi_mode && eo_isa(content, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) - { - eo_do(content, elm_interface_atspi_accessible_parent_set(EO_OBJ(it))); - elm_interface_atspi_accessible_children_changed_added_signal_emit(EO_OBJ(it), content); - } + snprintf(buf, sizeof(buf), "elm,state,%s,visible", key); + edje_object_signal_emit(target, buf, "elm"); +out: + if (old && content != old) + { + *contents = eina_list_remove(*contents, old); + evas_object_del(old); + } + + if (_elm_config->atspi_mode && eo_isa(content, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) + { + eo_do(content, elm_interface_atspi_accessible_parent_set(EO_OBJ(it))); + elm_interface_atspi_accessible_children_changed_added_signal_emit(EO_OBJ(it), content); } } } @@ -577,8 +589,11 @@ _view_clear(Evas_Object *view, Eina_List **texts, Eina_List **contents) edje_object_part_text_set(view, part, NULL); ELM_SAFE_FREE(*texts, elm_widget_stringlist_free); - EINA_LIST_FREE(*contents, c) - evas_object_del(c); + if (contents) + { + EINA_LIST_FREE(*contents, c) + evas_object_del(c); + } } static void @@ -662,7 +677,7 @@ _elm_genlist_item_unrealize(Elm_Gen_Item *it, eo_do(WIDGET(it), eo_event_callback_call(ELM_GENLIST_EVENT_UNREALIZED, EO_OBJ(it))); ELM_SAFE_FREE(it->long_timer, ecore_timer_del); - _view_clear(VIEW(it), &(it->texts), &(it->contents)); + _view_clear(VIEW(it), &(it->texts), NULL); ELM_SAFE_FREE(it->item_focus_chain, eina_list_free); eo_do(EO_OBJ(it), elm_wdg_item_track_cancel()); @@ -1550,11 +1565,18 @@ _item_cache_pop(Elm_Genlist_Data *sd, Item_Cache *itc) static void _item_cache_free(Item_Cache *itc) { + Evas_Object *c; + const char *part; + if (!itc) return; evas_object_del(itc->spacer); evas_object_del(itc->base_view); - eina_stringshare_del(itc->item_style); + itc->item_class = NULL; + EINA_LIST_FREE(itc->contents, c) + { + evas_object_del(c); + } ELM_SAFE_FREE(itc, free); } @@ -1587,7 +1609,7 @@ _item_cache_zero(Elm_Genlist_Data *sd) // add an item to item cache static Eina_Bool -_item_cache_add(Elm_Gen_Item *it) +_item_cache_add(Elm_Gen_Item *it, Eina_List *contents) { if (it->item->nocache_once || it->item->nocache) return EINA_FALSE; @@ -1611,7 +1633,8 @@ _item_cache_add(Elm_Gen_Item *it) } itc->spacer = it->spacer; itc->base_view = VIEW(it); - itc->item_style = eina_stringshare_add(it->itc->item_style); + itc->item_class = it->itc; + itc->contents = contents; if (it->item->type & ELM_GENLIST_ITEM_TREE) { itc->tree = 1; @@ -1677,9 +1700,9 @@ _item_cache_find(Elm_Gen_Item *it) EINA_INLIST_FOREACH_SAFE(sd->item_cache, l, itc) { if ((itc->tree == tree) && - (((!it->itc->item_style) && (!itc->item_style)) || - (it->itc->item_style && itc->item_style && - (!strcmp(it->itc->item_style, itc->item_style))))) + (((!it->itc) && (!itc->item_class)) || + (it->itc && itc->item_class && + (it->itc == itc->item_class)))) { itc = _item_cache_pop(sd, itc); if (!itc) continue; @@ -1689,6 +1712,8 @@ _item_cache_find(Elm_Gen_Item *it) itc->spacer = NULL; itc->base_view = NULL; + eina_list_free(itc->contents); + itc->contents = NULL; _item_cache_free(itc); return EINA_TRUE; } @@ -1696,6 +1721,18 @@ _item_cache_find(Elm_Gen_Item *it) return EINA_FALSE; } +static Eina_List * +_content_cache_add(Elm_Gen_Item *it, Eina_List **cache) +{ + Evas_Object *content = NULL; + EINA_LIST_FREE(it->contents, content) + { + *cache = eina_list_append(*cache, content); + } + + return *cache; +} + static char * _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED) { @@ -5171,10 +5208,12 @@ _decorate_item_finished_signal_cb(void *data, static void _item_unrealize(Elm_Gen_Item *it) { - Evas_Object *content; + Evas_Object *c; + Eina_List *cache = NULL; ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd); - EINA_LIST_FREE(it->item->flip_contents, content) - evas_object_del(content); + + EINA_LIST_FREE(it->item->flip_contents, c) + evas_object_del(c); /* access */ if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) @@ -5192,10 +5231,14 @@ _item_unrealize(Elm_Gen_Item *it) _decorate_item_unrealize(it); if (GL_IT(it)->wsd->decorate_all_mode) _decorate_all_item_unrealize(it); - if (!_item_cache_add(it)) + if (!_item_cache_add(it, _content_cache_add(it, &cache))) { ELM_SAFE_FREE(VIEW(it), evas_object_del); ELM_SAFE_FREE(it->spacer, evas_object_del); + EINA_LIST_FREE(cache, c) + { + evas_object_del(c); + } } it->states = NULL; diff --git a/src/lib/elm_genlist_common.h b/src/lib/elm_genlist_common.h index 567ec89..dd2cdbf 100644 --- a/src/lib/elm_genlist_common.h +++ b/src/lib/elm_genlist_common.h @@ -27,6 +27,11 @@ typedef Elm_Gen_Item_State_Get_Cb Elm_Genlist_Item_State_Get_Cb; typedef Elm_Gen_Item_Del_Cb Elm_Genlist_Item_Del_Cb; /** + * @see Elm_Gen_Item_Reusable_Content_Get_Cb + */ +typedef Elm_Gen_Item_Reusable_Content_Get_Cb Elm_Genlist_Reusable_Content_Get_Cb; + +/** * Create a new genlist item class in a given genlist widget. * * @return New allocated genlist item class. diff --git a/src/lib/elm_widget_genlist.h b/src/lib/elm_widget_genlist.h index f9c4c83..d1cb5f8 100644 --- a/src/lib/elm_widget_genlist.h +++ b/src/lib/elm_widget_genlist.h @@ -281,8 +281,9 @@ struct _Item_Cache EINA_INLIST; Evas_Object *base_view, *spacer; - const char *item_style; // it->itc->item_style + const Elm_Genlist_Item_Class *item_class; // it->itc Eina_Bool tree : 1; // it->group + Eina_List *contents; // content objects for reusing }; struct _Item_Size diff --git a/src/mobile_lib/elm_genlist.c b/src/mobile_lib/elm_genlist.c index 8e647cb..243db0c 100644 --- a/src/mobile_lib/elm_genlist.c +++ b/src/mobile_lib/elm_genlist.c @@ -322,6 +322,39 @@ _banded_item_bg_index_color_set(Elm_Gen_Item *it_top, Evas_Coord ox, Evas_Coord #endif static void +_item_content_free(Evas_Object *content) +{ + // FIXME: For animation, befor del, processing edc. + if (evas_object_smart_type_check(content, "elm_layout")) + edje_object_message_signal_process(elm_layout_edje_get(content)); + // FIXME: If parent-child relationship was broken before 'ic' + // is deleted, freeze_pop will not be called. ex) elm_slider + // If layout is used instead of edje, this problme can be + // solved. + if (elm_widget_is(content) && (0 != elm_widget_scroll_freeze_get(content))) + elm_widget_scroll_freeze_pop(content); + evas_object_del(content); +} + +static void +_item_cache_free(Elm_Genlist_Data *sd, Item_Cache *ic) +{ + Evas_Object *c; + if (!ic) return; + + if (ic->base_view) evas_object_del(ic->base_view); + ic->item_class = NULL; + EINA_LIST_FREE(ic->contents, c) + { + _item_content_free(c); + } + sd->item_cache = eina_inlist_remove(sd->item_cache, EINA_INLIST_GET(ic)); + sd->item_cache_count--; + // Free should be performed after inlist is poped + free(ic); +} + +static void _item_cache_all_free(Elm_Genlist_Data *sd) { // It would be better not to use @@ -329,39 +362,34 @@ _item_cache_all_free(Elm_Genlist_Data *sd) while (sd->item_cache) { Item_Cache *ic = EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache); - if (ic->base_view) evas_object_del(ic->base_view); - if (ic->item_style) eina_stringshare_del(ic->item_style); - sd->item_cache = eina_inlist_remove(sd->item_cache, EINA_INLIST_GET(ic)); - // Free should be performed after inlist is poped - free(ic); + _item_cache_free(sd, ic); } sd->item_cache = NULL; sd->item_cache_count = 0; } static void -_item_cache_push(Elm_Gen_Item *it) +_item_cache_push(Elm_Gen_Item *it, Eina_List *contents) { Elm_Genlist_Data *sd = GL_IT(it)->wsd; Item_Cache *ic = NULL; + Evas_Object *content; if (sd->no_cache) { if (VIEW(it)) evas_object_del(VIEW(it)); VIEW(it) = NULL; + EINA_LIST_FREE(contents, content) + { + _item_content_free(content); + } return; } if (sd->item_cache_count >= sd->item_cache_max) - { + { ic = EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache); - if (ic->base_view) evas_object_del(ic->base_view); - eina_stringshare_del(ic->item_style); - sd->item_cache = eina_inlist_remove(sd->item_cache, - sd->item_cache->last); - sd->item_cache_count--; - // Free should be performed after inlist is poped - free(ic); + _item_cache_free(sd, ic); } ic = ELM_NEW(Item_Cache); @@ -369,6 +397,10 @@ _item_cache_push(Elm_Gen_Item *it) { if (VIEW(it)) evas_object_del(VIEW(it)); VIEW(it) = NULL; + EINA_LIST_FREE(contents, content) + { + _item_content_free(content); + } return; } // set item's state as default before pushing item into cache. @@ -382,7 +414,8 @@ _item_cache_push(Elm_Gen_Item *it) ic->base_view = VIEW(it); ic->multiline = GL_IT(it)->multiline; - ic->item_style = eina_stringshare_add(it->itc->item_style); + ic->item_class = it->itc; + ic->contents = contents; evas_object_hide(ic->base_view); sd->item_cache = eina_inlist_prepend(sd->item_cache, EINA_INLIST_GET(ic)); @@ -398,12 +431,12 @@ _item_cache_pop(Elm_Gen_Item *it) Eina_Inlist *l; Elm_Genlist_Data *sd = GL_IT(it)->wsd; - if (!it->itc->item_style) return EINA_FALSE; + if (!it->itc) return EINA_FALSE; EINA_INLIST_FOREACH_SAFE(sd->item_cache, l, ic) { - if (ic->item_style && - (!strcmp(it->itc->item_style, ic->item_style))) + if (it->itc && ic->item_class && + (it->itc == ic->item_class)) { sd->item_cache = eina_inlist_remove(sd->item_cache, EINA_INLIST_GET(ic)); @@ -411,8 +444,9 @@ _item_cache_pop(Elm_Gen_Item *it) VIEW(it) = ic->base_view; GL_IT(it)->multiline = ic->multiline; - eina_stringshare_del(ic->item_style); + eina_list_free(ic->contents); + ic->contents = NULL; free(ic); return EINA_TRUE; } @@ -420,6 +454,18 @@ _item_cache_pop(Elm_Gen_Item *it) return EINA_FALSE; } +static Eina_List * +_content_cache_add(Elm_Gen_Item *it, Eina_List **cache) +{ + Evas_Object *content = NULL; + EINA_LIST_FREE(it->content_objs, content) + { + *cache = eina_list_append(*cache, content); + } + + return *cache; +} + // TIZEN_ONLY(20150828) : to prevent unnecessary genlist rendering // _changed is called instead of evas_object_smart_changed API. static void @@ -667,107 +713,111 @@ _changed_size_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSE _changed(GL_IT(it)->wsd->pan_obj); } -static Eina_List * +// FIXME: There are applications which do not use elm_win as top widget. +// This is workaround! Those could not use focus! +static Eina_Bool _focus_enabled(Evas_Object *obj) +{ + if (!elm_widget_focus_get(obj)) return EINA_FALSE; + + const Evas_Object *win = elm_widget_top_get(obj); + const char *type = evas_object_type_get(win); + + if (type && !strcmp(type, "elm_win")) + { + return elm_win_focus_highlight_enabled_get(win); + } + return EINA_FALSE; +} + +static void _item_content_realize(Elm_Gen_Item *it, Evas_Object *target, - Eina_List *contents, + Eina_List **contents, const char *src, const char *parts) { + Eina_Bool tmp; + Evas_Object *content; char buf[256]; + Eina_List *source; + const char *key; if (!parts) { - Evas_Object *c; - EINA_LIST_FREE(contents, c) - { - // FIXME: For animation, befor del, processing edc. - if (evas_object_smart_type_check(c, "elm_layout")) - edje_object_message_signal_process(elm_layout_edje_get(c)); - // FIXME: If parent-child relationship was broken before 'ic' - // is deleted, freeze_pop will not be called. ex) elm_slider - // If layout is used instead of edje, this problme can be - // solved. - if (elm_widget_is(c) && (0 != elm_widget_scroll_freeze_get(c))) - elm_widget_scroll_freeze_pop(c); - evas_object_del(c); - } + EINA_LIST_FREE(*contents, content) + _item_content_free(content); } - if (it->itc->func.content_get) + if ((!it->itc->func.content_get) && + ((it->itc->version < 3) || (!it->itc->func.reusable_content_get))) return; + + source = elm_widget_stringlist_get(edje_object_data_get(target, src)); + + EINA_LIST_FREE(source, key) { - const char *key; Evas_Object *ic = NULL; - Eina_List *source; Eina_Bool ret; - source = elm_widget_stringlist_get - (edje_object_data_get(target, src)); - - EINA_LIST_FREE(source, key) - { - if (parts && fnmatch(parts, key, FNM_PERIOD)) - continue; + if (parts && fnmatch(parts, key, FNM_PERIOD)) + continue; - Evas_Object *old = edje_object_part_swallow_get(target, key); - if (old) - { - contents = eina_list_remove(contents, old); - // FIXME: For animation, befor del, processing edc. - if (evas_object_smart_type_check(old, "elm_layout")) - edje_object_message_signal_process(elm_layout_edje_get(old)); - // FIXME: If parent-child relationship was broken before 'ic' - // is deleted, freeze_pop will not be called. ex) elm_slider - // If layout is used instead of edje, this problme can be - // solved. - if (elm_widget_is(old) && (0 != elm_widget_scroll_freeze_get(old))) - elm_widget_scroll_freeze_pop(old); - evas_object_del(old); - } + Evas_Object *old = NULL; + old = edje_object_part_swallow_get(target, key); + // Reuse content by popping from the cache + content = NULL; + if (it->itc->func.reusable_content_get) + content = it->itc->func.reusable_content_get( + (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key, old); + if (!content) + { + // Call the content get if (it->itc->func.content_get) - ic = it->itc->func.content_get + content = it->itc->func.content_get ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); - if (ic) + if (!content) goto out; + } + if (content != old) + { + // FIXME: cause elm_layout sizing eval is delayed by smart calc, + // genlist cannot get actual min size of edje. + // This is workaround code to set min size directly. + if (eo_class_get(content) == ELM_LAYOUT_CLASS) { - // TIZEN_ONLY(20150630): Add contents min height calculation for "full" style - if (eo_class_get(ic) == ELM_LAYOUT_CLASS) - { - Evas_Coord minw, minh; - - edje_object_size_min_calc(elm_layout_edje_get(ic), &minw, &minh); - evas_object_size_hint_min_set(ic, minw, minh); - } - // TIZEN_ONLY + Evas_Coord old_w, old_h, minw = 0, minh = 0; + evas_object_size_hint_min_get(content, &old_w, &old_h); + edje_object_size_min_calc(elm_layout_edje_get(content), &minw, &minh); - if (!edje_object_part_swallow(target, key, ic)) - { - WRN("%s (%p) can not be swallowed into %s", - evas_object_type_get(ic), ic, key); - continue; - } - if (eo_do_ret(EO_OBJ(it), ret, elm_wdg_item_disabled_get())) - elm_widget_disabled_set(ic, EINA_TRUE); - evas_object_show(ic); - contents = eina_list_append(contents, ic); + if (old_w > minw) minw = old_w; + if (old_h > minh) minw = old_h; + evas_object_size_hint_min_set(content, minw, minh); + } + if (!edje_object_part_swallow(target, key, content)) + { + ERR("%s (%p) can not be swallowed into %s", + evas_object_type_get(content), content, key); + evas_object_del(content); + goto out; + } + elm_widget_sub_object_add(WIDGET(it), content); + } + *contents = eina_list_append(*contents, content); - if (GL_IT(it)->wsd->realization_mode) - { - evas_object_event_callback_add - (ic, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, it); - } + if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get())) + elm_widget_disabled_set(content, EINA_TRUE); - snprintf(buf, sizeof(buf), "elm,state,%s,visible", key); - edje_object_signal_emit(target, buf, "elm"); - } + snprintf(buf, sizeof(buf), "elm,state,%s,visible", key); + edje_object_signal_emit(target, buf, "elm"); +out: + if (old && content != old) + { + *contents = eina_list_remove(*contents, old); + _item_content_free(old); } } #ifndef TIZEN_PROFILE_WEARABLE _banded_item_bg_add(it, target); #endif - - return contents; } static void @@ -880,18 +930,11 @@ _view_clear(Evas_Object *view, Eina_List **contents) (edje_object_data_get(view, "texts")); EINA_LIST_FREE(texts, part) edje_object_part_text_set(view, part, NULL); - EINA_LIST_FREE(*contents, c) + + if (contents) { - // FIXME: For animation, befor del, processing edc. - if (evas_object_smart_type_check(c, "elm_layout")) - edje_object_message_signal_process(elm_layout_edje_get(c)); - // FIXME: If parent-child relationship was broken before 'ic' - // is deleted, freeze_pop will not be called. ex) elm_slider - // If layout is used instead of edje, this problme can be - // solved. - if (elm_widget_is(c) && (0 != elm_widget_scroll_freeze_get(c))) - elm_widget_scroll_freeze_pop(c); - evas_object_del(c); + EINA_LIST_FREE(*contents, c) + _item_content_free(c); } } @@ -900,8 +943,7 @@ _view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **contents) { if (!view) return; _item_text_realize(it, view, NULL); - *contents = _item_content_realize(it, view, *contents, - "contents", NULL); + if (contents) _item_content_realize(it, view, contents, "contents", NULL); _item_state_realize(it, view, NULL); } @@ -1070,6 +1112,7 @@ _item_unrealize(Elm_Gen_Item *it, Eina_Bool calc) { Evas_Object *content; + Eina_List *cache = NULL; if (!it->realized) return; @@ -1110,7 +1153,7 @@ _item_unrealize(Elm_Gen_Item *it, EINA_LIST_FREE(GL_IT(it)->flip_content_objs, content) evas_object_del(content); if (it->spacer) evas_object_del(it->spacer); - _view_clear(VIEW(it), &(it->content_objs)); + _view_clear(VIEW(it), NULL); // TIZEN ONLY : for banded ux #ifndef TIZEN_PROFILE_WEARABLE @@ -1139,7 +1182,9 @@ _item_unrealize(Elm_Gen_Item *it, if (it->base->color_classes) edje_object_color_class_clear(VIEW(it)); // - _item_cache_push(it); + _item_cache_push(it, _content_cache_add(it, &cache)); + + it->realized = EINA_FALSE; } @@ -1568,9 +1613,8 @@ _item_realize(Elm_Gen_Item *it, edje_object_signal_emit(VIEW(it), SIGNAL_BG_CHANGE, "elm"); if (it->flipped) { - GL_IT(it)->flip_content_objs = - _item_content_realize(it, VIEW(it), GL_IT(it)->flip_content_objs, - "flips", NULL); + _item_content_realize(it, VIEW(it), &GL_IT(it)->flip_contents, + "flips", NULL); edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ENABLED, "elm"); } @@ -4988,9 +5032,8 @@ _item_update(Elm_Gen_Item *it) _view_inflate(VIEW(it), it, &(it->content_objs)); if (it->flipped) { - GL_IT(it)->flip_content_objs = - _item_content_realize(it, VIEW(it), GL_IT(it)->flip_content_objs, - "flips", NULL); + _item_content_realize(it, VIEW(it), &(GL_IT(it)->flip_content_objs), + "flips", NULL); edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ENABLED, "elm"); } if (GL_IT(it)->wsd->decorate_all_mode) @@ -5653,7 +5696,7 @@ _elm_genlist_elm_widget_atspi(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bo { elm_interface_atspi_accessible_added(EO_OBJ(it)); elm_interface_atspi_accessible_children_changed_added_signal_emit(sd->obj, EO_OBJ(it)); - EINA_LIST_FOREACH(it->contents, l, content) + EINA_LIST_FOREACH(it->content_objs, l, content) { if (eo_isa(content, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) { @@ -6918,27 +6961,23 @@ _elm_genlist_item_fields_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it, } if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT)) { - it->content_objs = _item_content_realize - (it, VIEW(it), it->content_objs, "contents", parts); + _item_content_realize(it, VIEW(it), &it->content_objs, "contents", parts); if (it->flipped) { - GL_IT(it)->flip_content_objs = - _item_content_realize(it, VIEW(it), GL_IT(it)->flip_content_objs, + _item_content_realize(it, VIEW(it), &GL_IT(it)->flip_content_objs, "flips", parts); } if (GL_IT(it)->deco_it_view) { - GL_IT(it)->deco_it_contents = - _item_content_realize(it, GL_IT(it)->deco_it_view, - GL_IT(it)->deco_it_contents, - "contents", parts); + _item_content_realize(it, GL_IT(it)->deco_it_view, + &GL_IT(it)->deco_it_contents, + "contents", parts); } if (GL_IT(it)->wsd->decorate_all_mode) { - GL_IT(it)->deco_all_contents = - _item_content_realize(it, it->deco_all_view, - GL_IT(it)->deco_all_contents, - "contents", parts); + _item_content_realize(it, it->deco_all_view, + &GL_IT(it)->deco_all_contents, + "contents", parts); } } @@ -7878,8 +7917,7 @@ _elm_genlist_item_flip_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, Eina_Bool fl if (it->flipped) { - GL_IT(it)->flip_content_objs = - _item_content_realize(it, VIEW(it), GL_IT(it)->flip_content_objs, + _item_content_realize(it, VIEW(it), &GL_IT(it)->flip_content_objs, "flips", NULL); edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ENABLED, "elm"); diff --git a/src/mobile_lib/elm_genlist_common.h b/src/mobile_lib/elm_genlist_common.h index e1f2cf1..76f6ee8 100644 --- a/src/mobile_lib/elm_genlist_common.h +++ b/src/mobile_lib/elm_genlist_common.h @@ -69,6 +69,12 @@ typedef Elm_Gen_Item_State_Get_Cb Elm_Genlist_Item_State_Get_Cb; typedef Elm_Gen_Item_Del_Cb Elm_Genlist_Item_Del_Cb; /** + * @see Elm_Gen_Item_Reusable_Content_Get_Cb + */ +typedef Elm_Gen_Item_Reusable_Content_Get_Cb Elm_Genlist_Reusable_Content_Get_Cb; + + +/** * @brief Create a new genlist item class in a given genlist widget. * * @details This adds genlist item class for the genlist widget. diff --git a/src/mobile_lib/elm_widget_genlist.h b/src/mobile_lib/elm_widget_genlist.h index 53e2270..43ab80a 100644 --- a/src/mobile_lib/elm_widget_genlist.h +++ b/src/mobile_lib/elm_widget_genlist.h @@ -312,12 +312,13 @@ struct _Item_Cache Evas_Object *base_view, *spacer; - const char *item_style; // it->itc->item_style + const Elm_Genlist_Item_Class *item_class; // it->itc Eina_Bool multiline; Eina_Bool selected : 1; // it->selected Eina_Bool disabled : 1; // it->disabled Eina_Bool expanded : 1; // it->item->expanded Eina_Bool tree : 1; // it->group + Eina_List *contents; // content objects for reusing }; typedef struct _Elm_Genlist_Pan_Data Elm_Genlist_Pan_Data;