summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSangHyeon Lee <sh10233.lee@samsung.com>2016-02-12 20:14:13 +0100
committerCedric BAIL <cedric@osg.samsung.com>2016-02-12 20:36:16 +0100
commit4c86a66f28876b68e92a90c8f741eed1130dd034 (patch)
treeb808cd685c34f294b94e688101fd98df929a55e5
parent7d77c0572dfcee970079eda515ae1ac4075c4f58 (diff)
genlist: add reusable_content_get item class function for support automatical content reusing in genlist.
Summary: Add new Item Class function reusable_content_get for improve genlist performance. If user want to reuse specific part contents, return old content which was passed by parameter of rreusable_content_get function. genlist will automatically caching those contents when item unrealized, and reusing it on item realizing. reusable_content_get will be performed content_get with old object caching. But if user return NULL in reusable_content_get, content_get is called to get new object. This feature is refered in Task T2813 @feature Test Plan: add test in genlist 1 case. Reviewers: raster, singh.amitesh, cedric Reviewed By: cedric Subscribers: smohanty, seoz, woohyun, Hermet, eagleeye Differential Revision: https://phab.enlightenment.org/D3252 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--src/bin/test_genlist.c34
-rw-r--r--src/lib/elm_gen.h12
-rw-r--r--src/lib/elm_general.eot3
-rw-r--r--src/lib/elm_genlist.c128
-rw-r--r--src/lib/elm_genlist_common.h5
-rw-r--r--src/lib/elm_widget_genlist.h1
6 files changed, 140 insertions, 43 deletions
diff --git a/src/bin/test_genlist.c b/src/bin/test_genlist.c
index ff640025a..483199d61 100644
--- a/src/bin/test_genlist.c
+++ b/src/bin/test_genlist.c
@@ -212,6 +212,35 @@ Eina_Bool gl_state_get(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, con
212 return EINA_FALSE; 212 return EINA_FALSE;
213} 213}
214 214
215Evas_Object *gl_reusable_content_get(void *data EINA_UNUSED, Evas_Object *obj, const char *part, Evas_Object *old)
216{
217 if (old && !strcmp(part, "elm.swallow.end"))
218 {
219 // Reuse old content
220 // Here need to add initializing and state changing
221 // for cached content.
222 // printf("content reuse for cached content %p, %s\n", old, part);
223 return old;
224 }
225 else
226 {
227 // Create new content object for non-reused part.
228 //printf("content create in reuse %p, %s\n", old, part);
229 char buf[PATH_MAX];
230 Evas_Object *ic = elm_icon_add(obj);
231 if (!strcmp(part, "elm.swallow.end"))
232 snprintf(buf, sizeof(buf), "%s/images/bubble.png", elm_app_data_dir_get());
233 else
234 snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get());
235 elm_image_file_set(ic, buf, NULL);
236 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
237 return ic;
238 }
239
240 // If return NULL value, content_get will be called to get new content.
241 // return NULL;
242}
243
215static void 244static void
216gl_sel(void *data, Evas_Object *obj, void *event_info) 245gl_sel(void *data, Evas_Object *obj, void *event_info)
217{ 246{
@@ -392,9 +421,12 @@ test_genlist(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i
392 api->itc1 = elm_genlist_item_class_new(); 421 api->itc1 = elm_genlist_item_class_new();
393 api->itc1->item_style = "default"; 422 api->itc1->item_style = "default";
394 api->itc1->func.text_get = gl_text_get1; 423 api->itc1->func.text_get = gl_text_get1;
395 api->itc1->func.content_get = gl_content_get; 424 api->itc1->func.content_get = NULL; // gl_content_get;
396 api->itc1->func.state_get = gl_state_get; 425 api->itc1->func.state_get = gl_state_get;
397 api->itc1->func.del = NULL; 426 api->itc1->func.del = NULL;
427 // use content_reuse function for reusing
428 // repeated content objects instead of content_get
429 api->itc1->func.reusable_content_get = gl_reusable_content_get;
398 430
399 bt_50 = elm_button_add(win); 431 bt_50 = elm_button_add(win);
400 elm_object_text_set(bt_50, "Go to 50"); 432 elm_object_text_set(bt_50, "Go to 50");
diff --git a/src/lib/elm_gen.h b/src/lib/elm_gen.h
index 8c1ce8476..08d6eb4d3 100644
--- a/src/lib/elm_gen.h
+++ b/src/lib/elm_gen.h
@@ -43,5 +43,17 @@ typedef void (*Elm_Gen_Item_Del_Cb)(void *data, Evas_Ob
43 */ 43 */
44typedef Eina_Bool (*Elm_Gen_Item_Filter_Get_Cb)(void *data, Evas_Object *obj, void *key); /**< Filter seeking class function for gen item classes. */ 44typedef Eina_Bool (*Elm_Gen_Item_Filter_Get_Cb)(void *data, Evas_Object *obj, void *key); /**< Filter seeking class function for gen item classes. */
45 45
46/**
47 * Reusable content get class function for Elm_Gen_Item_Class.
48 * @param data The data passed in the item creation function
49 * @param obj The base widget object
50 * @param part The part name of the swallow
51 * @param old The old content object for reusing
52 * @return The content object to swallow
53 *
54 * @since 1.18
55 */
56typedef 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. */
57
46#define ELM_GEN_ITEM_CLASS_VERSION 2 58#define ELM_GEN_ITEM_CLASS_VERSION 2
47#define ELM_GEN_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_VERSION, 0, 0 59#define ELM_GEN_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_VERSION, 0, 0
diff --git a/src/lib/elm_general.eot b/src/lib/elm_general.eot
index 68e7e1625..955ca6ca0 100644
--- a/src/lib/elm_general.eot
+++ b/src/lib/elm_general.eot
@@ -18,6 +18,9 @@ struct Elm.Gen.Item.Class.Functions
18 item classes. ]] 18 item classes. ]]
19 filter_get: Elm_Gen_Item_Filter_Get_Cb; [[ Filter seeking class function for 19 filter_get: Elm_Gen_Item_Filter_Get_Cb; [[ Filter seeking class function for
20 genlist/gengrid item classes. ]] 20 genlist/gengrid item classes. ]]
21 reusable_content_get: Elm_Gen_Item_Reusable_Content_Get_Cb; [[ Reusable content get class
22 function for gen item classes. ]]
23
21} 24}
22 25
23struct Elm.Gen.Item.Class 26struct Elm.Gen.Item.Class
diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c
index 4848ebb50..742c38502 100644
--- a/src/lib/elm_genlist.c
+++ b/src/lib/elm_genlist.c
@@ -365,7 +365,7 @@ _item_content_realize(Elm_Gen_Item *it,
365 EINA_LIST_FREE(*contents, content) 365 EINA_LIST_FREE(*contents, content)
366 evas_object_del(content); 366 evas_object_del(content);
367 } 367 }
368 if (it->itc->func.content_get) 368 if (it->itc->func.content_get || it->itc->func.reusable_content_get)
369 { 369 {
370 Eina_List *source; 370 Eina_List *source;
371 const char *key; 371 const char *key;
@@ -377,46 +377,61 @@ _item_content_realize(Elm_Gen_Item *it,
377 if (parts && fnmatch(parts, key, FNM_PERIOD)) 377 if (parts && fnmatch(parts, key, FNM_PERIOD))
378 continue; 378 continue;
379 379
380 Evas_Object *old = edje_object_part_swallow_get(target, key); 380 Evas_Object *old = NULL;
381 if (old) 381 old = edje_object_part_swallow_get(target, key);
382 { 382
383 *contents = eina_list_remove(*contents, old); 383 // Reuse content by popping from the cache
384 evas_object_del(old);
385 }
386 content = NULL; 384 content = NULL;
387 if (it->itc->func.content_get) 385 if (it->itc->func.reusable_content_get)
388 content = it->itc->func.content_get 386 content = it->itc->func.reusable_content_get(
389 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); 387 (void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key, old);
390 if (!content) continue; 388 if (!content)
391
392 // FIXME: cause elm_layout sizing eval is delayed by smart calc,
393 // genlist cannot get actual min size of edje.
394 // This is workaround code to set min size directly.
395 if (eo_class_get(content) == ELM_LAYOUT_CLASS)
396 { 389 {
397 Evas_Coord old_w, old_h, minw = 0, minh = 0; 390 // Call the content get
398 evas_object_size_hint_min_get(content, &old_w, &old_h); 391 if (it->itc->func.content_get)
399 edje_object_size_min_calc(elm_layout_edje_get(content), &minw, &minh); 392 content = it->itc->func.content_get
400 393 ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key);
401 if (old_w > minw) minw = old_w; 394 if (!content) continue;
402 if (old_h > minh) minw = old_h;
403 evas_object_size_hint_min_set(content, minw, minh);
404 } 395 }
405 396
406 *contents = eina_list_append(*contents, content); 397 if (content != old)
407 if (!edje_object_part_swallow(target, key, content))
408 { 398 {
409 ERR("%s (%p) can not be swallowed into %s", 399 // FIXME: cause elm_layout sizing eval is delayed by smart calc,
410 evas_object_type_get(content), content, key); 400 // genlist cannot get actual min size of edje.
411 evas_object_hide(content); 401 // This is workaround code to set min size directly.
412 continue; 402 if (eo_class_get(content) == ELM_LAYOUT_CLASS)
403 {
404 Evas_Coord old_w, old_h, minw = 0, minh = 0;
405 evas_object_size_hint_min_get(content, &old_w, &old_h);
406 edje_object_size_min_calc(elm_layout_edje_get(content), &minw, &minh);
407
408 if (old_w > minw) minw = old_w;
409 if (old_h > minh) minw = old_h;
410 evas_object_size_hint_min_set(content, minw, minh);
411 }
412
413 *contents = eina_list_append(*contents, content);
414 if (!edje_object_part_swallow(target, key, content))
415 {
416 ERR("%s (%p) can not be swallowed into %s",
417 evas_object_type_get(content), content, key);
418 evas_object_hide(content);
419 continue;
420 }
421 elm_widget_sub_object_add(WIDGET(it), content);
413 } 422 }
414 elm_widget_sub_object_add(WIDGET(it), content); 423
415 if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get())) 424 if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()))
416 elm_widget_disabled_set(content, EINA_TRUE); 425 elm_widget_disabled_set(content, EINA_TRUE);
417 426
418 snprintf(buf, sizeof(buf), "elm,state,%s,visible", key); 427 snprintf(buf, sizeof(buf), "elm,state,%s,visible", key);
419 edje_object_signal_emit(target, buf, "elm"); 428 edje_object_signal_emit(target, buf, "elm");
429
430 if (old && content != old)
431 {
432 *contents = eina_list_remove(*contents, old);
433 evas_object_del(old);
434 }
420 } 435 }
421 } 436 }
422} 437}
@@ -544,8 +559,11 @@ _view_clear(Evas_Object *view, Eina_List **texts, Eina_List **contents)
544 edje_object_part_text_set(view, part, NULL); 559 edje_object_part_text_set(view, part, NULL);
545 ELM_SAFE_FREE(*texts, elm_widget_stringlist_free); 560 ELM_SAFE_FREE(*texts, elm_widget_stringlist_free);
546 561
547 EINA_LIST_FREE(*contents, c) 562 if (contents)
548 evas_object_del(c); 563 {
564 EINA_LIST_FREE(*contents, c)
565 evas_object_del(c);
566 }
549} 567}
550 568
551static void 569static void
@@ -626,7 +644,7 @@ _elm_genlist_item_unrealize(Elm_Gen_Item *it,
626 eo_do(WIDGET(it), eo_event_callback_call(ELM_GENLIST_EVENT_UNREALIZED, EO_OBJ(it))); 644 eo_do(WIDGET(it), eo_event_callback_call(ELM_GENLIST_EVENT_UNREALIZED, EO_OBJ(it)));
627 ELM_SAFE_FREE(it->long_timer, ecore_timer_del); 645 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
628 646
629 _view_clear(VIEW(it), &(it->texts), &(it->contents)); 647 _view_clear(VIEW(it), &(it->texts), NULL);
630 ELM_SAFE_FREE(it->item_focus_chain, eina_list_free); 648 ELM_SAFE_FREE(it->item_focus_chain, eina_list_free);
631 649
632 eo_do(EO_OBJ(it), elm_wdg_item_track_cancel()); 650 eo_do(EO_OBJ(it), elm_wdg_item_track_cancel());
@@ -1306,8 +1324,7 @@ _elm_genlist_item_state_update(Elm_Gen_Item *it)
1306} 1324}
1307 1325
1308static void 1326static void
1309_view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **sources, 1327_view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **sources, Eina_List **contents)
1310 Eina_List **contents)
1311{ 1328{
1312 if (!view) return; 1329 if (!view) return;
1313 if (sources) _item_text_realize(it, view, sources, NULL); 1330 if (sources) _item_text_realize(it, view, sources, NULL);
@@ -1487,11 +1504,18 @@ _item_cache_pop(Elm_Genlist_Data *sd, Item_Cache *itc)
1487static void 1504static void
1488_item_cache_free(Item_Cache *itc) 1505_item_cache_free(Item_Cache *itc)
1489{ 1506{
1507 Evas_Object *c;
1508 const char *part;
1509
1490 if (!itc) return; 1510 if (!itc) return;
1491 1511
1492 evas_object_del(itc->spacer); 1512 evas_object_del(itc->spacer);
1493 evas_object_del(itc->base_view); 1513 evas_object_del(itc->base_view);
1494 eina_stringshare_del(itc->item_style); 1514 eina_stringshare_del(itc->item_style);
1515 EINA_LIST_FREE(itc->contents, c)
1516 {
1517 evas_object_del(c);
1518 }
1495 ELM_SAFE_FREE(itc, free); 1519 ELM_SAFE_FREE(itc, free);
1496} 1520}
1497 1521
@@ -1524,7 +1548,7 @@ _item_cache_zero(Elm_Genlist_Data *sd)
1524 1548
1525// add an item to item cache 1549// add an item to item cache
1526static Eina_Bool 1550static Eina_Bool
1527_item_cache_add(Elm_Gen_Item *it) 1551_item_cache_add(Elm_Gen_Item *it, Eina_List *contents)
1528{ 1552{
1529 if (it->item->nocache_once || it->item->nocache) return EINA_FALSE; 1553 if (it->item->nocache_once || it->item->nocache) return EINA_FALSE;
1530 1554
@@ -1549,6 +1573,7 @@ _item_cache_add(Elm_Gen_Item *it)
1549 itc->spacer = it->spacer; 1573 itc->spacer = it->spacer;
1550 itc->base_view = VIEW(it); 1574 itc->base_view = VIEW(it);
1551 itc->item_style = eina_stringshare_add(it->itc->item_style); 1575 itc->item_style = eina_stringshare_add(it->itc->item_style);
1576 itc->contents = contents;
1552 if (it->item->type & ELM_GENLIST_ITEM_TREE) 1577 if (it->item->type & ELM_GENLIST_ITEM_TREE)
1553 { 1578 {
1554 itc->tree = 1; 1579 itc->tree = 1;
@@ -1622,7 +1647,8 @@ _item_cache_find(Elm_Gen_Item *it)
1622 VIEW(it) = itc->base_view; 1647 VIEW(it) = itc->base_view;
1623 itc->spacer = NULL; 1648 itc->spacer = NULL;
1624 itc->base_view = NULL; 1649 itc->base_view = NULL;
1625 1650 eina_list_free(itc->contents);
1651 itc->contents = NULL;
1626 _item_cache_free(itc); 1652 _item_cache_free(itc);
1627 return EINA_TRUE; 1653 return EINA_TRUE;
1628 } 1654 }
@@ -1630,6 +1656,18 @@ _item_cache_find(Elm_Gen_Item *it)
1630 return EINA_FALSE; 1656 return EINA_FALSE;
1631} 1657}
1632 1658
1659static Eina_List *
1660_content_cache_add(Elm_Gen_Item *it, Eina_List **cache)
1661{
1662 Evas_Object *content = NULL;
1663 EINA_LIST_FREE(it->contents, content)
1664 {
1665 *cache = eina_list_append(*cache, content);
1666 }
1667
1668 return *cache;
1669}
1670
1633static char * 1671static char *
1634_access_info_cb(void *data, Evas_Object *obj EINA_UNUSED) 1672_access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
1635{ 1673{
@@ -4212,7 +4250,7 @@ _item_mouse_down_cb(void *data,
4212 else sd->on_hold = EINA_FALSE; 4250 else sd->on_hold = EINA_FALSE;
4213 if (sd->on_hold) return; 4251 if (sd->on_hold) return;
4214 sd->wasselected = it->selected; 4252 sd->wasselected = it->selected;
4215 4253
4216 ecore_timer_del(it->item->swipe_timer); 4254 ecore_timer_del(it->item->swipe_timer);
4217 it->item->swipe_timer = ecore_timer_add(SWIPE_TIME, _swipe_cancel, it); 4255 it->item->swipe_timer = ecore_timer_add(SWIPE_TIME, _swipe_cancel, it);
4218 ELM_SAFE_FREE(it->long_timer, ecore_timer_del); 4256 ELM_SAFE_FREE(it->long_timer, ecore_timer_del);
@@ -5074,9 +5112,11 @@ _decorate_item_finished_signal_cb(void *data,
5074static void 5112static void
5075_item_unrealize(Elm_Gen_Item *it) 5113_item_unrealize(Elm_Gen_Item *it)
5076{ 5114{
5077 Evas_Object *content; 5115 Evas_Object *c;
5078 EINA_LIST_FREE(it->item->flip_contents, content) 5116 Eina_List *cache = NULL;
5079 evas_object_del(content); 5117
5118 EINA_LIST_FREE(it->item->flip_contents, c)
5119 evas_object_del(c);
5080 5120
5081 /* access */ 5121 /* access */
5082 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) 5122 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
@@ -5086,10 +5126,14 @@ _item_unrealize(Elm_Gen_Item *it)
5086 _decorate_item_unrealize(it); 5126 _decorate_item_unrealize(it);
5087 if (GL_IT(it)->wsd->decorate_all_mode) _decorate_all_item_unrealize(it); 5127 if (GL_IT(it)->wsd->decorate_all_mode) _decorate_all_item_unrealize(it);
5088 5128
5089 if (!_item_cache_add(it)) 5129 if (!_item_cache_add(it, _content_cache_add(it, &cache)))
5090 { 5130 {
5091 ELM_SAFE_FREE(VIEW(it), evas_object_del); 5131 ELM_SAFE_FREE(VIEW(it), evas_object_del);
5092 ELM_SAFE_FREE(it->spacer, evas_object_del); 5132 ELM_SAFE_FREE(it->spacer, evas_object_del);
5133 EINA_LIST_FREE(cache, c)
5134 {
5135 evas_object_del(c);
5136 }
5093 } 5137 }
5094 5138
5095 it->states = NULL; 5139 it->states = NULL;
diff --git a/src/lib/elm_genlist_common.h b/src/lib/elm_genlist_common.h
index 094e1eba8..c2a2ee1b9 100644
--- a/src/lib/elm_genlist_common.h
+++ b/src/lib/elm_genlist_common.h
@@ -26,6 +26,11 @@ typedef Elm_Gen_Item_Del_Cb Elm_Genlist_Item_Del_Cb;
26typedef Elm_Gen_Item_Filter_Get_Cb Elm_Genlist_Item_Filter_Get_Cb; 26typedef Elm_Gen_Item_Filter_Get_Cb Elm_Genlist_Item_Filter_Get_Cb;
27 27
28/** 28/**
29 * @see Elm_Gen_Item_Reusable_Content_Get_Cb
30 */
31typedef Elm_Gen_Item_Reusable_Content_Get_Cb Elm_Genlist_Reusable_Content_Get_Cb;
32
33/**
29 * Create a new genlist item class in a given genlist widget. 34 * Create a new genlist item class in a given genlist widget.
30 * 35 *
31 * @return New allocated genlist item class. 36 * @return New allocated genlist item class.
diff --git a/src/lib/elm_widget_genlist.h b/src/lib/elm_widget_genlist.h
index 8107e20ef..bf067553e 100644
--- a/src/lib/elm_widget_genlist.h
+++ b/src/lib/elm_widget_genlist.h
@@ -278,6 +278,7 @@ struct _Item_Cache
278 Evas_Object *base_view, *spacer; 278 Evas_Object *base_view, *spacer;
279 const char *item_style; // it->itc->item_style 279 const char *item_style; // it->itc->item_style
280 Eina_Bool tree : 1; // it->group 280 Eina_Bool tree : 1; // it->group
281 Eina_List *contents; // content objects for reusing
281}; 282};
282 283
283struct _Item_Size 284struct _Item_Size