diff --git a/data/elementary/themes/edc/efl/list.edc b/data/elementary/themes/edc/efl/list.edc index 4b309c8ce5..1bc55ec4d6 100644 --- a/data/elementary/themes/edc/efl/list.edc +++ b/data/elementary/themes/edc/efl/list.edc @@ -1,8 +1,12 @@ -group { "efl/view_list"; +group { "efl/list"; inherit: "efl/scroller"; } -group { name: "efl/list/item"; +group { "efl/view_list"; + inherit: "efl/list"; +} + +group { "efl/list_item"; data.item: "selectraise" "on"; data.item: "focusraise" "on"; images.image: "bevel_curved_horiz_out.png" COMP; @@ -11,118 +15,91 @@ group { name: "efl/list/item"; images.image: "bevel_horiz_out.png" COMP; images.image: "shine.png" COMP; parts { - part { name: "event"; type: RECT; - description { state: "default" 0.0; + rect { "event"; + desc { "default"; color: 0 0 0 0; } - description { state: "disabled" 0.0; - inherit: "default" 0.0; - visible: 0; + desc { "disabled"; + inherit: "default"; + hid; } } - part { name: "base"; type: RECT; mouse_events: 0; - description { state: "default" 0.0; + rect { "base"; nomouse; + desc { "default"; color: 64 64 64 255; color_class: "list_item_base"; } - description { state: "odd" 0.0; + desc { "odd"; color: 56 56 56 255; color_class: "list_item_base_odd"; } } - program { - signal: "elm,state,odd"; source: "elm"; - action: STATE_SET "odd" 1.0; - target: "base"; - } - program { - signal: "elm,state,even"; source: "elm"; - action: STATE_SET "default" 0.0; - target: "base"; - } - part { name: "bevel"; mouse_events: 0; - description { state: "default" 0.0; + + image { "bevel"; nomouse; + desc { "default"; image.normal: "bevel_curved_horiz_out.png"; image.border: 0 0 2 2; image.middle: 0; fill.smooth: 0; } } - part { name: "sel_shadow"; mouse_events: 0; - description { state: "default" 0.0; + swallow { "efl.background"; + desc { "default"; + rel.to: "base"; + vis; + } + } + image { "sel_shadow"; nomouse; + desc { "default"; image.normal: "shadow_rounded_horiz.png"; image.border: 0 0 9 9; rel1.offset: 0 -4; rel2.offset: -1 5; fill.smooth: 0; - visible: 0; + hid; } - description { state: "selected" 0.0; - inherit: "default" 0.0; - visible: 1; + desc { "selected"; + inherit: "default"; + vis; } } - part { name: "sel_base"; mouse_events: 0; - description { state: "default" 0.0; + image { "sel_base"; nomouse; + desc { "default"; image.normal: "vgrad_med_dark.png"; fill.smooth: 0; - visible: 0; + hid; TILED_HORIZ(120) } - description { state: "selected" 0.0; - inherit: "default" 0.0; - visible: 1; + desc { "selected"; + inherit: "default"; + vis; } } - part { name: "sel_bevel"; mouse_events: 0; - description { state: "default" 0.0; + image { "sel_bevel"; nomouse; + desc { "default"; image.normal: "bevel_horiz_out.png"; image.border: 0 0 2 2; image.middle: 0; fill.smooth: 0; - visible: 0; + hid; } - description { state: "selected" 0.0; - inherit: "default" 0.0; - visible: 1; + desc { "selected"; + inherit: "default"; + vis; } } - program { - signal: "elm,state,selected"; source: "elm"; - action: STATE_SET "selected" 0.0; - target: "sel_shadow"; - target: "sel_base"; - target: "sel_bevel"; - } - program { - signal: "elm,state,unselected"; source: "elm"; - action: STATE_SET "default" 0.0; - target: "sel_shadow"; - target: "sel_base"; - target: "sel_bevel"; - } - program { - signal: "elm,state,disabled"; source: "elm"; - action: STATE_SET "disabled" 0.0; - target: "event"; - } - program { - signal: "elm,state,enabled"; source: "elm"; - action: STATE_SET "default" 0.0; - target: "event"; - } //##// - part { name: "elm.text"; type: TEXT; mouse_events: 0; + text { "efl.text"; nomouse; effect: SHADOW BOTTOM; scale: 1; - description { state: "default" 0.0; + desc { "default"; rel1.offset: 2 3; rel1.relative: 1.0 0.0; - rel1.to_x: "elm.swallow.icon"; + rel1.to_x: "efl.icon"; rel2.offset: -3 -3; rel2.relative: 0.0 1.0; - rel2.to_x: "elm.swallow.end"; + rel2.to_x: "efl.end"; color: FN_COL_DEFAULT; color_class: "list_item"; text { font: FN; size: 10; @@ -132,96 +109,68 @@ group { name: "efl/list/item"; text_class: "list_item"; } } - description { state: "selected" 0.0; - inherit: "default" 0.0; - visible: 0; + desc { "selected"; + inherit: "default"; + hid; } - description { state: "disabled" 0.0; - inherit: "default" 0.0; - visible: 0; + desc { "disabled"; + inherit: "default"; + hid; } } - part { name: "label2"; type: TEXT; mouse_events: 0; + text { "label2"; nomouse; effect: SHADOW BOTTOM; scale: 1; - description { state: "default" 0.0; - rel1.to: "elm.text"; - rel2.to: "elm.text"; + desc { "default"; + rel1.to: "efl.text"; + rel2.to: "efl.text"; color: FN_COL_DISABLE; color_class: "list_item_disabled"; text { font: FN; size: 10; - text_source: "elm.text"; + text_source: "efl.text"; align: 0.0 0.5; text_class: "list_item"; } - visible: 0; + hid; } - description { state: "selected" 0.0; - inherit: "default" 0.0; - visible: 0; + desc { "selected"; + inherit: "default"; + hid; } - description { state: "disabled" 0.0; - inherit: "default" 0.0; - visible: 1; + desc { "disabled"; + inherit: "default"; + vis; } } - part { name: "label3"; type: TEXT; mouse_events: 0; + text { "label3"; nomouse; effect: GLOW; scale: 1; - description { state: "default" 0.0; + desc { "default"; rel1.offset: -2 -3; - rel1.to: "elm.text"; + rel1.to: "efl.text"; rel2.offset: 1 1; - rel2.to: "elm.text"; + rel2.to: "efl.text"; color: FN_COL_HIGHLIGHT; color_class: "list_item_selected"; text { font: FN; size: 10; - text_source: "elm.text"; + text_source: "efl.text"; align: 0.0 0.5; text_class: "list_item"; } - visible: 0; + hid; } - description { state: "selected" 0.0; - inherit: "default" 0.0; - visible: 1; + desc { "selected"; + inherit: "default"; + vis; } - description { state: "disabled" 0.0; - inherit: "default" 0.0; - visible: 0; + desc { "disabled"; + inherit: "default"; + hid; } } - program { - signal: "elm,state,selected"; source: "elm"; - action: STATE_SET "selected" 0.0; - target: "elm.text"; - target: "label2"; - target: "label3"; - } - program { - signal: "elm,state,unselected"; source: "elm"; - action: STATE_SET "default" 0.0; - target: "elm.text"; - target: "label2"; - target: "label3"; - } - program { - signal: "elm,state,disabled"; source: "elm"; - action: STATE_SET "disabled" 0.0; - target: "elm.text"; - target: "label2"; - target: "label3"; - } - program { - signal: "elm,state,enabled"; source: "elm"; - action: STATE_SET "default" 0.0; - target: "elm.text"; - target: "label2"; - target: "label3"; - } //##// - part { name: "elm.swallow.icon"; type: SWALLOW; - description { state: "default" 0.0; + swallow { "efl.icon"; + desc { "default"; fixed: 1 0; align: 0.0 0.5; aspect: 1.0 1.0; @@ -230,8 +179,8 @@ group { name: "efl/list/item"; rel2.offset: 2 -3; } } - part { name: "elm.swallow.end"; type: SWALLOW; - description { state: "default" 0.0; + swallow { "efl.end"; + desc { "default"; fixed: 1 0; align: 1.0 0.5; aspect: 1.0 1.0; @@ -241,51 +190,281 @@ group { name: "efl/list/item"; } } //##// - - part { name: "sel_shine"; mouse_events: 0; - description { state: "default" 0.0; + image { "sel_shine"; nomouse; + desc { "default"; image.normal: "shine.png"; rel1.offset: 0 -2; rel1.to: "sel_base"; rel2.relative: 1.0 0.0; rel2.offset: -1 2; rel2.to: "sel_base"; - visible: 0; + hid; FIXED_SIZE(69, 5) } - description { state: "selected" 0.0; - inherit: "default" 0.0; - visible: 1; + desc { "selected"; + inherit: "default"; + vis; } } - part { name: "event_block"; type: RECT; - description { state: "default" 0.0; + rect { "event_block"; + desc { "default"; color: 0 0 0 0; - visible: 0; + hid; } - description { state: "disabled" 0.0; - inherit: "default" 0.0; - visible: 1; + desc { "disabled"; + inherit: "default"; + vis; } } + } + programs { program { - signal: "elm,state,selected"; source: "elm"; - action: STATE_SET "selected" 0.0; + signal: "efl,state,odd"; source: "efl"; + action: STATE_SET "odd"; + target: "base"; + } + program { + signal: "efl,state,even"; source: "efl"; + action: STATE_SET "default"; + target: "base"; + } + program { + signal: "efl,state,pressed"; source: "efl"; + action: STATE_SET "selected"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "efl.text"; + target: "label2"; + target: "label3"; target: "sel_shine"; } program { - signal: "elm,state,unselected"; source: "elm"; - action: STATE_SET "default" 0.0; + signal: "efl,state,unpressed"; source: "efl"; + action: STATE_SET "default"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "efl.text"; + target: "label2"; + target: "label3"; target: "sel_shine"; } program { - signal: "elm,state,disabled"; source: "elm"; - action: STATE_SET "disabled" 0.0; + signal: "efl,state,selected"; source: "efl"; + action: STATE_SET "selected"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "efl.text"; + target: "label2"; + target: "label3"; + target: "sel_shine"; + } + program { + signal: "efl,state,unselected"; source: "efl"; + action: STATE_SET "default"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "efl.text"; + target: "label2"; + target: "label3"; + target: "sel_shine"; + } + program { + signal: "efl,state,disabled"; source: "efl"; + action: STATE_SET "disabled"; + target: "event"; + target: "efl.text"; + target: "label2"; + target: "label3"; target: "event_block"; } program { - signal: "elm,state,enabled"; source: "elm"; - action: STATE_SET "default" 0.0; + signal: "efl,state,enabled"; source: "efl"; + action: STATE_SET "default"; + target: "event"; + target: "efl.text"; + target: "label2"; + target: "label3"; + target: "event_block"; + } + } +} + +group { "efl/list_item:empty"; + data.item: "selectraise" "on"; + data.item: "focusraise" "on"; + images.image: "bevel_curved_horiz_out.png" COMP; + images.image: "shadow_rounded_horiz.png" COMP; + images.image: "vgrad_med_dark.png" COMP; + images.image: "bevel_horiz_out.png" COMP; + images.image: "shine.png" COMP; + parts { + rect { "event"; + desc { "default"; + color: 0 0 0 0; + } + desc { "disabled"; + inherit: "default"; + hid; + } + } + rect { "base"; nomouse; + desc { "default"; + color: 64 64 64 255; + color_class: "list_item_base"; + } + desc { "odd"; + color: 56 56 56 255; + color_class: "list_item_base_odd"; + } + } + + image { "bevel"; nomouse; + desc { "default"; + image.normal: "bevel_curved_horiz_out.png"; + image.border: 0 0 2 2; + image.middle: 0; + fill.smooth: 0; + } + } + swallow { "efl.background"; + desc { "default"; + rel.to: "base"; + vis; + } + } + image { "sel_shadow"; nomouse; + desc { "default"; + image.normal: "shadow_rounded_horiz.png"; + image.border: 0 0 9 9; + rel1.offset: 0 -4; + rel2.offset: -1 5; + fill.smooth: 0; + hid; + } + desc { "selected"; + inherit: "default"; + vis; + } + } + image { "sel_base"; nomouse; + desc { "default"; + image.normal: "vgrad_med_dark.png"; + fill.smooth: 0; + hid; + TILED_HORIZ(120) + } + desc { "selected"; + inherit: "default"; + vis; + } + } + image { "sel_bevel"; nomouse; + desc { "default"; + image.normal: "bevel_horiz_out.png"; + image.border: 0 0 2 2; + image.middle: 0; + fill.smooth: 0; + hid; + } + desc { "selected"; + inherit: "default"; + vis; + } + } + //##// + swallow { "efl.content"; mouse; + scale; + desc { "default"; + min: 19 19; + rel1.offset: -1 2; + rel2.offset: -3 -3; + } + } + //##// + image { "sel_shine"; + desc { "default"; + image.normal: "shine.png"; + rel1.offset: 0 -2; + rel1.to: "sel_base"; + rel2.relative: 1.0 0.0; + rel2.offset: -1 2; + rel2.to: "sel_base"; + hid; + FIXED_SIZE(69, 5) + } + desc { "selected"; + inherit: "default"; + vis; + } + } + rect { "event_block"; mouse; + desc { "default"; + color: 0 0 0 0; + hid; + } + desc { "disabled"; + inherit: "default"; + vis; + } + } + } + programs { + program { + signal: "efl,state,odd"; source: "efl"; + action: STATE_SET "odd"; + target: "base"; + } + program { + signal: "efl,state,even"; source: "efl"; + action: STATE_SET "default"; + target: "base"; + } + program { + signal: "efl,state,pressed"; source: "efl"; + action: STATE_SET "selected"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "sel_shine"; + } + program { + signal: "efl,state,unpressed"; source: "efl"; + action: STATE_SET "default"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "sel_shine"; + } + program { + signal: "efl,state,selected"; source: "efl"; + action: STATE_SET "selected"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "sel_shine"; + } + program { + signal: "efl,state,unselected"; source: "efl"; + action: STATE_SET "default"; + target: "sel_shadow"; + target: "sel_base"; + target: "sel_bevel"; + target: "sel_shine"; + } + program { + signal: "efl,state,disabled"; source: "efl"; + action: STATE_SET "disabled"; + target: "event"; + target: "event_block"; + } + program { + signal: "efl,state,enabled"; source: "efl"; + action: STATE_SET "default"; + target: "event"; target: "event_block"; } } diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am index 595b1e604f..972eda7e04 100644 --- a/src/Makefile_Efl.am +++ b/src/Makefile_Efl.am @@ -12,6 +12,7 @@ efl_eolian_legacy_files = \ lib/efl/interfaces/efl_ui_scrollable_interactive.eo \ lib/efl/interfaces/efl_ui_scrollbar.eo \ lib/efl/interfaces/efl_ui_selectable.eo \ + lib/efl/interfaces/efl_ui_multi_selectable.eo \ lib/efl/interfaces/efl_ui_zoom.eo \ $(NULL) diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index d101d85bdb..ac528db73c 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -81,6 +81,13 @@ elm_public_eolian_files = \ lib/elementary/efl_ui_view_list_pan.eo \ lib/elementary/efl_ui_view_list_segarray.eo \ lib/elementary/efl_ui_view_list_relayout.eo \ + lib/elementary/efl_ui_item.eo \ + lib/elementary/efl_ui_list_item.eo \ + lib/elementary/efl_ui_list_default_item_part_icon.eo \ + lib/elementary/efl_ui_list_default_item_part_end.eo \ + lib/elementary/efl_ui_list_default_item.eo \ + lib/elementary/efl_ui_list_empty_item.eo \ + lib/elementary/efl_ui_list.eo \ lib/elementary/efl_ui_panes_part.eo \ lib/elementary/efl_ui_progressbar_part.eo \ lib/elementary/efl_ui_slider_part_indicator.eo \ @@ -391,6 +398,9 @@ includesunstable_HEADERS = \ lib/elementary/elm_widget_thumb.h \ lib/elementary/elm_widget_toolbar.h \ lib/elementary/efl_ui_video_private.h \ + lib/elementary/efl_ui_item_private.h \ + lib/elementary/efl_ui_list_item_private.h \ + lib/elementary/efl_ui_list_private.h \ lib/elementary/efl_ui_view_list_private.h \ lib/elementary/efl_ui_view_list_segarray.h \ lib/elementary/elm_widget_web.h \ @@ -809,6 +819,11 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_focus_parent_provider_gen.c \ lib/elementary/efl_ui_focus_util.c \ lib/elementary/elm_widget_item_static_focus.c \ + lib/elementary/efl_ui_item.c \ + lib/elementary/efl_ui_list_item.c \ + lib/elementary/efl_ui_list_default_item.c \ + lib/elementary/efl_ui_list_empty_item.c \ + lib/elementary/efl_ui_list.c \ lib/elementary/efl_ui_view_list.c \ lib/elementary/efl_ui_view_list_precise_layouter.c \ lib/elementary/efl_ui_view_list_segarray.c \ diff --git a/src/examples/elementary/.gitignore b/src/examples/elementary/.gitignore index 896a69007f..f59adb353e 100644 --- a/src/examples/elementary/.gitignore +++ b/src/examples/elementary/.gitignore @@ -60,6 +60,7 @@ /list_example_01 /list_example_02 /list_example_03 +/efl_ui_list_example_1 /efl_ui_view_list_example_1 /efl_ui_view_list_example_2 /efl_ui_view_list_example_3 diff --git a/src/examples/elementary/Makefile.am b/src/examples/elementary/Makefile.am index 488b48f28c..51dbd2051a 100644 --- a/src/examples/elementary/Makefile.am +++ b/src/examples/elementary/Makefile.am @@ -177,6 +177,7 @@ efl_thread_3.c \ efl_thread_4.c \ efl_thread_5.c \ efl_thread_6.c \ +efl_ui_list_example_1.c \ efl_ui_view_list_example_1.c \ efl_ui_view_list_example_2.c \ efl_ui_view_list_example_3.c @@ -393,6 +394,7 @@ efl_thread_3 \ efl_thread_4 \ efl_thread_5 \ efl_thread_6 \ +efl_ui_list_example_1 \ efl_ui_view_list_example_1 \ efl_ui_view_list_example_2 \ efl_ui_view_list_example_3 diff --git a/src/examples/elementary/efl_ui_list_example_1.c b/src/examples/elementary/efl_ui_list_example_1.c new file mode 100644 index 0000000000..432c58621c --- /dev/null +++ b/src/examples/elementary/efl_ui_list_example_1.c @@ -0,0 +1,327 @@ +// gcc -o efl_ui_list_example_1 efl_ui_list_example_1.c `pkg-config --cflags --libs elementary` +// ./efl_ui_list_example_1 item_style_name + +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#else +# define EFL_BETA_API_SUPPORT 1 +# define EFL_EO_API_SUPPORT 1 +#endif + +#include +#include +#include +#include + +#define NUM_ITEMS 400 + +typedef struct _List_Scroll_Data { + Eo *list; + Eo *slider; + Eina_Bool anim; +} List_Scroll_Data; +List_Scroll_Data priv_d; + + +static void +_list_selected(void *data, const Efl_Event *ev) +{ + Eo *list = ev->object; + Eo *item = ev->info, *tmp; + printf("list item [%p:%d] is %s\n", item, efl_ui_item_index_get(item), (efl_ui_item_selected_get(item)? "selected" : "unselected")); + + Eina_Iterator *selects = efl_ui_list_selected_items_get(list); + + EINA_ITERATOR_FOREACH(selects, tmp) + printf("selected [%p:%d] ", tmp, efl_ui_item_index_get(tmp)); + printf("\n"); + eina_iterator_free(selects); +} + +static void +_list_unselected(void *data, const Efl_Event *ev) +{ + Eo *item = ev->info; + printf("list item [%p : %d] is %s\n", item, efl_ui_item_index_get(item), (efl_ui_item_selected_get(item)? "selected" : "unselected")); +} + +static void +_list_pressed(void *data, const Efl_Event *ev) +{ + Eo *item = ev->info; + printf("list item [%p : %d] is pressed\n", item, efl_ui_item_index_get(item)); +} + +static void +_list_unpressed(void *data, const Efl_Event *ev) +{ + Eo *item = ev->info; + printf("list item [%p : %d] is unpressed\n", item, efl_ui_item_index_get(item)); +} + +static void +_list_longpressed(void *data, const Efl_Event *ev) +{ + Eo *item = ev->info; + printf("list item [%p : %d] is longpressed\n", item, efl_ui_item_index_get(item)); +} + +static void +_select_radio_changed(void *data, const Efl_Event *ev) +{ + Eo *list = data; + efl_ui_select_mode_set(list, efl_ui_radio_state_value_get(ev->object)); +} + +static void +_anim_radio_changed(void *data, const Efl_Event *ev) +{ + priv_d.anim = efl_ui_radio_state_value_get(ev->object); +} + +static void +_scrl_btn_clicked(void *data, const Efl_Event *ev) +{ + Efl_Ui_List_Item *item = efl_ui_list_last_selected_item_get(priv_d.list); + printf("show [%d:%p] [%d]\n", efl_ui_item_index_get(item), item, priv_d.anim); + efl_ui_list_item_scroll(priv_d.list, item, priv_d.anim); +} + +static void +_scrl_align_btn_clicked(void *data, const Efl_Event *ev) +{ + Efl_Ui_List_Item *item = efl_ui_list_last_selected_item_get(priv_d.list); + double align = efl_ui_range_value_get(priv_d.slider); + printf("show [%d:%p] [%.2lf], [%d]\n", efl_ui_item_index_get(item), item, align, priv_d.anim); + efl_ui_list_item_scroll_align(priv_d.list, item, align, priv_d.anim); +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Eo *win, *list; + Eo *wbox, *ibox, *bbox, *rbox; + Eo *item, *check, *txt; + Eo *radio, *select_radio, *anim_radio; + Eo *slider, *scrl_btn; + int i; + char buf[256]; + Eina_Bool emptystyle = EINA_FALSE; + + win = elm_win_util_standard_add("list", "list"); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + elm_win_autodel_set(win, EINA_TRUE); + efl_gfx_entity_size_set(win, EINA_SIZE2D(400, 800)); + + wbox = efl_add(EFL_UI_BOX_CLASS, win); + efl_ui_direction_set(wbox, EFL_UI_DIR_VERTICAL); + efl_gfx_size_hint_weight_set(wbox, EFL_GFX_SIZE_HINT_EXPAND, EFL_GFX_SIZE_HINT_EXPAND); + efl_gfx_size_hint_align_set(wbox, EFL_GFX_SIZE_HINT_FILL, EFL_GFX_SIZE_HINT_FILL); + + if ((argv[1] != NULL) && + (!strcmp(argv[1], "empty"))) + emptystyle = EINA_TRUE; + + priv_d.list = list = efl_add(EFL_UI_LIST_CLASS, wbox); + efl_gfx_size_hint_weight_set(list, EFL_GFX_SIZE_HINT_EXPAND, 0.9); + + efl_event_callback_add(list, EFL_UI_EVENT_SELECTED, _list_selected, NULL); + efl_event_callback_add(list, EFL_UI_EVENT_UNSELECTED, _list_unselected, NULL); + efl_event_callback_add(list, EFL_UI_EVENT_PRESSED, _list_pressed, NULL); + efl_event_callback_add(list, EFL_UI_EVENT_UNPRESSED, _list_unpressed, NULL); + efl_event_callback_add(list, EFL_UI_EVENT_LONGPRESSED, _list_longpressed, NULL); + + for (i = 0; i < NUM_ITEMS; i++) + { + if (emptystyle) item = efl_add(EFL_UI_LIST_EMPTY_ITEM_CLASS, list); + else item = efl_add(EFL_UI_LIST_DEFAULT_ITEM_CLASS, list); + + /* disable case test */ + if (i == 1) efl_ui_widget_disabled_set(item, EINA_TRUE); + + if (emptystyle) + { + ibox = efl_add(EFL_UI_BOX_CLASS, item); + efl_ui_direction_set(ibox, EFL_UI_DIR_HORIZONTAL); + + txt = efl_add(EFL_UI_TEXT_CLASS, ibox); + efl_gfx_size_hint_weight_set(txt, 0.95, EFL_GFX_SIZE_HINT_EXPAND); + efl_text_halign_set(txt, 0.2); + efl_text_interactive_selection_allowed_set(txt, EINA_FALSE); + snprintf(buf, sizeof(buf), "empty style item [%d]", i); + efl_text_set(txt, buf); + efl_pack_end(ibox, txt); + + check = efl_add(EFL_UI_CHECK_CLASS, ibox); + efl_gfx_size_hint_weight_set(check, 0.05, EFL_GFX_SIZE_HINT_EXPAND); + efl_pack_end(ibox, check); + + if (i % 2) + efl_content_set(item, ibox); + else + efl_content_set(efl_part(item, "content"), ibox); + } + else + { + snprintf(buf, sizeof(buf), "default style item [%d]", i); + if (i % 2) + efl_text_set(efl_part(item, "text"), buf); + else + efl_text_set(item, buf); + + + check = efl_add(EFL_UI_CHECK_CLASS, item); + if ((i % 3) == 0) + efl_content_set(efl_part(item, "end"), check); + else if ((i % 3) == 1) + efl_content_set(efl_part(item, "icon"), check); + else + efl_content_set(item, check); + } + /* Pack APIs test */ + switch (i) + { + case 10: + efl_gfx_color_set(efl_part(item, "background"), 255, 0, 0, 255); + efl_pack_begin(list, item); + break; + + case 20: + efl_gfx_color_set(efl_part(item, "background"), 0, 255, 0, 255); + efl_pack_before(list, item, efl_pack_content_get(list, 19)); + break; + + case 30: + efl_gfx_color_set(efl_part(item, "background"), 0, 0, 255, 255); + efl_pack_after(list, item, efl_pack_content_get(list, 29)); + break; + + case 40: + efl_file_set(efl_part(item, "background"), "./sky_01.jpg", NULL); + efl_gfx_image_scale_type_set(efl_part(item, "background"), EFL_GFX_IMAGE_SCALE_TYPE_FIT_OUTSIDE); + efl_pack_at(list, item, 39); + break; + + case 50: + efl_file_set(efl_part(item, "background"), "./sky_01.jpg", NULL); + efl_gfx_image_scale_type_set(efl_part(item, "background"), EFL_GFX_IMAGE_SCALE_TYPE_TILE); + efl_pack(list, item); + break; + + case 60: + efl_pack(list, item); + efl_pack_unpack(list, item); + efl_del(item); + break; + + default: + efl_pack_end(list, item); + } + } + + efl_pack_end(wbox, list); + + /*select mode */ + txt = efl_add(EFL_UI_TEXT_CLASS, wbox); + efl_gfx_size_hint_weight_set(txt, EFL_GFX_SIZE_HINT_EXPAND, 0.01); + efl_text_halign_set(txt, 0.02); + efl_text_interactive_selection_allowed_set(txt, EINA_FALSE); + efl_text_set(txt, "Select Mode"); + efl_pack_end(wbox, txt); + + bbox = efl_add(EFL_UI_BOX_CLASS, wbox); + efl_ui_direction_set(bbox, EFL_UI_DIR_HORIZONTAL); + efl_gfx_size_hint_weight_set(bbox, EFL_GFX_SIZE_HINT_EXPAND, 0.05); + + select_radio = radio = efl_add(EFL_UI_RADIO_CLASS, wbox); + efl_text_set(radio, "SINGLE"); + efl_ui_radio_state_value_set(radio, EFL_UI_SELECT_SINGLE); + efl_event_callback_add(radio, EFL_UI_RADIO_EVENT_CHANGED, _select_radio_changed, list); + efl_pack_end(bbox, radio); + radio = efl_add(EFL_UI_RADIO_CLASS, wbox); + efl_text_set(radio, "SINGLE_ALWAYS"); + efl_ui_radio_state_value_set(radio, EFL_UI_SELECT_SINGLE_ALWAYS); + efl_ui_radio_group_add(radio, select_radio); + efl_event_callback_add(radio, EFL_UI_RADIO_EVENT_CHANGED, _select_radio_changed, list); + efl_pack_end(bbox, radio); + radio = efl_add(EFL_UI_RADIO_CLASS, wbox); + efl_text_set(radio, "MULTI"); + efl_ui_radio_state_value_set(radio, EFL_UI_SELECT_MULTI); + efl_ui_radio_group_add(radio, select_radio); + efl_event_callback_add(radio, EFL_UI_RADIO_EVENT_CHANGED, _select_radio_changed, list); + efl_pack_end(bbox, radio); + radio = efl_add(EFL_UI_RADIO_CLASS, wbox); + efl_text_set(radio, "NONE"); + efl_ui_radio_state_value_set(radio, EFL_UI_SELECT_NONE); + efl_ui_radio_group_add(radio, select_radio); + efl_event_callback_add(radio, EFL_UI_RADIO_EVENT_CHANGED, _select_radio_changed, list); + efl_pack_end(bbox, radio); + efl_pack_end(wbox, bbox); + + /* scroll mode */ + txt = efl_add(EFL_UI_TEXT_CLASS, wbox); + efl_gfx_size_hint_weight_set(txt, EFL_GFX_SIZE_HINT_EXPAND, 0.01); + efl_text_interactive_selection_allowed_set(txt, EINA_FALSE); + efl_text_halign_set(txt, 0.02); + efl_text_set(txt, "Item Scroll"); + efl_pack_end(wbox, txt); + + priv_d.slider = slider = efl_add(EFL_UI_SLIDER_CLASS, wbox); + efl_ui_direction_set(slider, EFL_UI_DIR_HORIZONTAL); + efl_gfx_size_hint_weight_set(slider, 0.0, 0.05); + efl_gfx_size_hint_align_set(slider, 0.5, 0.5); + efl_gfx_size_hint_min_set(slider, EINA_SIZE2D(380, 20)); + efl_ui_range_min_max_set(slider, 0.0, 1.0); + efl_pack_end(wbox, slider); + + bbox = efl_add(EFL_UI_BOX_CLASS, wbox); + efl_ui_direction_set(bbox, EFL_UI_DIR_HORIZONTAL); + efl_gfx_size_hint_weight_set(bbox, EFL_GFX_SIZE_HINT_EXPAND, 0.05); + + rbox = efl_add(EFL_UI_BOX_CLASS, bbox); + efl_ui_direction_set(rbox, EFL_UI_DIR_VERTICAL); + + anim_radio = radio = efl_add(EFL_UI_RADIO_CLASS, rbox); + efl_gfx_size_hint_align_set(radio, 0.5, 0.5); + efl_text_set(radio, "ANIMATION OFF"); + efl_ui_radio_state_value_set(radio, 0); + efl_event_callback_add(radio, EFL_UI_RADIO_EVENT_CHANGED, _anim_radio_changed, NULL); + efl_pack_end(rbox, radio); + radio = efl_add(EFL_UI_RADIO_CLASS, rbox); + efl_gfx_size_hint_align_set(radio, 0.5, 0.5); + efl_text_set(radio, "ANIMATION ON"); + efl_ui_radio_state_value_set(radio, 1); + efl_ui_radio_group_add(radio, anim_radio); + efl_event_callback_add(radio, EFL_UI_RADIO_EVENT_CHANGED, _anim_radio_changed, NULL); + efl_pack_end(rbox, radio); + efl_pack_end(bbox, rbox); + + rbox = efl_add(EFL_UI_BOX_CLASS, bbox); + efl_ui_direction_set(rbox, EFL_UI_DIR_VERTICAL); + + scrl_btn = efl_add(EFL_UI_BUTTON_CLASS, rbox); + efl_text_set(scrl_btn, "Scroll Item"); + efl_gfx_size_hint_align_set(scrl_btn, 0.5, 0.5); + efl_gfx_size_hint_min_set(scrl_btn, EINA_SIZE2D(200, 25)); + efl_event_callback_add(scrl_btn, EFL_UI_EVENT_CLICKED, _scrl_btn_clicked, NULL); + efl_pack_end(rbox, scrl_btn); + + scrl_btn = efl_add(EFL_UI_BUTTON_CLASS, rbox); + efl_text_set(scrl_btn, "Scroll Item Align"); + efl_gfx_size_hint_align_set(scrl_btn, 0.5, 0.5); + efl_gfx_size_hint_min_set(scrl_btn, EINA_SIZE2D(200, 25)); + efl_event_callback_add(scrl_btn, EFL_UI_EVENT_CLICKED, _scrl_align_btn_clicked, NULL); + efl_pack_end(rbox, scrl_btn); + + efl_pack_end(bbox, rbox); + efl_pack_end(wbox, bbox); + + elm_win_resize_object_add(win, wbox); + //window show + efl_gfx_entity_visible_set(win, EINA_TRUE); + + elm_run(); + + return 0; +} +ELM_MAIN() \ No newline at end of file diff --git a/src/examples/elementary/efl_ui_view_list_example_1.c b/src/examples/elementary/efl_ui_view_list_example_1.c index 3994fa419f..621f81ee99 100644 --- a/src/examples/elementary/efl_ui_view_list_example_1.c +++ b/src/examples/elementary/efl_ui_view_list_example_1.c @@ -85,7 +85,7 @@ elm_main(int argc, char **argv) factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); efl_ui_model_connect(factory, "signal/elm,state,%v", "odd_style"); efl_ui_model_connect(factory, "elm.text", "name"); - efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + efl_ui_layout_factory_theme_config(factory, "list_item", NULL, "default"); li = efl_add(EFL_UI_VIEW_LIST_CLASS, win); efl_ui_view_list_layout_factory_set(li, factory); diff --git a/src/examples/elementary/efl_ui_view_list_example_2.c b/src/examples/elementary/efl_ui_view_list_example_2.c index 6a7c0eed2f..fac0e5d8f4 100644 --- a/src/examples/elementary/efl_ui_view_list_example_2.c +++ b/src/examples/elementary/efl_ui_view_list_example_2.c @@ -46,7 +46,7 @@ elm_main(int argc, char **argv) model = efl_add(EIO_MODEL_CLASS, efl_main_loop_get(), eio_model_path_set(efl_added, dirname)); factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); efl_ui_model_connect(factory, "elm.text", "filename"); - efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + efl_ui_layout_factory_theme_config(factory, "list_item", NULL, "default"); li = efl_add(EFL_UI_VIEW_LIST_CLASS, win); efl_ui_view_list_layout_factory_set(li, factory); diff --git a/src/examples/elementary/efl_ui_view_list_example_3.c b/src/examples/elementary/efl_ui_view_list_example_3.c index 53a816c661..c2e8281ed2 100644 --- a/src/examples/elementary/efl_ui_view_list_example_3.c +++ b/src/examples/elementary/efl_ui_view_list_example_3.c @@ -223,7 +223,7 @@ elm_main(int argc, char **argv) priv->model = _make_model(); factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); efl_ui_model_connect(factory, "elm.text", "filename"); - efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + efl_ui_layout_factory_theme_config(factory, "list_item", NULL, "default"); priv->list1 = efl_add(EFL_UI_VIEW_LIST_CLASS, win, efl_ui_view_model_set(efl_added, priv->model)); efl_event_callback_add(priv->list1, EFL_UI_VIEW_LIST_EVENT_ITEM_REALIZED, _realized_1_cb, priv); @@ -235,7 +235,7 @@ elm_main(int argc, char **argv) factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win); efl_ui_model_connect(factory, "elm.text", "filename"); efl_ui_model_connect(factory, "signal/elm,state,%v", "selected"); - efl_ui_layout_factory_theme_config(factory, "list", "item", "default"); + efl_ui_layout_factory_theme_config(factory, "list_item", NULL, "default"); priv->list2 = efl_add(EFL_UI_VIEW_LIST_CLASS, win, efl_ui_view_model_set(efl_added, priv->model)); efl_event_callback_add(priv->list2, EFL_UI_VIEW_LIST_EVENT_ITEM_REALIZED, _realized_2_cb, priv->list2); evas_object_size_hint_weight_set(priv->list2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h index 22175bf086..e9b00b1d50 100644 --- a/src/lib/efl/Efl.h +++ b/src/lib/efl/Efl.h @@ -92,6 +92,7 @@ typedef Efl_Gfx_Path_Command_Type Efl_Gfx_Path_Command; #include "interfaces/efl_ui_scrollbar.eo.h" #include "interfaces/efl_ui_scrollable_interactive.eo.h" #include "interfaces/efl_ui_selectable.eo.h" +#include "interfaces/efl_ui_multi_selectable.eo.h" #include "interfaces/efl_ui_zoom.eo.h" #include "interfaces/efl_screen.eo.h" diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c b/src/lib/efl/interfaces/efl_interfaces_main.c index d245e4afeb..4e02e1e5e1 100644 --- a/src/lib/efl/interfaces/efl_interfaces_main.c +++ b/src/lib/efl/interfaces/efl_interfaces_main.c @@ -74,6 +74,7 @@ #include "interfaces/efl_ui_scrollable_interactive.eo.c" #include "interfaces/efl_ui_scrollbar.eo.c" #include "interfaces/efl_ui_selectable.eo.c" +#include "interfaces/efl_ui_multi_selectable.eo.c" #include "interfaces/efl_ui_zoom.eo.c" EAPI void diff --git a/src/lib/efl/interfaces/efl_ui_item.eo b/src/lib/efl/interfaces/efl_ui_item.eo deleted file mode 100644 index 49ef31b6d5..0000000000 --- a/src/lib/efl/interfaces/efl_ui_item.eo +++ /dev/null @@ -1,54 +0,0 @@ -interface Efl.Ui.Item { - [[Efl UI item interface]] - legacy_prefix: null; - methods { - @property prev { - get { - [[Get the item before this one in the widget's list of items. - - See also @.next. - ]] - } - values { - item: Efl.Ui.Item; [[The item before the object in its parent's - list. If there is no previous item or in case - of error, $null is returned.]] - } - } - @property next { - get { - [[Get the item after this one in the widget's list of items. - - See also @.prev. - ]] - } - values { - item: Efl.Ui.Item; [[The item after the object in its parent's - list. If there is no next item or in case - of error, $null is returned.]] - } - } - @property selected { - [[Indicates whether this item is currently selected.]] - get { - [[Get the selected state of this item.]] - } - set { - [[Set the selected state of $item. - - This sets the selected state of the given item $it. - $true for selected, $false for not selected. - - If a new item is selected the previously selected will - be unselected. Previously selected item can be retrieved - with @Efl.Ui.Menu.selected_item.get. - - Selected items will be highlighted. - ]] - } - values { - selected: bool; [[The selection state.]] - } - } - } -} diff --git a/src/lib/efl/interfaces/efl_ui_multi_selectable.eo b/src/lib/efl/interfaces/efl_ui_multi_selectable.eo new file mode 100644 index 0000000000..8e82750441 --- /dev/null +++ b/src/lib/efl/interfaces/efl_ui_multi_selectable.eo @@ -0,0 +1,28 @@ +enum Efl.Ui.Select_Mode { + [[Type of multi selectable object.]] + legacy: efl_ui_select; + single, [[Only single child is selected. if the child is selected, + previous selected child will be unselected.]] + single_always, [[Same as single select except, this will be selected + in every select calls though child is already been selected.]] + multi, [[allow multiple selection of children.]] + none [[Last value of select mode. child cannot be selected at all.]] +} + +interface Efl.Ui.Multi_Selectable () +{ + [[Efl UI Multi selectable interface. + The container have to control select property of multiple chidren.]] + eo_prefix: efl_ui; + methods + { + @property select_mode { + [[The mode type for children selection.]] + set {} + get {} + values { + mode: Efl.Ui.Select_Mode; [[Type of selection of children]] + } + } + } +} diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 2853ba26e9..b59383a4d7 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -324,6 +324,13 @@ typedef Eo Efl_Ui_Focus_Manager; # include # include # include +# include +# include +# include +# include +# include +# include +# include # include # include # include diff --git a/src/lib/elementary/efl_ui_item.c b/src/lib/elementary/efl_ui_item.c new file mode 100644 index 0000000000..5eed4b2c7b --- /dev/null +++ b/src/lib/elementary/efl_ui_item.c @@ -0,0 +1,260 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_ACCESS_PROTECTED +#define EFL_UI_WIDGET_PART_BG_PROTECTED + +#include + +#include "elm_priv.h" +#include "efl_ui_item_private.h" + +#define MY_CLASS EFL_UI_ITEM_CLASS +#define MY_CLASS_PFX efl_ui_item + +#define MY_CLASS_NAME "Efl.Ui.Item" + +static void +_item_select(Eo *obj, Efl_Ui_Item_Data *pd) +{ + if (pd->selected && + (*(pd->select_mode) != EFL_UI_SELECT_SINGLE_ALWAYS)) + return; + if (*(pd->select_mode) == EFL_UI_SELECT_NONE) return; + + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + pd->selected = EINA_TRUE; + edje_object_signal_emit(wd->resize_obj, "efl,state,selected", "efl"); + efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED, NULL); +} + +static void +_item_unselect(Eo *obj, Efl_Ui_Item_Data *pd) +{ + if (!pd->selected) return; + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + pd->selected = EINA_FALSE; + edje_object_signal_emit(wd->resize_obj, "efl,state,unselected", "efl"); + efl_event_callback_call(obj, EFL_UI_EVENT_UNSELECTED, NULL); +} + +/* Mouse Controls */ +static Eina_Bool +_item_longpressed(void *data) +{ + Efl_Ui_Item *item = data; + EFL_UI_ITEM_DATA_GET_OR_RETURN(item, pd, ECORE_CALLBACK_CANCEL); + + pd->longpress_timer = NULL; + + efl_event_callback_call(item, EFL_UI_EVENT_LONGPRESSED, NULL); + return ECORE_CALLBACK_CANCEL; +} + +static void +_item_mouse_down(void *data, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + Evas_Event_Mouse_Down *ev = event_info; + Eo *item = data; + EFL_UI_ITEM_DATA_GET_OR_RETURN(item, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(item, wd); + if (wd->disabled) return; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; + + edje_object_signal_emit(wd->resize_obj, "efl,state,pressed", "efl"); + + pd->longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _item_longpressed, item); + efl_event_callback_call(item, EFL_UI_EVENT_PRESSED, NULL); +} + +static void +_item_mouse_up(void *data, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + Evas_Event_Mouse_Up *ev = event_info; + Eo *item = data; + EFL_UI_ITEM_DATA_GET_OR_RETURN(item, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(item, wd); + if (wd->disabled) return; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) + { + //FIXME: should we send this message to fallback? + edje_object_signal_emit(wd->resize_obj, "efl,state,unpressed", "efl"); + //efl_event_callback_call(item, EFL_UI_EVENT_UNPRESSED, NULL); + return; + } + + if (pd->longpress_timer) + { + ecore_timer_del(pd->longpress_timer); + pd->longpress_timer = NULL; + } + + edje_object_signal_emit(wd->resize_obj, "efl,state,unpressed", "efl"); + efl_event_callback_call(item, EFL_UI_EVENT_UNPRESSED, NULL); + + if ((*(pd->select_mode) != EFL_UI_SELECT_SINGLE_ALWAYS) && (pd->selected)) + _item_unselect(item, pd); + else if (*(pd->select_mode) != EFL_UI_SELECT_NONE) + _item_select(item, pd); +} + +static void +_item_mouse_move(void *data EINA_UNUSED, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + Evas_Event_Mouse_Move *ev = event_info; + Eo *item = data; + EFL_UI_ITEM_DATA_GET_OR_RETURN(item, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(item, wd); + if (wd->disabled) return; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) + { + edje_object_signal_emit(wd->resize_obj, "efl,state,unpressed", "efl"); + return; + } +} + +static void +_item_mouse_in(void *data EINA_UNUSED, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + Evas_Event_Mouse_In *ev = event_info; + Eo *item = data; + EFL_UI_ITEM_DATA_GET_OR_RETURN(item, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(item, wd); + if (wd->disabled) return; + + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; +} + +static void +_item_mouse_callback_add(Eo *obj, void *data) +{ + evas_object_event_callback_add + (obj, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down, data); + evas_object_event_callback_add + (obj, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up, data); + evas_object_event_callback_add + (obj, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move, data); + evas_object_event_callback_add + (obj, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in, data); +} + +static void +_item_mouse_callback_del(Eo *obj, void *data) +{ + evas_object_event_callback_del_full + (obj, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down, data); + evas_object_event_callback_del_full + (obj, EVAS_CALLBACK_MOUSE_UP, _item_mouse_up, data); + evas_object_event_callback_del_full + (obj, EVAS_CALLBACK_MOUSE_MOVE, _item_mouse_move, data); + evas_object_event_callback_del_full + (obj, EVAS_CALLBACK_MOUSE_IN, _item_mouse_in, data); +} +/* Mouse Controls ends */ + +static void +_sizing_eval(Evas_Object *obj, Efl_Ui_Item_Data *pd) +{ + Evas_Coord minh = -1, minw = -1; + Evas_Coord rest_w = 0, rest_h = 0; + ELM_WIDGET_DATA_GET_OR_RETURN(pd->obj, wd); + + edje_object_size_min_restricted_calc(wd->resize_obj, &minw, &minh, + rest_w, rest_h); + evas_object_size_hint_min_set(obj, minw, minh); + + pd->needs_size_calc = EINA_FALSE; +} + +static void +_efl_ui_item_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Item_Data *pd) +{ + if (pd->needs_size_calc) return; + pd->needs_size_calc = EINA_TRUE; + + efl_canvas_group_change(obj); +} + +EOLIAN static void +_efl_ui_item_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Item_Data *pd) +{ + if (pd->needs_size_calc) + { + _sizing_eval(obj, pd); + pd->needs_size_calc = EINA_FALSE; + } +} + +EOLIAN static Eo * +_efl_ui_item_efl_object_constructor(Eo *obj, Efl_Ui_Item_Data *pd) +{ + pd->obj = obj; + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + return obj; +} + +EOLIAN static Efl_Object * +_efl_ui_item_efl_object_finalize(Eo *obj, Efl_Ui_Item_Data *pd EINA_UNUSED) +{ + Eo *eo; + eo = efl_finalize(efl_super(obj, MY_CLASS)); + ELM_WIDGET_DATA_GET_OR_RETURN(eo, wd, eo); + + _item_mouse_callback_add(wd->resize_obj, eo); + return eo; +} + +EOLIAN static void +_efl_ui_item_efl_object_destructor(Eo *obj, Efl_Ui_Item_Data *pd EINA_UNUSED) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + _item_mouse_callback_del(wd->resize_obj, obj); + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static int +_efl_ui_item_index_get(const Eo *obj, Efl_Ui_Item_Data *pd) +{ + return efl_pack_index_get(pd->parent, obj); +} + +EOLIAN static void +_efl_ui_item_selected_set(Eo *obj, Efl_Ui_Item_Data *pd, Eina_Bool select) +{ + Eina_Bool selected = !!select; + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + if (wd->disabled) return; + + if (selected) _item_select(obj, pd); + else _item_unselect(obj, pd); +} + +EOLIAN static Eina_Bool +_efl_ui_item_selected_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd) +{ + return pd->selected; +} + +/* Internal EO APIs and hidden overrides */ + +#define EFL_UI_ITEM_EXTRA_OPS \ + ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_item) + +#include "efl_ui_item.eo.c" diff --git a/src/lib/elementary/efl_ui_item.eo b/src/lib/elementary/efl_ui_item.eo new file mode 100644 index 0000000000..6137dd9fb7 --- /dev/null +++ b/src/lib/elementary/efl_ui_item.eo @@ -0,0 +1,30 @@ +abstract Efl.Ui.Item (Efl.Ui.Layout.Object, Efl.Ui.Selectable, Efl.Ui.Clickable) +{ + [[Item abstract class for pack widget. All item have to be inherited from this class.]] + methods { + @property index { + [[index number of item from their parent object.]] + get {} + values { + index : int; + } + } + @property selected { + [[Select property for item object. + Item can be selected by user mouse/key input also]] + set {} + get {} + values { + select: bool; + } + } + } + implements { + //Efl.Object + Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.destructor; + //Efl.Canvas + Efl.Canvas.Group.group_calculate; + } +} diff --git a/src/lib/elementary/efl_ui_item_private.h b/src/lib/elementary/efl_ui_item_private.h new file mode 100644 index 0000000000..b8849a2316 --- /dev/null +++ b/src/lib/elementary/efl_ui_item_private.h @@ -0,0 +1,37 @@ +#ifndef EFL_UI_ITEM_PRIVATE_H +#define EFL_UI_ITEM_PRIVATE_H + +#include "Elementary.h" + +typedef struct _Efl_Ui_Item_Data +{ + // Eo Objects + Eo *obj; /* Self-Object */ + Eo *parent; /* Parent Widget */ + + Efl_Ui_Select_Mode *select_mode; /* Select Mdoe of parent widget */ + Ecore_Timer *longpress_timer; /* Timer for longpress handle */ + + // Boolean Data + Eina_Bool selected : 1; /* State for item selected */ + Eina_Bool needs_size_calc : 1; /* Flag for Size calculation */ +} Efl_Ui_Item_Data; + + +#define EFL_UI_ITEM_DATA_GET(o, pd) \ + Efl_Ui_Item_Data * pd = efl_data_scope_safe_get(o, EFL_UI_ITEM_CLASS) + +#define EFL_UI_ITEM_DATA_GET_OR_RETURN(o, ptr, ...) \ + EFL_UI_ITEM_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + ERR("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return __VA_ARGS__; \ + } + +#define EFL_UI_ITEM_CHECK_OR_RETURN(obj, ...) \ + if (EINA_UNLIKELY(!efl_isa((obj), EFL_UI_ITEM_CLASS))) \ + return __VA_ARGS__; + +#endif diff --git a/src/lib/elementary/efl_ui_list.c b/src/lib/elementary/efl_ui_list.c new file mode 100644 index 0000000000..bb6abf3ef3 --- /dev/null +++ b/src/lib/elementary/efl_ui_list.c @@ -0,0 +1,1140 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define ELM_LAYOUT_PROTECTED +#define EFL_UI_SCROLL_MANAGER_PROTECTED +#define EFL_UI_SCROLLBAR_PROTECTED +#define EFL_UI_SCROLLBAR_BETA + +#include +#include "elm_priv.h" +#include "efl_ui_list_item_private.h" +#include "efl_ui_item_private.h" +#include "efl_ui_list_private.h" + +#define MY_CLASS EFL_UI_LIST_CLASS +#define MY_CLASS_PFX efl_ui_list + +#define MY_CLASS_NAME "Efl.Ui.List" + +static void +_item_scroll_internal(Eo *obj, + Efl_Ui_List_Item *item, + double align, + Eina_Bool anim) +{ + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + Eina_Rect ipos, view; + Eina_Position2D vpos; + + if (!pd->smanager) return; + + ipos = efl_gfx_entity_geometry_get(item); + view = efl_ui_scrollable_viewport_geometry_get(pd->smanager); + vpos = efl_ui_scrollable_content_pos_get(pd->smanager); + + ipos.x = view.x; + ipos.w = ipos.w; + + // FIXME: align case will not correctly show in the position because of + // bar size calculation. there are no certain way to know the scroll calcuation finished. + if (EINA_DBL_EQ(align, -1.0)) + { + ipos.y = ipos.y + vpos.y - view.y; + ipos.h = ipos.h; + } + else if ((align > 0.0 || EINA_DBL_EQ(align, 0.0)) && + (align < 1.0 || EINA_DBL_EQ(align, 1.0))) + { + ipos.y = ipos.y + vpos.y - view.y - (int)((view.h - ipos.h) * align); + ipos.h = view.h; + } + else ERR("align (%.2lf) is not proper value. it must be the value between [0.0 , 1.0]!", align); + + efl_ui_scrollable_scroll(pd->smanager, ipos, anim); +} + +static void +_efl_ui_list_bar_read_and_update(Eo *obj) +{ + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + double vx = 0.0, vy = 0.0; + + edje_object_part_drag_value_get + (wd->resize_obj, "efl.dragable.vbar", NULL, &vy); + + /* FIXME: Horizontal Scroll is not yet supported in the list. + edje_object_part_drag_value_get + (wd->resize_obj, "efl.dragable.hbar", &vx, NULL); + */ + + efl_ui_scrollbar_bar_position_set(pd->smanager, vx, vy); +} + +static void +_efl_ui_list_reload_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *list = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(list, pd); + + efl_ui_scrollbar_bar_visibility_update(pd->smanager); +} + +static void +_efl_ui_list_vbar_drag_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + _efl_ui_list_bar_read_and_update(data); + + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_DRAG, &type); +} + +static void +_efl_ui_list_vbar_press_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_PRESS, &type); +} + +static void +_efl_ui_list_vbar_unpress_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_VERTICAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESS, &type); +} + +static void +_efl_ui_list_edje_drag_start_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *list = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(list, pd); + + _efl_ui_list_bar_read_and_update(list); + + pd->freeze_want = efl_ui_scrollable_scroll_freeze_get(pd->smanager); + efl_ui_scrollable_scroll_freeze_set(pd->smanager, EINA_TRUE); + efl_event_callback_call(list, EFL_UI_EVENT_SCROLL_DRAG_START, NULL); +} + +static void +_efl_ui_list_edje_drag_stop_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *list = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(list, pd); + + _efl_ui_list_bar_read_and_update(list); + + efl_ui_scrollable_scroll_freeze_set(pd->smanager, pd->freeze_want); + efl_event_callback_call(list, EFL_UI_EVENT_SCROLL_DRAG_STOP, NULL); +} + +static void +_efl_ui_list_edje_drag_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + _efl_ui_list_bar_read_and_update(data); +} + +/* FIXME: Horizontal Scroll is not yet supported in the list. + static void + _efl_ui_list_hbar_drag_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) + { + _efl_ui_list_bar_read_and_update(data); + + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_DRAG, &type); + } + + static void + _efl_ui_list_hbar_press_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) + { + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_PRESS, &type); + } + + static void + _efl_ui_list_hbar_unpress_cb(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) + { + Efl_Ui_Scrollbar_Direction type = EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL; + efl_event_callback_call(data, EFL_UI_SCROLLBAR_EVENT_BAR_UNPRESS, &type); + } + */ + +static void +_efl_ui_list_bar_size_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Eo *obj = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + double width = 0.0, height = 0.0; + + edje_object_calc_force(wd->resize_obj); + efl_ui_scrollbar_bar_size_get(pd->smanager, &width, &height); + edje_object_part_drag_size_set(wd->resize_obj, "efl.dragable.hbar", width, 1.0); + edje_object_part_drag_size_set(wd->resize_obj, "efl.dragable.vbar", 1.0, height); +} + +static void +_efl_ui_list_bar_pos_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Eo *obj = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + double posx = 0.0, posy = 0.0; + + efl_ui_scrollbar_bar_position_get(pd->smanager, &posx, &posy); + edje_object_part_drag_value_set(wd->resize_obj, "efl.dragable.hbar", posx, 0.0); + edje_object_part_drag_value_set(wd->resize_obj, "efl.dragable.vbar", 0.0, posy); +} + +static void +_efl_ui_list_bar_show_cb(void *data, const Efl_Event *event) +{ + Eo *obj = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + Efl_Ui_Scrollbar_Direction type = *(Efl_Ui_Scrollbar_Direction *)(event->info); + + if (type == EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,show,hbar", "efl"); + else if (type == EFL_UI_SCROLLBAR_DIRECTION_VERTICAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,show,vbar", "efl"); +} + +static void +_efl_ui_list_bar_hide_cb(void *data, const Efl_Event *event) +{ + Eo *obj = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + Efl_Ui_Scrollbar_Direction type = *(Efl_Ui_Scrollbar_Direction *)(event->info); + + if (type == EFL_UI_SCROLLBAR_DIRECTION_HORIZONTAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,hide,hbar", "efl"); + else if (type == EFL_UI_SCROLLBAR_DIRECTION_VERTICAL) + edje_object_signal_emit(wd->resize_obj, "efl,action,hide,vbar", "efl"); +} + +static void +_scroll_edje_object_attach(Eo *obj) +{ + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + + efl_layout_signal_callback_add + (obj, "reload", "efl", + _efl_ui_list_reload_cb, obj); + efl_layout_signal_callback_add + (obj, "drag", "efl.dragable.vbar", + _efl_ui_list_vbar_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,set", "efl.dragable.vbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,start", "efl.dragable.vbar", + _efl_ui_list_edje_drag_start_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,stop", "efl.dragable.vbar", + _efl_ui_list_edje_drag_stop_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,step", "efl.dragable.vbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,page", "efl.dragable.vbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "efl,vbar,press", "efl", + _efl_ui_list_vbar_press_cb, obj); + efl_layout_signal_callback_add + (obj, "efl,vbar,unpress", "efl", + _efl_ui_list_vbar_unpress_cb, obj); + + /* FIXME: Horizontal Scroll is not yet supported in the list. + efl_layout_signal_callback_add + (obj, "drag", "efl.dragable.hbar", + _efl_ui_list_hbar_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,set", "efl.dragable.hbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,start", "efl.dragable.hbar", + _efl_ui_list_edje_drag_start_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,stop", "efl.dragable.hbar", + _efl_ui_list_edje_drag_stop_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,step", "efl.dragable.hbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "drag,page", "efl.dragable.hbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_add + (obj, "efl,hbar,press", "efl", + _efl_ui_list_hbar_press_cb, obj); + efl_layout_signal_callback_add + (obj, "efl,hbar,unpress", "efl", + _efl_ui_list_hbar_unpress_cb, obj); + */ +} + +static void +_scroll_edje_object_detach(Eo *obj) +{ + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + + efl_layout_signal_callback_del + (obj, "reload", "efl", + _efl_ui_list_reload_cb, obj); + efl_layout_signal_callback_del + (obj, "drag", "efl.dragable.vbar", + _efl_ui_list_vbar_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,set", "efl.dragable.vbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,start", "efl.dragable.vbar", + _efl_ui_list_edje_drag_start_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,stop", "efl.dragable.vbar", + _efl_ui_list_edje_drag_stop_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,step", "efl.dragable.vbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,page", "efl.dragable.vbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "efl,vbar,press", "efl", + _efl_ui_list_vbar_press_cb, obj); + efl_layout_signal_callback_del + (obj, "efl,vbar,unpress", "efl", + _efl_ui_list_vbar_unpress_cb, obj); + + /* FIXME: Horizontal Scroll is not yet supported in the list. + efl_layout_signal_callback_del + (obj, "drag", "efl.dragable.hbar", + _efl_ui_list_hbar_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,set", "efl.dragable.hbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,start", "efl.dragable.hbar", + _efl_ui_list_edje_drag_start_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,stop", "efl.dragable.hbar", + _efl_ui_list_edje_drag_stop_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,step", "efl.dragable.hbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "drag,page", "efl.dragable.hbar", + _efl_ui_list_edje_drag_cb, obj); + efl_layout_signal_callback_del + (obj, "efl,hbar,press", "efl", + _efl_ui_list_hbar_press_cb, obj); + efl_layout_signal_callback_del + (obj, "efl,hbar,unpress", "efl", + _efl_ui_list_hbar_unpress_cb, obj); + */ +} + +static void +_efl_ui_list_pan_resized_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Eo *obj = data; + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + if (!pd->smanager) return; + + elm_layout_sizing_eval(obj); + + if (!pd->pan_resized) + { + Eina_Rect view = efl_ui_scrollable_viewport_geometry_get(pd->smanager); + // FIXME: Below code is workaround size check + if (view.h > 1) + { + pd->pan_resized = EINA_TRUE; + if (pd->scroll.item) + { + _item_scroll_internal(obj, pd->scroll.item, pd->scroll.align, pd->scroll.anim); + + pd->scroll.item = NULL; + pd->scroll.align = 0.0; + pd->scroll.anim = EINA_FALSE; + return; + } + } + } +} + +static void +_efl_ui_list_resized_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + elm_layout_sizing_eval(data); +} + +static void +_efl_ui_list_size_hint_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + elm_layout_sizing_eval(data); +} + +EOLIAN static Eo * +_efl_ui_list_efl_object_constructor(Eo *obj, Efl_Ui_List_Data *pd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + return obj; +} + +EOLIAN static Eo * +_efl_ui_list_efl_object_finalize(Eo *obj, + Efl_Ui_List_Data *pd) +{ + obj = efl_finalize(efl_super(obj, MY_CLASS)); + + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL); + + efl_ui_layout_object_theme_set(obj, "list", "base", efl_ui_widget_style_get(obj)); + + pd->smanager = efl_add(EFL_UI_SCROLL_MANAGER_CLASS, obj); + efl_ui_mirrored_set(pd->smanager, efl_ui_mirrored_get(obj)); + + pd->pan = efl_add(EFL_UI_PAN_CLASS, obj); + + efl_ui_scroll_manager_pan_set(pd->smanager, pd->pan); + edje_object_part_swallow(wd->resize_obj, "efl.content", pd->pan); + + pd->box = efl_add(EFL_UI_BOX_CLASS, obj, + efl_ui_direction_set(efl_added, EFL_UI_DIR_VERTICAL)); + efl_ui_mirrored_set(pd->box, efl_ui_mirrored_get(obj)); + efl_content_set(pd->pan, pd->box); + + pd->select_mode = EFL_UI_SELECT_SINGLE; + + _scroll_edje_object_attach(obj); + + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED, + _efl_ui_list_bar_size_changed_cb, obj); + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_POS_CHANGED, + _efl_ui_list_bar_pos_changed_cb, obj); + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SHOW, + _efl_ui_list_bar_show_cb, obj); + efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_HIDE, + _efl_ui_list_bar_hide_cb, obj); + efl_event_callback_add(obj, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_list_resized_cb, obj); + efl_event_callback_add(obj, EFL_GFX_ENTITY_EVENT_CHANGE_SIZE_HINTS, + _efl_ui_list_size_hint_changed_cb, obj); + efl_event_callback_add(pd->pan, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_list_pan_resized_cb, obj); + + elm_layout_sizing_eval(obj); + + return obj; +} + +EOLIAN static void +_efl_ui_list_efl_object_destructor(Eo *obj, Efl_Ui_List_Data *pd) +{ + _scroll_edje_object_detach(obj); + + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED, + _efl_ui_list_bar_size_changed_cb, obj); + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_POS_CHANGED, + _efl_ui_list_bar_pos_changed_cb, obj); + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SHOW, + _efl_ui_list_bar_show_cb, obj); + efl_event_callback_del(obj, EFL_UI_SCROLLBAR_EVENT_BAR_HIDE, + _efl_ui_list_bar_hide_cb, obj); + efl_event_callback_del(obj, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_list_resized_cb, obj); + efl_event_callback_del(obj, EFL_GFX_ENTITY_EVENT_CHANGE_SIZE_HINTS, + _efl_ui_list_size_hint_changed_cb, obj); + efl_event_callback_del(pd->pan, EFL_GFX_ENTITY_EVENT_RESIZE, + _efl_ui_list_pan_resized_cb, obj); + + efl_del(pd->box); + pd->box = NULL; + efl_del(pd->pan); + pd->pan = NULL; + efl_del(pd->smanager); + pd->smanager = NULL; + + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_ui_list_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd EINA_UNUSED) +{ + // Need to be implemented + efl_canvas_group_calculate(efl_super(obj, MY_CLASS)); +} + +EOLIAN static void +_efl_ui_list_elm_layout_sizing_eval(Eo *obj, Efl_Ui_List_Data *pd) +{ + Eina_Size2D min = {0, 0}, max = {0, 0}, size = {-1, -1}; + Eina_Rect view = {}; + Evas_Coord vmw = 0, vmh = 0; + double xw = 0.0, yw = 0.0; + + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + if (pd->box) + { + min = efl_gfx_size_hint_combined_min_get(pd->box); + max = efl_gfx_size_hint_max_get(pd->box); + efl_gfx_size_hint_weight_get(pd->box, &xw, &yw); + } + + if (pd->smanager) + view = efl_ui_scrollable_viewport_geometry_get(pd->smanager); + + if (xw > 0.0) + { + if ((min.w > 0) && (view.w < min.w)) + view.w = min.w; + else if ((max.w > 0) && (view.w > max.w)) + view.w = max.w; + } + else if (min.w > 0) + view.w = min.w; + + if (yw > 0.0) + { + if ((min.h > 0) && (view.h < min.h)) + view.h = min.h; + else if ((max.h > 0) && (view.h > max.h)) + view.h = max.h; + } + else if (min.h > 0) + view.h = min.h; + + if (pd->box) efl_gfx_entity_size_set(pd->box, EINA_SIZE2D(view.w, view.h)); + + edje_object_size_min_calc(wd->resize_obj, &vmw, &vmh); + + if (pd->match_content_w) size.w = vmw + min.w; + if (pd->match_content_h) size.h = vmh + min.h; + + max = efl_gfx_size_hint_max_get(obj); + if ((max.w > 0) && (size.w > max.w)) size.w = max.w; + if ((max.h > 0) && (size.h > max.h)) size.h = max.h; + + efl_gfx_size_hint_min_set(obj, size); +} + +//FIXME: is this box related API could be improved more? +EOLIAN static int +_efl_ui_list_efl_container_content_count(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->box ? efl_content_count(pd->box) : 0; +} + +EOLIAN static Eina_Iterator * +_efl_ui_list_efl_container_content_iterate(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->box ? efl_content_iterate(pd->box) : NULL; +} + +/* FIXME: Direction is not supported yet in the list + EOLIAN static void + _efl_ui_list_efl_ui_direction_direction_set(Eo *obj, Efl_Ui_List_Data *pd, Efl_Ui_Dir dir) + { + switch (dir) + { + case EFL_UI_DIR_RTL: + // FIXME: Should be inverted! + case EFL_UI_DIR_HORIZONTAL: + case EFL_UI_DIR_LTR: + pd->dir = EFL_UI_DIR_HORIZONTAL; + break; + + case EFL_UI_DIR_UP: + // FIXME: Should be inverted! + case EFL_UI_DIR_DOWN: + case EFL_UI_DIR_VERTICAL: + case EFL_UI_DIR_DEFAULT: + default: + pd->dir = EFL_UI_DIR_VERTICAL; + break; + } + + efl_pack_layout_request(obj); + } + */ + +EOLIAN static Efl_Ui_Theme_Apply +_efl_ui_list_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_List_Data *pd) +{ + Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED; + int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS)); + if (!int_ret) return EFL_UI_THEME_APPLY_FAILED; + + efl_ui_mirrored_set(pd->smanager, efl_ui_mirrored_get(obj)); + + elm_layout_sizing_eval(obj); + + return int_ret; +} + +static void +_list_item_pressed(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_List_Item *item = event->object; + efl_event_callback_call(obj, EFL_UI_EVENT_PRESSED, item); +} + +static void +_list_item_unpressed(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_List_Item *item = event->object; + efl_event_callback_call(obj, EFL_UI_EVENT_UNPRESSED, item); +} + +static void +_list_item_longpressed(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_List_Item *item = event->object; + efl_event_callback_call(obj, EFL_UI_EVENT_LONGPRESSED, item); +} + +static void +_list_item_selected(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_List_Item *item = event->object; + Efl_Ui_List_Item *selected; + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + + /* Single Select */ + if (pd->select_mode != EFL_UI_SELECT_MULTI) + { + EINA_LIST_FREE(pd->selected, selected) + { + if (selected != item) + efl_ui_item_selected_set(selected, EINA_FALSE); + } + } + pd->selected = eina_list_append(pd->selected, item); + pd->last_selected = item; + + efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED, item); +} + +static void +_list_item_unselected(void *data, const Efl_Event *event) +{ + Eo *obj = data; + Efl_Ui_List_Item *item = event->object; + EFL_UI_LIST_DATA_GET_OR_RETURN(obj, pd); + + pd->selected = eina_list_remove(pd->selected, item); + if (pd->last_selected == item) pd->last_selected = NULL; + + efl_event_callback_call(obj, EFL_UI_EVENT_UNSELECTED, item); +} + +static Eina_Bool +_list_item_process(Eo *obj, Efl_Ui_List_Data *pd, EINA_UNUSED Efl_Ui_List_Item *it) +{ + EFL_UI_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); + + //FIXME: This is tricky workaround for set select mode and parent value. + EFL_UI_LIST_ITEM_DATA_GET(it, ld); + EFL_UI_ITEM_DATA_GET(it, id); + id->select_mode = &(pd->select_mode); + id->parent = obj; + ld->parent = obj; + efl_ui_mirrored_set(it, efl_ui_mirrored_get(obj)); + + efl_event_callback_add(it, EFL_UI_EVENT_PRESSED, _list_item_pressed, obj); + efl_event_callback_add(it, EFL_UI_EVENT_UNPRESSED, _list_item_unpressed, obj); + efl_event_callback_add(it, EFL_UI_EVENT_LONGPRESSED, _list_item_longpressed, obj); + efl_event_callback_add(it, EFL_UI_EVENT_SELECTED, _list_item_selected, obj); + efl_event_callback_add(it, EFL_UI_EVENT_UNSELECTED, _list_item_unselected, obj); + + return EINA_TRUE; +} + +static void +_list_item_clear(Eo *obj, Efl_Ui_List_Data *pd EINA_UNUSED, EINA_UNUSED Efl_Ui_List_Item *it) +{ + EFL_UI_LIST_ITEM_CHECK_OR_RETURN(it); + EFL_UI_LIST_ITEM_DATA_GET(it, ld); + EFL_UI_ITEM_DATA_GET(it, id); + id->select_mode = NULL; + id->parent = NULL; + ld->parent = NULL; + + efl_event_callback_del(it, EFL_UI_EVENT_PRESSED, _list_item_pressed, obj); + efl_event_callback_del(it, EFL_UI_EVENT_UNPRESSED, _list_item_unpressed, obj); + efl_event_callback_del(it, EFL_UI_EVENT_LONGPRESSED, _list_item_longpressed, obj); + efl_event_callback_del(it, EFL_UI_EVENT_SELECTED, _list_item_selected, obj); + efl_event_callback_del(it, EFL_UI_EVENT_UNSELECTED, _list_item_unselected, obj); +} + +/* Pack APIs */ +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_pack_clear(Eo *obj, Efl_Ui_List_Data *pd) +{ + Eina_Bool ret = efl_pack_clear(pd->box); + + if (ret) + { + eina_list_free(pd->items); + eina_list_free(pd->selected); + pd->items = NULL; + pd->selected = NULL; + } + + elm_layout_sizing_eval(obj); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_unpack_all(Eo *obj, Efl_Ui_List_Data *pd) +{ + Eina_Bool ret = efl_pack_unpack_all(pd->box); + + if (ret) + { + Efl_Ui_List_Item *it = NULL; + EINA_LIST_FREE(pd->items, it) + { + _list_item_clear(obj, pd, it); + } + eina_list_free(pd->selected); + pd->items = NULL; + pd->selected = NULL; + } + + elm_layout_sizing_eval(obj); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_unpack(Eo *obj, Efl_Ui_List_Data *pd, Efl_Gfx_Entity *subobj) +{ + Eina_Bool ret = efl_pack_unpack(pd->box, subobj); + Efl_Ui_List_Item *item = (Efl_Ui_List_Item *)subobj; + + if (ret) + { + pd->items = eina_list_remove(pd->items, item); + if (efl_ui_item_selected_get(item)) + { + pd->selected = eina_list_remove(pd->selected, item); + } + _list_item_clear(obj, pd, item); + } + + elm_layout_sizing_eval(obj); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_pack(Eo *obj, Efl_Ui_List_Data *pd, Efl_Gfx_Entity *subobj) +{ + if (!_list_item_process(obj, pd, subobj)) return EINA_FALSE; + + Eina_Bool ret = efl_pack_end(pd->box, subobj); + pd->items = eina_list_append(pd->items, subobj); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_linear_pack_end(Eo *obj, Efl_Ui_List_Data *pd, Efl_Gfx_Entity *subobj) +{ + if (!_list_item_process(obj, pd, subobj)) return EINA_FALSE; + + Eina_Bool ret = efl_pack_end(pd->box, subobj); + pd->items = eina_list_append(pd->items, subobj); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_linear_pack_begin(Eo *obj, Efl_Ui_List_Data *pd, Efl_Gfx_Entity *subobj) +{ + if (!_list_item_process(obj, pd, subobj)) return EINA_FALSE; + + Eina_Bool ret = efl_pack_begin(pd->box, subobj); + pd->items = eina_list_prepend(pd->items, subobj); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_linear_pack_before(Eo *obj, + Efl_Ui_List_Data *pd, + Efl_Gfx_Entity *subobj, + const Efl_Gfx_Entity *existing) +{ + if (!_list_item_process(obj, pd, subobj)) return EINA_FALSE; + EFL_UI_LIST_ITEM_CHECK_OR_RETURN(existing, EINA_FALSE); + + Eina_Bool ret = efl_pack_before(pd->box, subobj, existing); + pd->items = eina_list_prepend_relative(pd->items, subobj, existing); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_linear_pack_after(Eo *obj, + Efl_Ui_List_Data *pd, + Efl_Gfx_Entity *subobj, + const Efl_Gfx_Entity *existing) +{ + if (!_list_item_process(obj, pd, subobj)) return EINA_FALSE; + EFL_UI_LIST_ITEM_CHECK_OR_RETURN(existing, EINA_FALSE); + + Eina_Bool ret = efl_pack_after(pd->box, subobj, existing); + pd->items = eina_list_append_relative(pd->items, subobj, existing); + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_pack_linear_pack_at(Eo *obj, + Efl_Ui_List_Data *pd, + Efl_Gfx_Entity *subobj, + int index) +{ + if (!_list_item_process(obj, pd, subobj)) return EINA_FALSE; + Efl_Ui_List_Item *existing = efl_pack_content_get(pd->box, index); + + Eina_Bool ret = efl_pack_at(pd->box, subobj, index); + pd->items = eina_list_append_relative(pd->items, subobj, existing); + return ret; +} + +EOLIAN static Efl_Gfx_Entity * +_efl_ui_list_efl_pack_linear_pack_content_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, int index) +{ + return efl_pack_content_get(pd->box, index); +} + +EOLIAN static Efl_Gfx_Entity * +_efl_ui_list_efl_pack_linear_pack_unpack_at(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, int index) +{ + return efl_pack_unpack_at(pd->box, index); +} + +EOLIAN static int +_efl_ui_list_efl_pack_linear_pack_index_get(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + const Efl_Gfx_Entity *subobj) +{ + return efl_pack_index_get(pd->box, subobj); +} + +EOLIAN static void +_efl_ui_list_efl_pack_layout_layout_update(Eo *obj, Efl_Ui_List_Data *pd) +{ + efl_pack_layout_update(pd->box); + elm_layout_sizing_eval(obj); + + efl_event_callback_legacy_call(obj, EFL_PACK_EVENT_LAYOUT_UPDATED, NULL); +} + +EOLIAN static void +_efl_ui_list_efl_pack_layout_layout_request(Eo *obj, Efl_Ui_List_Data *pd) +{ + efl_pack_layout_request(pd->box); + elm_layout_sizing_eval(obj); +} + +EOLIAN static void +_efl_ui_list_efl_pack_pack_padding_set(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + double h, + double v, + Eina_Bool scalable) +{ + efl_pack_padding_set(pd->box, h, v, scalable); +} + +EOLIAN static void +_efl_ui_list_efl_pack_pack_padding_get(const Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + double *h, + double *v, + Eina_Bool *scalable) +{ + efl_pack_padding_get(pd->box, h, v, scalable); +} + +/* FIXME: align could not work properly on the list + EOLIAN static void + _efl_ui_list_efl_pack_pack_align_set(Eo *obj, Efl_Ui_List_Data *pd, double h, double v) + { + efl_pack_align_set(pd->box, h, v); + } + + EOLIAN static void + _efl_ui_list_efl_pack_pack_align_get(Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd, double *h, double *v) + { + efl_pack_align_get(pd->box, &h, &v); + } + */ + +/* Scroll APIs */ +EOLIAN static Eina_Size2D +_efl_ui_list_efl_ui_scrollable_interactive_content_size_get(const Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd) +{ + return efl_ui_scrollable_content_size_get(pd->smanager); +} + +EOLIAN static Eina_Rect +_efl_ui_list_efl_ui_scrollable_interactive_viewport_geometry_get(const Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd) +{ + return efl_ui_scrollable_viewport_geometry_get(pd->smanager); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollable_interactive_bounce_enabled_set(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Eina_Bool horiz, + Eina_Bool vert) +{ + efl_ui_scrollable_bounce_enabled_set(pd->smanager, horiz, vert); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollable_interactive_bounce_enabled_get(const Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Eina_Bool *horiz, + Eina_Bool *vert) +{ + efl_ui_scrollable_bounce_enabled_get(pd->smanager, horiz, vert); +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_ui_scrollable_interactive_scroll_hold_get(const Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd) +{ + return efl_ui_scrollable_scroll_hold_get(pd->smanager); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollable_interactive_scroll_hold_set(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Eina_Bool hold) +{ + efl_ui_scrollable_scroll_hold_set(pd->smanager, hold); +} + +EOLIAN static Eina_Bool +_efl_ui_list_efl_ui_scrollable_interactive_scroll_freeze_get(const Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd) +{ + return efl_ui_scrollable_scroll_freeze_get(pd->smanager); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollable_interactive_scroll_freeze_set(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Eina_Bool freeze) +{ + efl_ui_scrollable_scroll_freeze_set(pd->smanager, freeze); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollable_interactive_match_content_set(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Eina_Bool match_content_w, + Eina_Bool match_content_h) +{ + pd->match_content_w = !!match_content_w; + pd->match_content_h = !!match_content_h; + + efl_ui_scrollable_match_content_set(pd->smanager, match_content_w, match_content_h); + + elm_layout_sizing_eval(obj); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollbar_bar_mode_set(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Efl_Ui_Scrollbar_Mode hmode, + Efl_Ui_Scrollbar_Mode vmode) +{ + efl_ui_scrollbar_bar_mode_set(pd->smanager, hmode, vmode); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollbar_bar_mode_get(const Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Efl_Ui_Scrollbar_Mode *hmode, + Efl_Ui_Scrollbar_Mode *vmode) +{ + efl_ui_scrollbar_bar_mode_get(pd->smanager, hmode, vmode); +} + +EOLIAN static void +_efl_ui_list_efl_ui_scrollable_interactive_scroll(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Eina_Rect rc, + Eina_Bool animation) +{ + efl_ui_scrollable_scroll(pd->smanager, rc, animation); +} + +EOLIAN static void +_efl_ui_list_efl_ui_multi_selectable_select_mode_set(Eo *obj EINA_UNUSED, + Efl_Ui_List_Data *pd, + Efl_Ui_Select_Mode mode) +{ + Efl_Ui_List_Item *selected; + + if ((pd->select_mode == EFL_UI_SELECT_MULTI && + mode != EFL_UI_SELECT_MULTI) || + mode == EFL_UI_SELECT_NONE) + { + Eina_List *clone = eina_list_clone(pd->selected); + EINA_LIST_FREE(clone, selected) + efl_ui_item_selected_set(selected, EINA_FALSE); + } + + pd->select_mode = mode; +} + +EOLIAN static Efl_Ui_Select_Mode +_efl_ui_list_efl_ui_multi_selectable_select_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->select_mode; +} + +/* List APIs */ +EOLIAN static void +_efl_ui_list_item_scroll(Eo *obj, + Efl_Ui_List_Data *pd, + Efl_Ui_List_Item *item, + Eina_Bool animation) +{ + // Need to be implemented here. + if (pd->pan_resized) + { + _item_scroll_internal(obj, item, -1.0, animation); + } + else + { + pd->scroll.item = item; + pd->scroll.align = -1.0; + pd->scroll.anim = animation; + } +} + +EOLIAN static void +_efl_ui_list_item_scroll_align(Eo *obj, + Efl_Ui_List_Data *pd, + Efl_Ui_List_Item *item, + double align, + Eina_Bool animation) +{ + // Need to be implemented here. + if (pd->pan_resized) + { + _item_scroll_internal(obj, item, align, animation); + } + else + { + pd->scroll.item = item; + pd->scroll.align = align; + pd->scroll.anim = animation; + } +} + +EOLIAN static Efl_Ui_List_Item * +_efl_ui_list_last_selected_item_get(const Eo *obj EINA_UNUSED, Efl_Ui_List_Data *pd) +{ + return pd->last_selected; +} + +static Eina_Bool +_list_item_iterator_next(Item_Iterator *it, void **data) +{ + Efl_Ui_List_Item *item; + + if (!eina_iterator_next(it->real_iterator, (void **)&item)) + return EINA_FALSE; + + if (data) *data = item; + return EINA_TRUE; +} + +static Eo * +_list_item_iterator_get_container(Item_Iterator *it) +{ + return it->object; +} + +static void +_list_item_iterator_free(Item_Iterator *it) +{ + eina_iterator_free(it->real_iterator); + eina_list_free(it->list); + free(it); +} + +EOLIAN static Eina_Iterator * +_efl_ui_list_selected_items_get(Eo *obj, Efl_Ui_List_Data *pd) +{ + Item_Iterator *item; + + item = calloc(1, sizeof(*item)); + if (!item) return NULL; + + EINA_MAGIC_SET(&item->iterator, EINA_MAGIC_ITERATOR); + + item->list = eina_list_clone(pd->selected); + item->real_iterator = eina_list_iterator_new(item->list); + item->iterator.version = EINA_ITERATOR_VERSION; + item->iterator.next = FUNC_ITERATOR_NEXT(_list_item_iterator_next); + item->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_list_item_iterator_get_container); + item->iterator.free = FUNC_ITERATOR_FREE(_list_item_iterator_free); + item->object = obj; + + return &item->iterator; +} + +/* Internal EO APIs and hidden overrides */ +#define EFL_UI_LIST_EXTRA_OPS \ + ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_list) + +#include "efl_ui_list.eo.c" diff --git a/src/lib/elementary/efl_ui_list.eo b/src/lib/elementary/efl_ui_list.eo new file mode 100644 index 0000000000..b97e5b5b99 --- /dev/null +++ b/src/lib/elementary/efl_ui_list.eo @@ -0,0 +1,93 @@ +import efl_ui_list_item; + +class Efl.Ui.List (Efl.Ui.Layout.Object, + Efl.Ui.Scrollable_Interactive, + Efl.Ui.Scrollbar, + Efl.Pack_Linear, Efl.Pack_Layout, + Efl.Ui.Clickable, + Efl.Ui.Selectable, + Efl.Ui.Multi_Selectable) +{ + [[Simple list widget with Pack interface.]] + methods { + item_scroll { + [[scroll move the item to show in the viewport.]] + params { + @in item: Efl.Ui.List_Item; [[Target item.]] + @in animation: bool; [[Boolean value for animation of scroll move.]] + } + } + item_scroll_align { + [[scroll move the item to show at the align position of the viewport.]] + params { + @in item: Efl.Ui.List_Item; [[Target item.]] + @in align: double; [[align value in Viewport.]] + @in animation: bool; [[Boolean value for animation of scroll move.]] + } + } + @property last_selected_item { + [[Property data of last selected item.]] + get {} + values { + return: Efl.Ui.List_Item; [[last selected item of list.]] + } + } + selected_items_get { + [[Get the selected items iterator. The iterator sequence will be decided by selection.]] + return: iterator @owned @warn_unused; [[Iterator covered by selected items list. + user have to free the iterator after used.]] + } + } + implements { + //Efl.Object + Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.destructor; + + //Efl.Canvas + Efl.Canvas.Group.group_calculate; + + //Efl.Container + Efl.Container.content_iterate; + Efl.Container.content_count; + + //Efl.Ui.Direction.direction { get; set; } //TODO + + //Efl.Ui.Widget + Efl.Ui.Widget.theme_apply; + + //Efl.Ui.Focus + //Efl.Ui.Focus.Object.on_focus_update; + + //Efl.Pack + Efl.Pack.pack_clear; + Efl.Pack.unpack_all; + Efl.Pack.unpack; + Efl.Pack.pack; + Efl.Pack_Linear.pack_begin; + Efl.Pack_Linear.pack_end; + Efl.Pack_Linear.pack_before; + Efl.Pack_Linear.pack_after; + Efl.Pack_Linear.pack_at; + Efl.Pack_Linear.pack_content_get; + Efl.Pack_Linear.pack_unpack_at; + Efl.Pack_Linear.pack_index_get; + Efl.Pack_Layout.layout_update; + Efl.Pack_Layout.layout_request; + Efl.Pack.pack_padding { get; set; } + //Efl.Pack.pack_align { get; set; } + + //Efl.Ui.Scrollable + Efl.Ui.Scrollable_Interactive.scroll; + Efl.Ui.Scrollable_Interactive.content_size{ get; } + Efl.Ui.Scrollable_Interactive.viewport_geometry{ get; } + Efl.Ui.Scrollable_Interactive.bounce_enabled { set; get; } + Efl.Ui.Scrollable_Interactive.scroll_freeze { get; set; } + Efl.Ui.Scrollable_Interactive.scroll_hold { get; set; } + Efl.Ui.Scrollable_Interactive.match_content { set; } + Efl.Ui.Scrollbar.bar_mode { get; set; } + + //Efl.Ui.Multi_Selectable + Efl.Ui.Multi_Selectable.select_mode {get; set;} + } +} diff --git a/src/lib/elementary/efl_ui_list_default_item.c b/src/lib/elementary/efl_ui_list_default_item.c new file mode 100644 index 0000000000..25e9fdabe7 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_default_item.c @@ -0,0 +1,111 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_UI_LIST_DEFAULT_ITEM_PROTECTED + +#include + +#include "elm_priv.h" +#include "efl_ui_list_default_item_part_icon.eo.h" +#include "efl_ui_list_default_item_part_end.eo.h" +#include "elm_part_helper.h" + +#define MY_CLASS EFL_UI_LIST_DEFAULT_ITEM_CLASS +#define MY_CLASS_PFX efl_ui_list_default_item + +#define MY_CLASS_NAME "Efl.Ui.List_Default_Item" + +EOLIAN static Efl_Object * +_efl_ui_list_default_item_efl_object_finalize(Eo *obj, void *pd EINA_UNUSED) +{ + Eo *eo; + eo = efl_finalize(efl_super(obj, MY_CLASS)); + ELM_WIDGET_DATA_GET_OR_RETURN(eo, wd, eo); + Efl_Ui_Theme_Apply theme_apply = efl_ui_layout_object_theme_set(obj, "list_item", NULL, NULL); + + if (theme_apply == EFL_UI_THEME_APPLY_FAILED) + CRI("Default Item(%p) failed to set theme [efl/list_item]!", eo); + return eo; +} + +EOLIAN static void +_efl_ui_list_default_item_efl_object_destructor(Eo *obj, void *pd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +/* Efl.Part */ + +ELM_PART_TEXT_DEFAULT_GET(efl_ui_list_default_item, "efl.text") +ELM_PART_TEXT_DEFAULT_IMPLEMENT(efl_ui_list_default_item, void) +ELM_PART_MARKUP_DEFAULT_IMPLEMENT(efl_ui_list_default_item, void) +ELM_PART_CONTENT_DEFAULT_GET(efl_ui_list_default_item, "efl.icon") +ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_list_default_item, void +) + +Eina_Bool +_efl_ui_list_default_item_part_icon_efl_content_content_set(Eo *obj, void *pd EINA_UNUSED, Efl_Gfx_Entity *content) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_set(efl_part(efl_super(wd->obj, MY_CLASS), wd->part), content); +} + +Efl_Gfx_Entity * +_efl_ui_list_default_item_part_icon_efl_content_content_get(const Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_get(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} + +Efl_Gfx_Entity * +_efl_ui_list_default_item_part_icon_efl_content_content_unset(Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_unset(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} +#include "efl_ui_list_default_item_part_icon.eo.c" + +Eina_Bool +_efl_ui_list_default_item_part_end_efl_content_content_set(Eo *obj, void *pd EINA_UNUSED, Efl_Gfx_Entity *content) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_set(efl_part(efl_super(wd->obj, MY_CLASS), wd->part), content); +} + +Efl_Gfx_Entity * +_efl_ui_list_default_item_part_end_efl_content_content_get(const Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_get(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} + +Efl_Gfx_Entity * +_efl_ui_list_default_item_part_end_efl_content_content_unset(Eo *obj, void *pd EINA_UNUSED) +{ + Elm_Part_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + return efl_content_unset(efl_part(efl_super(wd->obj, MY_CLASS), wd->part)); +} +#include "efl_ui_list_default_item_part_end.eo.c" + +EOLIAN static Efl_Object * +_efl_ui_list_default_item_efl_part_part(const Eo *obj, void *wd EINA_UNUSED, const char *part) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); + if (eina_streq(part, "text")) + return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_TEXT_CLASS, obj, "efl.text"); + else if (eina_streq(part, "icon")) + return ELM_PART_IMPLEMENT(EFL_UI_LIST_DEFAULT_ITEM_PART_ICON_CLASS, obj, "efl.icon"); + else if (eina_streq(part, "end")) + return ELM_PART_IMPLEMENT(EFL_UI_LIST_DEFAULT_ITEM_PART_END_CLASS, obj, "efl.end"); + + return efl_part(efl_super(obj, MY_CLASS), part); +} +/* Efl.Part end */ + +/* Internal EO APIs and hidden overrides */ +#define EFL_UI_LIST_DEFAULT_ITEM_EXTRA_OPS \ + ELM_PART_TEXT_DEFAULT_OPS(efl_ui_list_default_item), \ + ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_list_default_item) + +#include "efl_ui_list_default_item.eo.c" diff --git a/src/lib/elementary/efl_ui_list_default_item.eo b/src/lib/elementary/efl_ui_list_default_item.eo new file mode 100644 index 0000000000..0fcb0b6f0b --- /dev/null +++ b/src/lib/elementary/efl_ui_list_default_item.eo @@ -0,0 +1,24 @@ + +class Efl.Ui.List_Default_Item (Efl.Ui.List_Item, + Efl.Text, + Efl.Text_Markup, + Efl.Ui.Translatable, + Efl.Content) +{ + [[List Default Item class. + This class need to be sub object of list widget. + text and contents can be appliable by efl_text, + efl_content or efl_part APIs.]] + data: null; + implements { + //Efl.Object + Efl.Object.finalize; + Efl.Object.destructor; + Efl.Text.text { get; set; } + Efl.Text_Markup.markup { get; set; } + Efl.Ui.Translatable.translatable_text { get; set; } + Efl.Content.content { get; set; } + Efl.Content.content_unset; + Efl.Part.part; + } +} diff --git a/src/lib/elementary/efl_ui_list_default_item_part_end.eo b/src/lib/elementary/efl_ui_list_default_item_part_end.eo new file mode 100644 index 0000000000..7388c9f49b --- /dev/null +++ b/src/lib/elementary/efl_ui_list_default_item_part_end.eo @@ -0,0 +1,9 @@ +class Efl.Ui.List_Default_Item_Part_End (Efl.Ui.Layout.Part, Efl.Content) +{ + [[List Default Item internal content of end part class]] + data: null; + implements { + Efl.Content.content { get; set; } + Efl.Content.content_unset; + } +} \ No newline at end of file diff --git a/src/lib/elementary/efl_ui_list_default_item_part_icon.eo b/src/lib/elementary/efl_ui_list_default_item_part_icon.eo new file mode 100644 index 0000000000..faed96db51 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_default_item_part_icon.eo @@ -0,0 +1,9 @@ +class Efl.Ui.List_Default_Item_Part_Icon (Efl.Ui.Layout.Part, Efl.Content) +{ + [[List Default Item internal content of icon part class]] + data: null; + implements { + Efl.Content.content { get; set; } + Efl.Content.content_unset; + } +} \ No newline at end of file diff --git a/src/lib/elementary/efl_ui_list_empty_item.c b/src/lib/elementary/efl_ui_list_empty_item.c new file mode 100644 index 0000000000..b78707ad57 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_empty_item.c @@ -0,0 +1,56 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_UI_LIST_EMPTY_ITEM_PROTECTED + +#include + +#include "elm_priv.h" +#include "elm_part_helper.h" + +#define MY_CLASS EFL_UI_LIST_EMPTY_ITEM_CLASS +#define MY_CLASS_PFX efl_ui_list_empty_item + +#define MY_CLASS_NAME "Efl.Ui.List_Empty_Item" + +EOLIAN static Efl_Object * +_efl_ui_list_empty_item_efl_object_finalize(Eo *obj, void *pd EINA_UNUSED) +{ + Eo *eo; + eo = efl_finalize(efl_super(obj, MY_CLASS)); + ELM_WIDGET_DATA_GET_OR_RETURN(eo, wd, eo); + Efl_Ui_Theme_Apply theme_apply = efl_ui_layout_object_theme_set(obj, "list_item", NULL, "empty"); + + if (theme_apply == EFL_UI_THEME_APPLY_FAILED) + CRI("Empty Item(%p) failed to set theme [efl/list_item:empty]!", eo); + return eo; +} + +EOLIAN static void +_efl_ui_list_empty_item_efl_object_destructor(Eo *obj, void *pd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +/* Efl.Part */ +ELM_PART_CONTENT_DEFAULT_GET(efl_ui_list_empty_item, "efl.content") +ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_list_empty_item, void) +/* Efl.Part end */ + +EOLIAN static Efl_Object * +_efl_ui_list_empty_item_efl_part_part(const Eo *obj, void *wd EINA_UNUSED, const char *part) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); + if (eina_streq(part, "content")) + return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_CONTENT_CLASS, obj, "efl.content"); + + return efl_part(efl_super(obj, MY_CLASS), part); +} + +/* Internal EO APIs and hidden overrides */ + +#define EFL_UI_LIST_EMPTY_ITEM_EXTRA_OPS \ + ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_list_empty_item) + +#include "efl_ui_list_empty_item.eo.c" diff --git a/src/lib/elementary/efl_ui_list_empty_item.eo b/src/lib/elementary/efl_ui_list_empty_item.eo new file mode 100644 index 0000000000..a139ef3bf1 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_empty_item.eo @@ -0,0 +1,16 @@ + +class Efl.Ui.List_Empty_Item (Efl.Ui.List_Item, Efl.Content) +{ + [[List Empty Item class. This item have only one swallow space, + thus user can decorate item by filling the swallow with + any kind of container.]] + data: null; + implements { + //Efl.Object + Efl.Object.finalize; + Efl.Object.destructor; + Efl.Content.content { get; set; } + Efl.Content.content_unset; + Efl.Part.part; + } +} diff --git a/src/lib/elementary/efl_ui_list_item.c b/src/lib/elementary/efl_ui_list_item.c new file mode 100644 index 0000000000..1fe67e9c0c --- /dev/null +++ b/src/lib/elementary/efl_ui_list_item.c @@ -0,0 +1,83 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_ACCESS_PROTECTED +#define EFL_UI_WIDGET_PART_BG_PROTECTED + +#include + +#include "elm_priv.h" +#include "efl_ui_list_item_private.h" + +#define MY_CLASS EFL_UI_LIST_ITEM_CLASS +#define MY_CLASS_PFX efl_ui_list_item + +#define MY_CLASS_NAME "Efl.Ui.List_Item" + +static void +_sizing_eval(Evas_Object *obj, Efl_Ui_List_Item_Data *pd) +{ + Evas_Coord minh = -1, minw = -1; + Evas_Coord rest_w = 0, rest_h = 0; + ELM_WIDGET_DATA_GET_OR_RETURN(pd->obj, wd); + + edje_object_size_min_restricted_calc(wd->resize_obj, &minw, &minh, + rest_w, rest_h); + evas_object_size_hint_min_set(obj, minw, minh); + + pd->needs_size_calc = EINA_FALSE; +} + +static void +_efl_ui_list_item_elm_layout_sizing_eval(Eo *obj, Efl_Ui_List_Item_Data *pd) +{ + if (pd->needs_size_calc) return; + pd->needs_size_calc = EINA_TRUE; + + efl_canvas_group_change(obj); +} + +EOLIAN static void +_efl_ui_list_item_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_List_Item_Data *pd) +{ + if (pd->needs_size_calc) + { + _sizing_eval(obj, pd); + pd->needs_size_calc = EINA_FALSE; + } +} + +EOLIAN static Eo * +_efl_ui_list_item_efl_object_constructor(Eo *obj, Efl_Ui_List_Item_Data *pd) +{ + pd->obj = obj; + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + return obj; +} + +EOLIAN static Efl_Object * +_efl_ui_list_item_efl_object_finalize(Eo *obj, Efl_Ui_List_Item_Data *pd EINA_UNUSED) +{ + Eo *eo; + eo = efl_finalize(efl_super(obj, MY_CLASS)); + ELM_WIDGET_DATA_GET_OR_RETURN(eo, wd, eo); + + return eo; +} + +EOLIAN static void +_efl_ui_list_item_efl_object_destructor(Eo *obj, Efl_Ui_List_Item_Data *pd EINA_UNUSED) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + efl_destructor(efl_super(obj, MY_CLASS)); +} + +/* Internal EO APIs and hidden overrides */ + +#define EFL_UI_LIST_ITEM_EXTRA_OPS \ + ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_list_item) + +#include "efl_ui_list_item.eo.c" diff --git a/src/lib/elementary/efl_ui_list_item.eo b/src/lib/elementary/efl_ui_list_item.eo new file mode 100644 index 0000000000..82943ad3c6 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_item.eo @@ -0,0 +1,12 @@ + +abstract Efl.Ui.List_Item (Efl.Ui.Item) +{ + implements { + //Efl.Object + Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.destructor; + //Efl.Canvas + Efl.Canvas.Group.group_calculate; + } +} diff --git a/src/lib/elementary/efl_ui_list_item_private.h b/src/lib/elementary/efl_ui_list_item_private.h new file mode 100644 index 0000000000..e68b3fa14a --- /dev/null +++ b/src/lib/elementary/efl_ui_list_item_private.h @@ -0,0 +1,31 @@ +#ifndef EFL_UI_LIST_ITEM_PRIVATE_H +#define EFL_UI_LIST_ITEM_PRIVATE_H + +#include "Elementary.h" + +typedef struct _Efl_Ui_List_Item_Data +{ + // Eo Objects + Eo *obj; /* Self-Object */ + Eo *parent; /* Parent Widget */ + Eina_Bool needs_size_calc : 1; /* Flag for Size calculation */ +} Efl_Ui_List_Item_Data; + + +#define EFL_UI_LIST_ITEM_DATA_GET(o, pd) \ + Efl_Ui_List_Item_Data * pd = efl_data_scope_safe_get(o, EFL_UI_LIST_ITEM_CLASS) + +#define EFL_UI_LIST_ITEM_DATA_GET_OR_RETURN(o, ptr, ...) \ + EFL_UI_LIST_ITEM_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + ERR("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return __VA_ARGS__; \ + } + +#define EFL_UI_LIST_ITEM_CHECK_OR_RETURN(obj, ...) \ + if (EINA_UNLIKELY(!efl_isa((obj), EFL_UI_LIST_ITEM_CLASS))) \ + return __VA_ARGS__; + +#endif diff --git a/src/lib/elementary/efl_ui_list_private.h b/src/lib/elementary/efl_ui_list_private.h new file mode 100644 index 0000000000..409956dce1 --- /dev/null +++ b/src/lib/elementary/efl_ui_list_private.h @@ -0,0 +1,63 @@ +#ifndef EFL_UI_LIST_PRIVATE_H +#define EFL_UI_LIST_PRIVATE_H + +#include "Elementary.h" + +typedef struct _Efl_Ui_List_Data +{ + // Eo Objects + Eo *box; /* Internal box for Efl.Pack support */ + Eo *pan; /* Internal pan for scroll */ + Eo *smanager; /* Scroll Manager for support scroll with pan */ + + struct { + Efl_Ui_List_Item *item; /* Scroll target item */ + double align; /* Item scroll aligned position. + -1 is for default case of scroll in */ + Eina_Bool anim : 1; /* boolean data for animation on scroll */ + } scroll; /* Item scroll values for deferred operation */ + + Eina_List *items; /* All item list for internal maintaining */ + Eina_List *selected; /* Selected items list */ + Efl_Ui_List_Item *last_selected; /* latest selected item */ + + Efl_Ui_Select_Mode select_mode; /* Select mode for items + with single or multiple seleciton */ + + // Boolean Data + Eina_Bool freeze_want : 1; /* Flag for Scroll freezing */ + Eina_Bool match_content_w: 1; /* Flag for size matching on content width. + it will disable horizontal scroll */ + Eina_Bool match_content_h: 1; /* Flag for size matching on content height. + it will disable vertical scroll */ + Eina_Bool pan_resized : 1; /* Flag for pan resized. + This value is used for checking scroll is + calculated after initialized */ +} Efl_Ui_List_Data; + +typedef struct _Item_Iterator +{ + Eina_Iterator iterator; + Eina_List *list; + Eina_Iterator *real_iterator; + Eo *object; +} Item_Iterator; + + +#define EFL_UI_LIST_DATA_GET(o, pd) \ + Efl_Ui_List_Data * pd = efl_data_scope_safe_get(o, EFL_UI_LIST_CLASS) + +#define EFL_UI_LIST_DATA_GET_OR_RETURN(o, ptr, ...) \ + EFL_UI_LIST_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + ERR("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return __VA_ARGS__; \ + } + +#define EFL_UI_LIST_CHECK(obj) \ + if (EINA_UNLIKELY(!efl_isa((obj), EFL_UI_LIST_CLASS))) \ + return + +#endif