From 5dcb5a532d2a78643a22a48f094708df188d8958 Mon Sep 17 00:00:00 2001 From: seoz Date: Thu, 21 Apr 2011 11:47:36 +0000 Subject: [PATCH] Elementary genlist: Added genlist mode feature. I introduce a new concept to genlist. I named it "genlist mode" after I discussed it with raster. Using this feature, one can activate/deactivate any mode(effect) to an item. The mode is defined in genlist item edc. You can watch a sample video on youtube. http://www.youtube.com/watch?v=ZPbwpzwwiS8 I created two sample mode: Slide and Rotate. [Feature Description] - One can activate a specific mode to an item. - One item is activated at one time while others are deactivated. - Genlist handles deactivating other items when one item is activated. - There are two different view: before activated, after activated. - Genlist creates the second view when the first view is activated. Usually the first view is animated. - Genlist destroys the second view when the item finishes deactivating. - Creating/Destroying the second view on the fly gives performance enhancement because there is no reason to hold all objects in two views all the time. - Mode is defined in genlist edc so one can easily add it more. - Mode edc style is separated from normal genlist styles. One can combine any genlist style with mode edc style. [API] - EAPI void elm_genlist_item_mode_set(Elm_Genlist_Item *it, const char *mode_type, Eina_Bool mode_set) EINA_ARG_NONNULL(1, 2); Activate/Deactivate a mode to an item. - EAPI const char *elm_genlist_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); Get activated mode name. - EAPI const Elm_Genlist_Item *elm_genlist_mode_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); Get activated item. [Structure] - Elm_Genlist_Item Added const char *mode_item_style; [Usage] - Set mode style name to genlist item class. itc.mode_item_style = "mode"; - Activated mode to an item whenever you want. elm_genlist_item_mode_set(it, "slide", EINA_TRUE); git-svn-id: https://svn.enlightenment.org/svn/e/trunk/elementary@58791 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- data/themes/default.edc | 669 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/test.c | 2 + src/bin/test_genlist.c | 152 +++++++++++ src/bin/test_store.c | 2 +- src/lib/Elementary.h.in | 4 + src/lib/elm_genlist.c | 326 ++++++++++++++++++++++- 6 files changed, 1148 insertions(+), 7 deletions(-) diff --git a/data/themes/default.edc b/data/themes/default.edc index 2599027..4c9c5fd 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -26005,6 +26005,675 @@ collections { } } + group { name: "elm/genlist/item/mode/default"; + data.item: "stacking" "above"; + data.item: "selectraise" "on"; + data.item: "labels" "elm.text.mode"; + data.item: "icons" "elm.swallow.mode"; + data.item: "mode_part" "elm.swallow.origin"; + data.item: "treesize" "20"; + images { + image: "bt_sm_base1.png" COMP; + image: "bt_sm_shine.png" COMP; + image: "bt_sm_hilight.png" COMP; + image: "ilist_1.png" COMP; + image: "ilist_item_shadow.png" COMP; + } + + parts { + part { + name: "event"; + type: RECT; + repeat_events: 1; + description { + state: "default" 0.0; + color: 0 0 0 0; + } + } + part { + name: "base_sh"; + mouse_events: 0; + description { + state: "default" 0.0; + align: 0.0 0.0; + min: 0 10; + fixed: 1 1; + rel1 { + to: "base"; + relative: 0.0 1.0; + offset: 0 0; + } + rel2 { + to: "base"; + relative: 1.0 1.0; + offset: -1 0; + } + image { + normal: "ilist_item_shadow.png"; + } + fill.smooth: 0; + } + } + part { + name: "base"; + mouse_events: 0; + description { + state: "default" 0.0; + image { + normal: "ilist_1.png"; + border: 2 2 2 2; + } + fill.smooth: 0; + } + } + part { name: "bg"; + clip_to: "disclip"; + mouse_events: 0; + description { state: "default" 0.0; + visible: 0; + color: 255 255 255 0; + rel1 { + relative: 0.0 0.0; + offset: -5 -5; + } + rel2 { + relative: 1.0 1.0; + offset: 4 4; + } + image { + normal: "bt_sm_base1.png"; + border: 6 6 6 6; + } + image.middle: SOLID; + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 255 255 255 255; + rel1 { + relative: 0.0 0.0; + offset: -2 -2; + } + rel2 { + relative: 1.0 1.0; + offset: 1 1; + } + } + } + part { name: "elm.text.mode"; + clip_to: "disclip"; + type: TEXT; + scale: 1; + description { state: "default" 0.0; + rel2.relative: 0.5 1.0; + color: 0 0 0 255; + text { + font: "Sans"; + size: 10; + min: 1 1; + align: 0.5 0.5; + text_class: "list_item"; + } + } + } + part { name: "elm.swallow.mode"; + clip_to: "disclip"; + type: SWALLOW; + description { state: "default" 0.0; + rel1.relative: 0.5 0.0; + } + } + part { name: "fg1"; + clip_to: "disclip"; + mouse_events: 0; + description { state: "default" 0.0; + visible: 0; + color: 255 255 255 0; + rel1.to: "bg"; + rel2.relative: 1.0 0.5; + rel2.to: "bg"; + image { + normal: "bt_sm_hilight.png"; + border: 6 6 6 0; + } + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 255 255 255 255; + } + } + part { name: "fg2"; + clip_to: "disclip"; + mouse_events: 0; + description { state: "default" 0.0; + visible: 0; + color: 255 255 255 0; + rel1.to: "bg"; + rel2.to: "bg"; + image { + normal: "bt_sm_shine.png"; + border: 6 6 6 0; + } + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 255 255 255 255; + } + } + // Transparent part between base parts and slidable parts + part { name: "event_block_layer"; + type: RECT; + clip_to: "disclip"; + mouse_events: 1; + description { state: "default" 0.0; + rel1.to: "base"; + rel2.to: "base"; + color: 0 0 0 0; + } + description { state: "repeat_events" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + part { name: "pers"; + clip_to: "disclip"; + type: RECT; + description { state: "default" 0.0; + rel1.relative: 0.0 1.0; + } + } + part { name: "elm.swallow.origin"; + clip_to: "disclip"; + type: SWALLOW; + description { state: "default" 0.0; + fixed: 1 0; + align: 0.0 0.5; + } + description { state: "slide" 0.0; + inherit: "default" 0.0; + rel1.relative: 1 0; + rel2.relative: 2 1; + } + description { state: "rotate" 0.0; + inherit: "default" 0.0; + map { + perspective: "pers"; + on: 1; + smooth: 1; + perspective_on: 1; + backface_cull: 1; + rotation { + center: "pers"; + x: 0.0; + y: 0.0; + z: 0.0; + } + } + } + description { state: "rotate" 1.0; + inherit: "default" 0.0; + map { + perspective: "pers"; + on: 1; + smooth: 1; + perspective_on: 1; + backface_cull: 1; + rotation { + center: "pers"; + x: 90.0; + y: 0.0; + z: 0.0; + } + } + } + } + part { name: "disclip"; + type: RECT; + description { state: "default" 0.0; + rel1.to: "bg"; + rel2.to: "bg"; + } + description { state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 64; + } + } + } + programs { + program { + name: "go_active"; + signal: "elm,state,selected"; + source: "elm"; + action: STATE_SET "selected" 0.0; + target: "bg"; + target: "fg1"; + target: "fg2"; + } + program { + name: "go_passive"; + signal: "elm,state,unselected"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "bg"; + target: "fg1"; + target: "fg2"; + transition: LINEAR 0.1; + } + program { + name: "go_disabled"; + signal: "elm,state,disabled"; + source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "disclip"; + } + program { + name: "go_enabled"; + signal: "elm,state,enabled"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "disclip"; + } + program { + name: "slide_right"; + signal: "elm,state,slide,active"; + source: "elm"; + action: STATE_SET "slide" 0.0; + target: "elm.swallow.origin"; + transition: ACCELERATE 0.5; + after: "unblock_event"; + } + program { + name: "unblock_event"; + action: STATE_SET "repeat_events" 0.0; + target: "event_block_layer"; + } + program { + name: "slide_left"; + signal: "elm,state,slide,passive"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "event_block_layer"; + after: "slide_left2"; + } + program { + name: "slide_left2"; + action: STATE_SET "default" 0.0; + target: "elm.swallow.origin"; + transition: DECELERATE 0.5; + after: "slide_left_finished"; + } + program { + name: "slide_left_finished"; + action: SIGNAL_EMIT "elm,state,slide,passive,finished" "elm"; + } + program { + name: "rotate_on"; + signal: "elm,state,rotate,active"; + source: "elm"; + action: STATE_SET "rotate" 0.0; + target: "elm.swallow.origin"; + after: "rotate_on2"; + } + program { + name: "rotate_on2"; + action: STATE_SET "rotate" 1.0; + target: "elm.swallow.origin"; + transition: LINEAR 0.5; + after: "unblock_event"; + } + program { + name: "rotate_off"; + signal: "elm,state,rotate,passive"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "event_block_layer"; + after: "rotate_off2"; + } + program { + name: "rotate_off2"; + action: STATE_SET "rotate" 0.0; + transition: LINEAR 0.5; + target: "elm.swallow.origin"; + after: "rotate_off3"; + } + program { + name: "rotate_off3"; + action: STATE_SET "default" 0.0; + target: "elm.swallow.origin"; + after: "rotate_off_finished"; + } + program { + name: "rotate_off_finished"; + action: SIGNAL_EMIT "elm,state,rotate,passive,finished" "elm"; + } + } + } + + group { name: "elm/genlist/item_odd/mode/default"; + data.item: "stacking" "below"; + data.item: "selectraise" "on"; + data.item: "labels" "elm.text.mode"; + data.item: "icons" "elm.swallow.mode"; + data.item: "mode_part" "elm.swallow.origin"; + data.item: "treesize" "20"; + images { + image: "bt_sm_base1.png" COMP; + image: "bt_sm_shine.png" COMP; + image: "bt_sm_hilight.png" COMP; + image: "ilist_2.png" COMP; + } + + parts { + part { + name: "event"; + type: RECT; + repeat_events: 1; + description { + state: "default" 0.0; + color: 0 0 0 0; + } + } + part { + name: "base"; + mouse_events: 0; + description { + state: "default" 0.0; + image { + normal: "ilist_2.png"; + border: 2 2 2 2; + } + fill.smooth: 0; + } + } + part { name: "bg"; + clip_to: "disclip"; + mouse_events: 0; + description { state: "default" 0.0; + visible: 0; + color: 255 255 255 0; + rel1 { + relative: 0.0 0.0; + offset: -5 -5; + } + rel2 { + relative: 1.0 1.0; + offset: 4 4; + } + image { + normal: "bt_sm_base1.png"; + border: 6 6 6 6; + } + image.middle: SOLID; + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 255 255 255 255; + rel1 { + relative: 0.0 0.0; + offset: -2 -2; + } + rel2 { + relative: 1.0 1.0; + offset: 1 1; + } + } + } + part { name: "elm.text.mode"; + clip_to: "disclip"; + type: TEXT; + scale: 1; + description { state: "default" 0.0; + rel2.relative: 0.5 1.0; + color: 0 0 0 255; + text { + font: "Sans"; + size: 10; + min: 1 1; + align: 0.5 0.5; + text_class: "list_item"; + } + } + } + part { name: "elm.swallow.mode"; + clip_to: "disclip"; + type: SWALLOW; + description { state: "default" 0.0; + rel1.relative: 0.5 0.0; + } + } + part { name: "fg1"; + clip_to: "disclip"; + mouse_events: 0; + description { state: "default" 0.0; + visible: 0; + color: 255 255 255 0; + rel1.to: "bg"; + rel2.relative: 1.0 0.5; + rel2.to: "bg"; + image { + normal: "bt_sm_hilight.png"; + border: 6 6 6 0; + } + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 255 255 255 255; + } + } + part { name: "fg2"; + clip_to: "disclip"; + mouse_events: 0; + description { state: "default" 0.0; + visible: 0; + color: 255 255 255 0; + rel1.to: "bg"; + rel2.to: "bg"; + image { + normal: "bt_sm_shine.png"; + border: 6 6 6 0; + } + } + description { state: "selected" 0.0; + inherit: "default" 0.0; + visible: 1; + color: 255 255 255 255; + } + } + // Transparent part between base parts and slidable parts + part { name: "event_block_layer"; + type: RECT; + clip_to: "disclip"; + mouse_events: 1; + description { state: "default" 0.0; + rel1.to: "base"; + rel2.to: "base"; + color: 0 0 0 0; + } + description { state: "repeat_events" 0.0; + inherit: "default" 0.0; + visible: 0; + } + } + part { name: "pers"; + clip_to: "disclip"; + type: RECT; + description { state: "default" 0.0; + rel1.relative: 0.0 1.0; + } + } + part { name: "elm.swallow.origin"; + clip_to: "disclip"; + type: SWALLOW; + description { state: "default" 0.0; + fixed: 1 0; + align: 0.0 0.5; + } + description { state: "slide" 0.0; + inherit: "default" 0.0; + rel1.relative: 1 0; + rel2.relative: 2 1; + } + description { state: "rotate" 0.0; + inherit: "default" 0.0; + map { + perspective: "pers"; + on: 1; + smooth: 1; + perspective_on: 1; + backface_cull: 1; + rotation { + center: "pers"; + x: 0.0; + y: 0.0; + z: 0.0; + } + } + } + description { state: "rotate" 1.0; + inherit: "default" 0.0; + map { + perspective: "pers"; + on: 1; + smooth: 1; + perspective_on: 1; + backface_cull: 1; + rotation { + center: "pers"; + x: 90.0; + y: 0.0; + z: 0.0; + } + } + } + } + part { name: "disclip"; + type: RECT; + description { state: "default" 0.0; + rel1.to: "bg"; + rel2.to: "bg"; + } + description { state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 64; + } + } + } + programs { + program { + name: "go_active"; + signal: "elm,state,selected"; + source: "elm"; + action: STATE_SET "selected" 0.0; + target: "bg"; + target: "fg1"; + target: "fg2"; + } + program { + name: "go_passive"; + signal: "elm,state,unselected"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "bg"; + target: "fg1"; + target: "fg2"; + transition: LINEAR 0.1; + } + program { + name: "go_disabled"; + signal: "elm,state,disabled"; + source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "disclip"; + } + program { + name: "go_enabled"; + signal: "elm,state,enabled"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "disclip"; + } + program { + name: "slide_right"; + signal: "elm,state,slide,active"; + source: "elm"; + action: STATE_SET "slide" 0.0; + target: "elm.swallow.origin"; + transition: ACCELERATE 0.5; + after: "unblock_event"; + } + program { + name: "unblock_event"; + action: STATE_SET "repeat_events" 0.0; + target: "event_block_layer"; + } + program { + name: "slide_left"; + signal: "elm,state,slide,passive"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "event_block_layer"; + after: "slide_left2"; + } + program { + name: "slide_left2"; + action: STATE_SET "default" 0.0; + target: "elm.swallow.origin"; + transition: DECELERATE 0.5; + after: "slide_left_finished"; + } + program { + name: "slide_left_finished"; + action: SIGNAL_EMIT "elm,state,slide,passive,finished" "elm"; + } + program { + name: "rotate_on"; + signal: "elm,state,rotate,active"; + source: "elm"; + action: STATE_SET "rotate" 0.0; + target: "elm.swallow.origin"; + after: "rotate_on2"; + } + program { + name: "rotate_on2"; + action: STATE_SET "rotate" 1.0; + target: "elm.swallow.origin"; + transition: LINEAR 0.5; + after: "unblock_event"; + } + program { + name: "rotate_off"; + signal: "elm,state,rotate,passive"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "event_block_layer"; + after: "rotate_off2"; + } + program { + name: "rotate_off2"; + signal: "elm,state,rotate,passive"; + source: "elm"; + action: STATE_SET "rotate" 0.0; + transition: LINEAR 0.5; + target: "elm.swallow.origin"; + after: "rotate_off3"; + } + program { + name: "rotate_off3"; + action: STATE_SET "default" 0.0; + target: "elm.swallow.origin"; + after: "rotate_off_finished"; + } + program { + name: "rotate_off_finished"; + action: SIGNAL_EMIT "elm,state,rotate,passive,finished" "elm"; + } + } + } + /////////////////////////////////////////////////////////////////////////////// group { name: "elm/pager/base/default"; data.item: "onshow" "raise"; diff --git a/src/bin/test.c b/src/bin/test.c index edcc1e1..5851a28 100644 --- a/src/bin/test.c +++ b/src/bin/test.c @@ -67,6 +67,7 @@ void test_genlist6(void *data, Evas_Object *obj, void *event_info); void test_genlist7(void *data, Evas_Object *obj, void *event_info); void test_genlist8(void *data, Evas_Object *obj, void *event_info); void test_genlist9(void *data, Evas_Object *obj, void *event_info); +void test_genlist10(void *data, Evas_Object *obj, void *event_info); void test_table(void *data, Evas_Object *obj, void *event_info); void test_gengrid(void *data, Evas_Object *obj, void *event_info); void test_gengrid2(void *data, Evas_Object *obj, void *event_info); @@ -321,6 +322,7 @@ my_win_main(char *autorun) ADD_TEST("Genlist Tree", test_genlist6); ADD_TEST("Genlist Group", test_genlist8); ADD_TEST("Genlist Group Tree", test_genlist9); + ADD_TEST("Genlist Mode", test_genlist10); ADD_TEST("GenGrid", test_gengrid); ADD_TEST("GenGrid 2", test_gengrid2); ADD_TEST("Checks", test_check); diff --git a/src/bin/test_genlist.c b/src/bin/test_genlist.c index 3228931..6950016 100644 --- a/src/bin/test_genlist.c +++ b/src/bin/test_genlist.c @@ -1630,4 +1630,156 @@ test_genlist9(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_in evas_object_resize(win, 480, 800); evas_object_show(win); } + +/*************/ + +static Elm_Genlist_Item_Class itc10; +static char *mode_type[] = { "slide", "rotate" }; +char *gl10_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part) +{ + char buf[256]; + if (!strcmp(part, "elm.text.mode")) + snprintf(buf, sizeof(buf), "Mode # %i", (int)(long)data); + else + snprintf(buf, sizeof(buf), "Item # %i", (int)(long)data); + return strdup(buf); +} + +Evas_Object *gl10_icon_get(void *data __UNUSED__, Evas_Object *obj, const char *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", PACKAGE_DATA_DIR); + else + snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR); + elm_icon_file_set(ic, buf, NULL); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + return ic; +} +static void +_gl_sel10(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + if (!data) return; + int v = elm_radio_value_get(data); + if (v == 1) + elm_genlist_item_mode_set(event_info, mode_type[v], EINA_TRUE); +} + +static void +_my_gl_mode_right(void *data, Evas_Object *obj __UNUSED__, void *event_info) +{ + if (!data) return; + int v = elm_radio_value_get(data); + if (v == 0) + elm_genlist_item_mode_set(event_info, mode_type[v], EINA_TRUE); +} + +static void +_my_gl_mode_left(void *data, Evas_Object *obj __UNUSED__, void *event_info) +{ + if (!data) return; + int v = elm_radio_value_get(data); + if (v == 0) + elm_genlist_item_mode_set(event_info, mode_type[v], EINA_FALSE); +} + +static void +_my_gl_mode_cancel(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + fprintf(stderr, "drag\n"); + if (!data) return; + int v = elm_radio_value_get(data); + Elm_Genlist_Item *it = (Elm_Genlist_Item *)elm_genlist_mode_item_get(obj); + if (it) + elm_genlist_item_mode_set(it, mode_type[v], EINA_FALSE); +} + +void +test_genlist10(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *win, *bg, *fr, *lb, *bx, *bx2, *bx3, *rd, *rdg, *gl; + int i; + + win = elm_win_add(NULL, "genlist10", ELM_WIN_BASIC); + elm_win_title_set(win, "Genlist Mode"); + elm_win_autodel_set(win, 1); + + bg = elm_bg_add(win); + elm_win_resize_object_add(win, bg); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(bg); + + 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); + + fr = elm_frame_add(win); + elm_frame_label_set(fr, "Mode Type"); + elm_box_pack_end(bx, fr); + evas_object_show(fr); + + bx2 = elm_box_add(win); + elm_frame_content_set(fr, bx2); + evas_object_show(bx2); + + lb = elm_label_add(win); + elm_label_label_set(lb, + "Sweep genlist items to the right.
" + "Test this by changing Mode Type to Slide or Rotate."); + elm_box_pack_end(bx2, lb); + evas_object_show(lb); + + bx3 = elm_box_add(win); + elm_box_horizontal_set(bx3, EINA_TRUE); + elm_box_pack_end(bx2, bx3); + evas_object_show(bx3); + + rd = elm_radio_add(win); + evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_radio_state_value_set(rd, 0); + elm_radio_label_set(rd, "Slide "); + evas_object_show(rd); + elm_box_pack_end(bx3, rd); + rdg = rd; + + rd = elm_radio_add(win); + evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_radio_state_value_set(rd, 1); + elm_radio_label_set(rd, "Rotate"); + elm_radio_group_add(rd, rdg); + evas_object_show(rd); + elm_box_pack_end(bx3, rd); + + gl = elm_genlist_add(win); + evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_smart_callback_add(gl, "drag,start,right", _my_gl_mode_right, rdg); + evas_object_smart_callback_add(gl, "drag,start,left", _my_gl_mode_left, rdg); + evas_object_smart_callback_add(gl, "drag,start,up", _my_gl_mode_cancel, rdg); + evas_object_smart_callback_add(gl, "drag,start,down", _my_gl_mode_cancel, rdg); + evas_object_show(gl); + + itc10.item_style = "default"; + itc10.func.label_get = gl10_label_get; + itc10.func.icon_get = gl10_icon_get; + itc10.func.state_get = gl_state_get; + itc10.func.del = gl_del; + itc10.mode_item_style = "mode"; + + for (i = 0; i < 50; i++) + elm_genlist_item_append(gl, + &itc10, + (void *)(1000 + i)/* item data */, + NULL/* parent */, + ELM_GENLIST_ITEM_NONE/* flags */, + _gl_sel10/* func */, + rdg/* func data */); + + elm_box_pack_end(bx, gl); + + evas_object_resize(win, 520, 520); + evas_object_show(win); +} #endif diff --git a/src/bin/test_store.c b/src/bin/test_store.c index 95e14ff..bbbe75a 100644 --- a/src/bin/test_store.c +++ b/src/bin/test_store.c @@ -34,7 +34,7 @@ _st_longpress(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_in // store callbacks to handle loading/parsing/freeing of store items from src static Elm_Genlist_Item_Class itc1 = { - "message", { NULL, NULL, NULL, NULL } + "message", { NULL, NULL, NULL, NULL }, NULL }; static const Elm_Store_Item_Mapping it1_mapping[] = diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index a713b00..c8c9ca2 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -1764,6 +1764,7 @@ extern "C" { GenlistItemStateGetFunc state_get; GenlistItemDelFunc del; } func; + const char *mode_item_style; }; EAPI Evas_Object *elm_genlist_add(Evas_Object *parent) EINA_ARG_NONNULL(1); @@ -1849,6 +1850,9 @@ extern "C" { EAPI void elm_genlist_item_cursor_engine_only_set(Elm_Genlist_Item *item, Eina_Bool engine_only) EINA_ARG_NONNULL(1); EAPI Eina_Bool elm_genlist_item_cursor_engine_only_get(const Elm_Genlist_Item *item) EINA_ARG_NONNULL(1); EAPI void elm_genlist_realized_items_update(Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI void elm_genlist_item_mode_set(Elm_Genlist_Item *it, const char *mode_type, Eina_Bool mode_set) EINA_ARG_NONNULL(1, 2); + EAPI const char *elm_genlist_mode_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI const Elm_Genlist_Item *elm_genlist_mode_item_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); /* smart callbacks called: * "clicked,double" - This is called when a user has double-clicked an item. The * event_info parameter is the genlist item that was double-clicked. diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c index 7ffcd5b..5d99e2f 100644 --- a/src/lib/elm_genlist.c +++ b/src/lib/elm_genlist.c @@ -315,6 +315,9 @@ struct _Widget_Data int group_item_height; int max_items_per_block; double longpress_timeout; + const char *mode_type; + Elm_Genlist_Item *mode_item; + Ecore_Timer *scr_hold_timer; }; struct _Item_Block @@ -353,12 +356,14 @@ struct _Elm_Genlist_Item Evas_Object *spacer; Eina_List *labels, *icons, *states, *icon_objs; + Eina_List *mode_labels, *mode_icons, *mode_states, *mode_icon_objs; Ecore_Timer *long_timer; Ecore_Timer *swipe_timer; Evas_Coord dx, dy; Evas_Coord scrl_x, scrl_y; Elm_Genlist_Item *rel; + Evas_Object *mode_view; struct { @@ -448,6 +453,11 @@ static void _signal_emit_hook(Evas_Object *obj, const char *source); static Eina_Bool _deselect_all_items(Widget_Data *wd); static void _pan_calculate(Evas_Object *obj); +static void _item_position(Elm_Genlist_Item *it, Evas_Object *obj); +static void _mode_item_realize(Elm_Genlist_Item *it); +static void _mode_item_unrealize(Elm_Genlist_Item *it); +static void _item_mode_set(Elm_Genlist_Item *it); +static void _item_mode_unset(Widget_Data *wd); static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION; @@ -695,6 +705,8 @@ _del_hook(Evas_Object *obj) if (wd->update_job) ecore_job_del(wd->update_job); if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler); if (wd->multi_timer) ecore_timer_del(wd->multi_timer); + if (wd->mode_type) eina_stringshare_del(wd->mode_type); + if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer); free(wd); } @@ -831,7 +843,9 @@ static void _item_highlight(Elm_Genlist_Item *it) { const char *selectraise; - if ((it->wd->no_select) || (it->delete_me) || (it->highlighted) || (it->disabled) || (it->display_only)) return; + if ((it->wd->no_select) || (it->delete_me) || (it->highlighted) || + (it->disabled) || (it->display_only) || (it->mode_view)) + return; edje_object_signal_emit(it->base.view, "elm,state,selected", "elm"); selectraise = edje_object_data_get(it->base.view, "selectraise"); if ((selectraise) && (!strcmp(selectraise, "on"))) @@ -946,7 +960,7 @@ _item_del(Elm_Genlist_Item *it) static void _item_select(Elm_Genlist_Item *it) { - if ((it->wd->no_select) || (it->delete_me)) return; + if ((it->wd->no_select) || (it->delete_me) || (it->mode_view)) return; if (it->selected) { if (it->wd->always_select) goto call; @@ -1489,6 +1503,34 @@ _signal_contract(void *data, evas_object_smart_callback_call(it->base.widget, "contract,request", it); } +static Eina_Bool +_scr_hold_timer_cb(void *data) +{ + if (!data) return ECORE_CALLBACK_CANCEL; + Widget_Data *wd = data; + elm_smart_scroller_hold_set(wd->scr, EINA_FALSE); + wd->scr_hold_timer = NULL; + return ECORE_CALLBACK_CANCEL; +} + +static void +_mode_finished_signal_cb(void *data, + Evas_Object *obj, + const char *emission __UNUSED__, + const char *source __UNUSED__) +{ + if (!data) return; + if (!obj) return; + Elm_Genlist_Item *it = data; + if ((it->delete_me) || (!it->realized) || (!it->mode_view)) return; + char buf[1024]; + + it->nocache = EINA_FALSE; + _mode_item_unrealize(it); + snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->mode_type); + edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it); +} + static void _item_cache_clean(Widget_Data *wd) { @@ -1914,6 +1956,7 @@ _item_unrealize(Elm_Genlist_Item *it, Eina_Bool calc) EINA_LIST_FREE(it->icon_objs, icon) evas_object_del(icon); + _mode_item_unrealize(it); it->states = NULL; it->realized = EINA_FALSE; it->want_unrealize = EINA_FALSE; @@ -2020,6 +2063,17 @@ _item_block_unrealize(Item_Block *itb) } static void +_item_position(Elm_Genlist_Item *it, Evas_Object *view) +{ + if (!it) return; + if (!view) return; + + evas_object_resize(view, it->w, it->h); + evas_object_move(view, it->scrl_x, it->scrl_y); + evas_object_show(view); +} + +static void _item_block_position(Item_Block *itb, int in) { @@ -2062,10 +2116,10 @@ _item_block_position(Item_Block *itb, git->scrl_y = (it->scrl_y + it->h) - git->h; git->want_realize = EINA_TRUE; } - evas_object_resize(it->base.view, it->w, it->h); - evas_object_move(it->base.view, - it->scrl_x, it->scrl_y); - evas_object_show(it->base.view); + if (it->mode_view) + _item_position(it, it->mode_view); + else + _item_position(it, it->base.view); } else { @@ -2584,6 +2638,184 @@ _scroll_edge_bottom(void *data, evas_object_smart_callback_call(obj, "scroll,edge,bottom", NULL); } +static void +_mode_item_realize(Elm_Genlist_Item *it) +{ + char buf[1024]; + + if ((it->mode_view) || (it->delete_me)) return; + + it->mode_view = edje_object_add(evas_object_evas_get(it->base.widget)); + edje_object_scale_set(it->mode_view, + elm_widget_scale_get(it->base.widget) * + _elm_config->scale); + evas_object_smart_member_add(it->mode_view, it->wd->pan_smart); + elm_widget_sub_object_add(it->base.widget, it->mode_view); + + strncpy(buf, "item", sizeof(buf)); + if (it->wd->compress) + strncat(buf, "_compress", sizeof(buf) - strlen(buf)); + + if (it->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf)); + strncat(buf, "/", sizeof(buf) - strlen(buf)); + strncat(buf, it->itc->mode_item_style, sizeof(buf) - strlen(buf)); + + _elm_theme_object_set(it->base.widget, it->mode_view, "genlist", buf, + elm_widget_style_get(it->base.widget)); + edje_object_mirrored_set(it->mode_view, + elm_widget_mirrored_get(it->base.widget)); + elm_widget_sub_object_add(it->base.widget, it->spacer); + + /* signal callback add */ + evas_object_event_callback_add(it->mode_view, EVAS_CALLBACK_MOUSE_DOWN, + _mouse_down, it); + evas_object_event_callback_add(it->mode_view, EVAS_CALLBACK_MOUSE_UP, + _mouse_up, it); + evas_object_event_callback_add(it->mode_view, EVAS_CALLBACK_MOUSE_MOVE, + _mouse_move, it); + + /* label_get, icon_get, state_get */ + if (it->itc->func.label_get) + { + const Eina_List *l; + const char *key; + + it->mode_labels = + elm_widget_stringlist_get(edje_object_data_get(it->mode_view, + "labels")); + EINA_LIST_FOREACH(it->mode_labels, l, key) + { + char *s = it->itc->func.label_get + ((void *)it->base.data, it->base.widget, l->data); + + if (s) + { + edje_object_part_text_set(it->mode_view, l->data, s); + free(s); + } + } + } + if (it->itc->func.icon_get) + { + const Eina_List *l; + const char *key; + + it->mode_icons = + elm_widget_stringlist_get(edje_object_data_get(it->mode_view, + "icons")); + EINA_LIST_FOREACH(it->mode_icons, l, key) + { + Evas_Object *ic = it->itc->func.icon_get + ((void *)it->base.data, it->base.widget, l->data); + + if (ic) + { + it->mode_icon_objs = eina_list_append(it->mode_icon_objs, ic); + edje_object_part_swallow(it->mode_view, key, ic); + evas_object_show(ic); + elm_widget_sub_object_add(it->base.widget, ic); + } + } + } + if (it->itc->func.state_get) + { + const Eina_List *l; + const char *key; + + it->mode_states = + elm_widget_stringlist_get(edje_object_data_get(it->mode_view, + "states")); + EINA_LIST_FOREACH(it->mode_states, l, key) + { + Eina_Bool on = it->itc->func.state_get + ((void *)it->base.data, it->base.widget, l->data); + + if (on) + { + snprintf(buf, sizeof(buf), "elm,state,%s,active", key); + edje_object_signal_emit(it->mode_view, buf, "elm"); + } + } + } + + edje_object_part_swallow(it->mode_view, + edje_object_data_get(it->mode_view, "mode_part"), + it->base.view); + + it->want_unrealize = EINA_FALSE; +} + +static void +_mode_item_unrealize(Elm_Genlist_Item *it) +{ + Widget_Data *wd = it->wd; + Evas_Object *icon; + if (!it->mode_view) return; + + elm_widget_stringlist_free(it->mode_labels); + it->mode_labels = NULL; + elm_widget_stringlist_free(it->mode_icons); + it->mode_icons = NULL; + elm_widget_stringlist_free(it->mode_states); + + EINA_LIST_FREE(it->mode_icon_objs, icon) + evas_object_del(icon); + + edje_object_part_unswallow(it->mode_view, it->base.view); + evas_object_smart_member_add(it->base.view, wd->pan_smart); + evas_object_del(it->mode_view); + it->mode_view = NULL; + + if (wd->mode_item == it) + wd->mode_item = NULL; +} + +static void +_item_mode_set(Elm_Genlist_Item *it) +{ + if (!it) return; + Widget_Data *wd = it->wd; + if (!wd) return; + char buf[1024]; + + wd->mode_item = it; + it->nocache = EINA_TRUE; + + if (wd->scr_hold_timer) + { + ecore_timer_del(wd->scr_hold_timer); + wd->scr_hold_timer = NULL; + } + elm_smart_scroller_hold_set(wd->scr, EINA_TRUE); + wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd); + + _mode_item_realize(it); + _item_position(it, it->mode_view); + + snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type); + edje_object_signal_emit(it->mode_view, buf, "elm"); +} + +static void +_item_mode_unset(Widget_Data *wd) +{ + if (!wd) return; + if (!wd->mode_item) return; + char buf[1024], buf2[1024]; + Elm_Genlist_Item *it; + + it = wd->mode_item; + it->nocache = EINA_TRUE; + + snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->mode_type); + snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->mode_type); + + edje_object_signal_emit(it->mode_view, buf, "elm"); + edje_object_signal_callback_add(it->mode_view, buf2, "elm", _mode_finished_signal_cb, it); + + wd->mode_item = NULL; +} + /** * Add a new Genlist object * @@ -4943,3 +5175,85 @@ elm_genlist_realized_items_update(Evas_Object *obj) EINA_LIST_FOREACH(list, l, it) elm_genlist_item_update(it); } + +/** + * Set genlist item mode + * + * @param item The genlist item + * @param mode Mode name + * @param mode_set Boolean to define set or unset mode. + * + * @ingroup Genlist + */ +EAPI void +elm_genlist_item_mode_set(Elm_Genlist_Item *it, + const char *mode_type, + Eina_Bool mode_set) +{ + ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it); + Widget_Data *wd = it->wd; + Eina_List *l; + Elm_Genlist_Item *it2; + + if (!wd) return; + if (!mode_type) return; + + if ((wd->mode_item == it) && + (!strcmp(mode_type, wd->mode_type)) && + (mode_set)) + return; + if (!it->itc->mode_item_style) return; + + if (wd->multi) + { + EINA_LIST_FOREACH(wd->selected, l, it2) + if (it2->realized) + elm_genlist_item_selected_set(it2, EINA_FALSE); + } + else + { + it2 = elm_genlist_selected_item_get(wd->obj); + if ((it2) && (it2->realized)) + elm_genlist_item_selected_set(it2, EINA_FALSE); + } + + if (((wd->mode_type) && (strcmp(mode_type, wd->mode_type))) || + (mode_set) || + ((it == wd->mode_item) && (!mode_set))) + _item_mode_unset(wd); + + eina_stringshare_replace(&wd->mode_type, mode_type); + if (mode_set) _item_mode_set(it); +} + +/** + * Get active genlist mode type + * + * @param obj The genlist object + * + * @ingroup Genlist + */ +EAPI const char * +elm_genlist_mode_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + return wd->mode_type; +} + +/** + * Get active genlist mode item + * + * @param obj The genlist object + * + * @ingroup Genlist + */ +EAPI const Elm_Genlist_Item * +elm_genlist_mode_item_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + return wd->mode_item; +} -- 2.7.4