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.
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);
}
}
}
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
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());
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);
}
// 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;
}
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;
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;
itc->spacer = NULL;
itc->base_view = NULL;
+ eina_list_free(itc->contents);
+ itc->contents = NULL;
_item_cache_free(itc);
return EINA_TRUE;
}
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)
{
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)
_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;
#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
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);
{
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.
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));
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));
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;
}
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
_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
(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);
}
}
{
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);
}
Eina_Bool calc)
{
Evas_Object *content;
+ Eina_List *cache = NULL;
if (!it->realized) return;
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
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;
}
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");
}
_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)
{
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))
{
}
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);
}
}
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");