cedric pushed a commit to branch master. http://git.enlightenment.org/core/elementary.git/commit/?id=b4f8b8c0c66095730d4436db3987c3fad34aec95
commit b4f8b8c0c66095730d4436db3987c3fad34aec95 Author: divyesh purohit <div.puro...@samsung.com> Date: Mon Jan 4 15:22:46 2016 -0800 combobox: add new widget. Summary: Combobox is a combinational widget of a drop-down list and single line entry. Based on the text entered in the entry, the list items are filtered accordingly. Signed-Off By: Cedric Bail <cedric.b...@free.fr> Signed-Off By: Divyesh Purohit <div.puro...@samsung.com> Test Plan: test_combobox.c is added to elementary test Reviewers: raster, shilpasingh, cedric, jpeg, stefan_schmidt Reviewed By: raster, shilpasingh, cedric Subscribers: SanghyeonLee, shashank0990, singh.amitesh, tasn, raster, seoz, poornima.srinivasan, rajeshps, govi Differential Revision: https://phab.enlightenment.org/D2537 Signed-off-by: Cedric BAIL <ced...@osg.samsung.com> --- AUTHORS | 1 + config/default/base.src.in | 49 ++++- config/mobile/base.src.in | 49 ++++- config/standard/base.src.in | 49 ++++- data/themes/edc/elm/button.edc | 299 +++++++++++++++++++++++++++ data/themes/edc/elm/hover.edc | 4 + src/bin/Makefile.am | 1 + src/bin/test.c | 2 + src/bin/test_combobox.c | 165 +++++++++++++++ src/lib/Elementary.h.in | 1 + src/lib/Makefile.am | 5 + src/lib/elc_combobox.c | 458 +++++++++++++++++++++++++++++++++++++++++ src/lib/elc_combobox.h | 64 ++++++ src/lib/elc_combobox_legacy.h | 11 + src/lib/elm_authors.h | 1 + src/lib/elm_combobox.eo | 54 +++++ src/lib/elm_config.c | 27 +++ src/lib/elm_priv.h | 2 +- src/lib/elm_widget_combobox.h | 80 +++++++ 19 files changed, 1318 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0e2457b..5ead385 100644 --- a/AUTHORS +++ b/AUTHORS @@ -166,3 +166,4 @@ Subodh Kumar <s7158.ku...@samsung.com> Kumar Navneet <k.navn...@samsung.com> Godly T Alias <godly.tal...@samsung.com> <godlytal...@yahoo.co.in> Shashank Pandey <shashan...@samsung.com> <shashank0...@gmail.com> +Divyesh Purohit <div.puro...@samsung.com> <purohit....@gmail.com> diff --git a/config/default/base.src.in b/config/default/base.src.in index 7bf7713..e86f7d8 100644 --- a/config/default/base.src.in +++ b/config/default/base.src.in @@ -1,5 +1,5 @@ group "Elm_Config" struct { - value "config_version" int: 131078; + value "config_version" int: 131079; value "engine" string: ""; value "vsync" uchar: 0; value "thumbscroll_enable" uchar: 1; @@ -433,6 +433,53 @@ group "Elm_Config" struct { } } group "Elm_Config_Bindings_Widget" struct { + value "name" string: "Elm_Combobox"; + group "key_bindings" list { + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Return"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Enter"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "space"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down"; + } + } + } + group "Elm_Config_Bindings_Widget" struct { value "name" string: "Elm_Multibuttonentry"; group "key_bindings" list { group "Elm_Config_Binding_Key" struct { diff --git a/config/mobile/base.src.in b/config/mobile/base.src.in index 44bfd67..a588aa1 100644 --- a/config/mobile/base.src.in +++ b/config/mobile/base.src.in @@ -1,5 +1,5 @@ group "Elm_Config" struct { - value "config_version" int: 131078; + value "config_version" int: 131079; value "engine" string: ""; value "vsync" uchar: 0; value "thumbscroll_enable" uchar: 1; @@ -437,6 +437,53 @@ group "Elm_Config" struct { } } group "Elm_Config_Bindings_Widget" struct { + value "name" string: "Elm_Combobox"; + group "key_bindings" list { + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Return"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Enter"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "space"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down"; + } + } + } + group "Elm_Config_Bindings_Widget" struct { value "name" string: "Elm_Multibuttonentry"; group "key_bindings" list { group "Elm_Config_Binding_Key" struct { diff --git a/config/standard/base.src.in b/config/standard/base.src.in index fd60d6a..745e577 100644 --- a/config/standard/base.src.in +++ b/config/standard/base.src.in @@ -1,5 +1,5 @@ group "Elm_Config" struct { - value "config_version" int: 131078; + value "config_version" int: 131079; value "engine" string: ""; value "vsync" uchar: 0; value "thumbscroll_enable" uchar: 0; @@ -434,6 +434,53 @@ group "Elm_Config" struct { } } group "Elm_Config_Bindings_Widget" struct { + value "name" string: "Elm_Combobox"; + group "key_bindings" list { + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Return"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Enter"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "space"; + value "action" string: "activate"; + value "params" string: "return"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Up"; + value "action" string: "move"; + value "params" string: "up"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Up"; + value "action" string: "move"; + value "params" string: "up"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "Down"; + value "action" string: "move"; + value "params" string: "down"; + } + group "Elm_Config_Binding_Key" struct { + value "context" int: 0; + value "key" string: "KP_Down"; + value "action" string: "move"; + value "params" string: "down"; + } + } + } + group "Elm_Config_Bindings_Widget" struct { value "name" string: "Elm_Multibuttonentry"; group "key_bindings" list { group "Elm_Config_Binding_Key" struct { diff --git a/data/themes/edc/elm/button.edc b/data/themes/edc/elm/button.edc index 2134d41..9dd9f61 100644 --- a/data/themes/edc/elm/button.edc +++ b/data/themes/edc/elm/button.edc @@ -1712,3 +1712,302 @@ group { name: "elm/button/base/hoversel_horizontal_entry/default"; } } /******************* SPINNER BUTTONS STYLES END **********************/ +group { name: "elm/button/base/combobox_vertical/default"; + alias: "elm/button/base/combobox_vertical/entry"; + alias: "elm/button/base/combobox_horizontal/default"; + alias: "elm/button/base/combobox_horizontal/entry"; + + images.image: "button_normal.png" COMP; + images.image: "button_clicked.png" COMP; + images.image: "vertical_separated_bar_glow.png" COMP; + parts { + image { "base"; nomouse; + desc { "default"; + image.normal: "button_normal.png"; + image.border: 4 4 3 5; + image.middle: SOLID; + rel1.offset: -1 0; + rel2.offset: 0 1; + fill.smooth: 0; + } + desc { "clicked"; + inherit: "default"; + image.normal: "button_clicked.png"; + image.border: 5 5 4 6; + } + } + rect { "icon_clip"; + desc { "default"; + } + desc { "disabled"; + inherit: "default"; + color: 255 255 255 64; + } + } + rect { "event"; + desc { "default"; + color: 0 0 0 0; + } + desc { "disabled"; + inherit: "default"; + visible: 0; + } + } + swallow { "elm.swallow.content"; + clip_to: "icon_clip"; + desc { "default"; + fixed: 0 0; + align: 0.5 0.5; + rel1.offset: 6 5; + rel1.to: "base"; + rel2.relative: 0.0 1.0; + rel2.offset: -3 -8; + rel2.to: "select_line"; + visible: 1; + } + } + image { "select_line"; nomouse; + desc { "default"; + fixed: 1 1; + align: 1.0 0.5; + min: 15 10; + rel1.to: "base"; + rel1.relative: 1.0 0.0; + rel1.offset: 1 -3; + rel2.to: "base"; + rel2.offset: 1 0; + image.normal: "vertical_separated_bar_glow.png"; + image.border: 7 7 7 7; + fill.smooth : 0; + } + desc { "clicked"; + inherit: "default"; + rel1.offset: 0 -2; + rel2.offset: 0 -1; + } + } + } + programs { + program { + signal: "mouse,down,1"; source: "event"; + action: SIGNAL_EMIT "elm,action,press" "elm"; + after: "button_click_anim"; + } + program { name: "button_click_anim"; + action: STATE_SET "clicked" 0.0; + target: "base"; + target: "select_line"; + } + program { name: "button_unclick"; + signal: "mouse,up,1"; source: "event"; + action: SIGNAL_EMIT "elm,action,unpress" "elm"; + after: "button_unclick_anim"; + } + program { name: "button_unclick_anim"; + action: STATE_SET "default" 0.0; + target: "base"; + target: "select_line"; + } + program { name: "buttonactivate"; + signal: "elm,anim,activate"; source: "elm"; + action: STATE_SET "clicked" 0.0; + target: "base"; + target: "select_line"; + after: "button_unpressed_anim"; + } + program { name: "button_unpressed_anim"; + action: STATE_SET "default" 0.0; + in: 0.5 0.0; + target: "base"; + target: "select_line"; + } + program { + signal: "mouse,clicked,1"; source: "event"; + action: SIGNAL_EMIT "elm,action,click" "elm"; + } + program { name: "button_state_disabled"; + signal: "elm,state,disabled"; source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "icon_clip"; + target: "event"; + } + program { name: "button_state_enabled"; + signal: "elm,state,enabled"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "icon_clip"; + target: "event"; + } + } +} + +group { name: "elm/button/base/combobox_vertical_entry/default"; + alias: "elm/button/base/combobox_vertical_entry/entry"; + images.image: "vgrad_med_dark.png" COMP; + images.image: "bevel_horiz_out.png" COMP; + images.image: "shadow_rounded_horiz.png" COMP; + images.image: "shine.png" COMP; + + parts { + image { "shadow"; nomouse; + desc { "default"; + fixed: 1 1; + image.normal: "shadow_rounded_horiz.png"; + image.border: 0 0 9 9; + rel1.to: "base"; + rel1.offset: 0 -4; + rel2.to: "base"; + rel2.offset: -1 5; + fill.smooth: 0; + visible: 0; + } + desc { "clicked"; + inherit: "default"; + visible: 1; + } + } + image { "base"; nomouse; + desc { "default"; + fixed: 1 1; + rel1.offset: -6 0; + image.normal: "vgrad_med_dark.png"; + fill.smooth: 0; + TILED_HORIZ(120) + visible: 0; + } + desc { "clicked"; + inherit: "default"; + visible: 1; + } + } + rect { "icon_clip"; + desc { "default"; + } + desc { "disabled"; + inherit: "default"; + color: 255 255 255 64; + } + } + image { "bevel"; nomouse; + desc { "default"; + fixed: 1 1; + image.normal: "bevel_horiz_out.png"; + image.border: 0 0 2 2; + image.middle: 0; + fill.smooth: 0; + visible: 0; + } + desc { "clicked"; + inherit: "default"; + visible: 1; + } + } + image { "shine"; nomouse; + desc { "default"; + fixed: 1 1; + rel1.to: "base"; + rel1.offset: 0 -2; + rel2.to: "base"; + rel2.relative: 1.0 0.0; + rel2.offset: -1 2; + image.normal: "shine.png"; + visible: 0; + FIXED_SIZE(69, 5) + } + desc { "clicked"; + inherit: "default"; + visible: 1; + } + } + rect { name: "event"; + desc { "default"; + color: 0 0 0 0; + } + desc { "disabled"; + inherit: "default"; + visible: 0; + } + } + swallow { "elm.swallow.content"; nomouse; + clip_to: "icon_clip"; + desc { "default"; + fixed: 1 0; + align: 0.0 0.5; + rel1.offset: 6 5; + rel1.to: "base"; + rel2.relative: 0.0 1.0; + rel2.offset: 6 -8; + rel2.to: "base"; + visible: 0; + } + desc { "visible"; + inherit: "default"; + fixed: 1 0; + aspect: 1.0 1.0; + visible: 1; + } + desc { "icononly"; + inherit: "default"; + fixed: 0 0; + align: 0.5 0.5; + rel2.relative: 1.0 1.0; + rel2.offset: -7 -8; + visible: 1; + } + } + } + programs { + program { + signal: "mouse,down,1"; source: "event"; + action: SIGNAL_EMIT "elm,action,press" "elm"; + after: "button_click_anim"; + } + program { name: "button_click_anim"; + action: STATE_SET "clicked" 0.0; + target: "shadow"; + target: "base"; + target: "shine"; + } + program { name: "button_unclick"; + signal: "mouse,up,1"; source: "event"; + action: SIGNAL_EMIT "elm,action,unpress" "elm"; + after: "button_unclick_anim"; + } + program { name: "button_unclick_anim"; + action: STATE_SET "default" 0.0; + target: "shadow"; + target: "base"; + target: "shine"; + } + program { name: "buttonactivate"; + signal: "elm,anim,activate"; source: "elm"; + action: STATE_SET "clicked" 0.0; + target: "shadow"; + target: "base"; + target: "shine"; + after: "button_unpressed_anim"; + } + program { name: "button_unpressed_anim"; + action: STATE_SET "default" 0.0; + in: 0.5 0.0; + target: "shadow"; + target: "base"; + target: "shine"; + } + program { + signal: "mouse,clicked,1"; source: "event"; + action: SIGNAL_EMIT "elm,action,click" "elm"; + } + program { name: "button_state_disabled"; + signal: "elm,state,disabled"; source: "elm"; + action: STATE_SET "disabled" 0.0; + target: "event"; + target: "icon_clip"; + } + program { name: "button_state_enabled"; + signal: "elm,state,enabled"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "event"; + target: "icon_clip"; + } + } +} diff --git a/data/themes/edc/elm/hover.edc b/data/themes/edc/elm/hover.edc index 8a7ed49..75ea813 100644 --- a/data/themes/edc/elm/hover.edc +++ b/data/themes/edc/elm/hover.edc @@ -439,6 +439,8 @@ group { name: "elm/hover/base/popout"; group { name: "elm/hover/base/hoversel_vertical/default"; alias: "elm/hover/base/hoversel_vertical/entry"; + alias: "elm/hover/base/combobox_vertical/entry"; + alias: "elm/hover/base/combobox_vertical/default"; images.image: "button_normal.png" COMP; images.image: "vertical_separated_bar_glow.png" COMP; data.item: "dismiss" "on"; @@ -773,6 +775,8 @@ group { name: "elm/hover/base/hoversel_vertical/default"; group { name: "elm/hover/base/hoversel_horizontal/default"; alias: "elm/hover/base/hoversel_horizontal/entry"; + alias: "elm/hover/base/combobox_horizontal/default"; + alias: "elm/hover/base/combobox_horizontal/entry"; images.image: "button_normal.png" COMP; data.item: "dismiss" "on"; // max_size limits the maximum size of expanded hoversel diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index b93374a..46db673 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -43,6 +43,7 @@ test_clock.c \ test_cnp.c \ test_colorselector.c \ test_colorclass.c \ +test_combobox.c \ test_config.c \ test_conform.c \ test_conform_indicator.c \ diff --git a/src/bin/test.c b/src/bin/test.c index 53f419d..a3ae31d 100644 --- a/src/bin/test.c +++ b/src/bin/test.c @@ -45,6 +45,7 @@ void test_clock(void *data, Evas_Object *obj, void *event_info); void test_clock_edit(void *data, Evas_Object *obj, void *event_info); void test_clock_edit2(void *data, Evas_Object *obj, void *event_info); void test_clock_pause(void *data, Evas_Object *obj, void *event_info); +void test_combobox(void *data, Evas_Object *obj, void *event_info); void test_check(void *data, Evas_Object *obj, void *event_info); void test_check_toggle(void *data, Evas_Object *obj, void *event_info); void test_radio(void *data, Evas_Object *obj, void *event_info); @@ -753,6 +754,7 @@ add_tests: ADD_TEST(NULL, "Selectors", "FlipSelector", test_flipselector); ADD_TEST(NULL, "Selectors", "DaySelector", test_dayselector); ADD_TEST(NULL, "Selectors", "Main menu", test_main_menu); + ADD_TEST(NULL, "Selectors", "Combobox", test_combobox); //------------------------------// ADD_TEST(NULL, "Cursors", "Cursor", test_cursor); diff --git a/src/bin/test_combobox.c b/src/bin/test_combobox.c new file mode 100644 index 0000000..b5f1172 --- /dev/null +++ b/src/bin/test_combobox.c @@ -0,0 +1,165 @@ +#include "test.h" +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif +#include <Elementary.h> + +static void +_combobox_clicked_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + printf("Hover button is clicked and 'clicked' callback is called.\n"); +} + +static void +_combobox_selected_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + const char *txt = elm_object_item_text_get(event_info); + printf("'selected' callback is called. (selected item : %s)\n", txt); +} + +static void +_combobox_dismissed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + printf("'dismissed' callback is called.\n"); +} + +static void +_combobox_expanded_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + printf("'expanded' callback is called.\n"); +} + +static void +_combobox_item_pressed_cb(void *data EINA_UNUSED, Evas_Object *obj, + void *event_info) +{ + const char *txt = elm_object_item_text_get(event_info); + printf("'item,pressed' callback is called. (selected item : %s)\n", txt); + elm_object_text_set(obj, txt); + elm_combobox_hover_end(obj); +} + +static char * +gl_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) +{ + char buf[256]; + snprintf(buf, sizeof(buf), "Item # %i", (int)(uintptr_t)data); + return strdup(buf); +} + +static Evas_Object *gl_content_get(void *data EINA_UNUSED, Evas_Object *obj, + const char *part) +{ + char buf[PATH_MAX]; + Evas_Object *ic = elm_icon_add(obj); + if (!strcmp(part, "elm.swallow.end")) + snprintf(buf, sizeof(buf), "%s/images/bubble.png", elm_app_data_dir_get()); + else + snprintf(buf, sizeof(buf), "%s/images/logo_small.png", elm_app_data_dir_get()); + elm_image_file_set(ic, buf, NULL); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + return ic; +} + +static Eina_Bool gl_state_get(void *data EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + const char *part EINA_UNUSED) +{ + return EINA_FALSE; +} + +static Eina_Bool +gl_filter_get(void *data, Evas_Object *obj EINA_UNUSED, void *key) +{ + // if the key is empty/NULL, return true for item + if (!strlen((char *)key)) return EINA_TRUE; + char buf[256]; + snprintf(buf, sizeof(buf), "Item # %i", (int)(uintptr_t)data); + if (strcasestr(buf, (char *)key)) + return EINA_TRUE; + // Default case should return false (item fails filter hence will be hidden) + return EINA_FALSE; +} + +static void +_gl_filter_finished_cb(void *data EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + printf("Filter finished\n"); +} + +void +test_combobox(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Evas_Object *win, *bx, *combobox; + Elm_Genlist_Item_Class *itc; + win = elm_win_util_standard_add("combobox", "Combobox"); + elm_win_autodel_set(win, EINA_TRUE); + + bx = elm_box_add(win); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bx); + evas_object_show(bx); + + itc = elm_genlist_item_class_new(); + itc->item_style = "default"; + itc->func.text_get = gl_text_get; + itc->func.content_get = gl_content_get; + itc->func.state_get = gl_state_get; + itc->func.filter_get = gl_filter_get; + itc->func.del = NULL; + + combobox = elm_combobox_add(win); + evas_object_size_hint_weight_set(combobox, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(combobox, EVAS_HINT_FILL, 0); + elm_object_part_text_set(combobox, "guide", "A long list"); + for (int i = 0; i < 1000; i++) + elm_genlist_item_append(combobox, itc, (void *)(uintptr_t)i, + NULL, ELM_GENLIST_ITEM_NONE, NULL, + (void*)(uintptr_t)(i * 10)); + evas_object_smart_callback_add(combobox, "clicked", + _combobox_clicked_cb, NULL); + evas_object_smart_callback_add(combobox, "selected", + _combobox_selected_cb, NULL); + evas_object_smart_callback_add(combobox, "dismissed", + _combobox_dismissed_cb, NULL); + evas_object_smart_callback_add(combobox, "expanded", + _combobox_expanded_cb, NULL); + evas_object_smart_callback_add(combobox, "item,pressed", + _combobox_item_pressed_cb, NULL); + evas_object_smart_callback_add(combobox, "filter,done", + _gl_filter_finished_cb, NULL); + elm_box_pack_end(bx, combobox); + evas_object_show(combobox); + + combobox = elm_combobox_add(win); + evas_object_size_hint_weight_set(combobox, EVAS_HINT_EXPAND, 0); + evas_object_size_hint_align_set(combobox, EVAS_HINT_FILL, 0); + elm_object_text_set(combobox, "Disabled Combobox"); + for (int i = 0; i < 1000; i++) + elm_genlist_item_append(combobox, itc, (void *)(uintptr_t)i, + NULL, ELM_GENLIST_ITEM_NONE, NULL, + (void*)(uintptr_t)(i * 10)); + evas_object_smart_callback_add(combobox, "clicked", + _combobox_clicked_cb, NULL); + evas_object_smart_callback_add(combobox, "selected", + _combobox_selected_cb, NULL); + evas_object_smart_callback_add(combobox, "dismissed", + _combobox_dismissed_cb, NULL); + evas_object_smart_callback_add(combobox, "expanded", + _combobox_expanded_cb, NULL); + evas_object_smart_callback_add(combobox, "filter,done", + _gl_filter_finished_cb, NULL); + elm_object_disabled_set(combobox, EINA_TRUE); + elm_box_pack_end(bx, combobox); + evas_object_show(combobox); + + evas_object_resize(win, 320, 500); + evas_object_show(win); +} diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 1cd7c76..7dceefa 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -174,6 +174,7 @@ EAPI extern Elm_Version *elm_version; /* other includes */ #include <elc_ctxpopup.h> +#include <elc_combobox.h> #include <elm_dayselector.h> #include <elc_fileselector_button.h> #include <elc_fileselector_entry.h> diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 20f6521..40fb597 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -56,6 +56,7 @@ elm_widget_clock.h \ elm_widget_colorselector.h \ elm_widget_conform.h \ elm_widget_container.h \ +elm_widget_combobox.h \ elm_widget_ctxpopup.h \ elm_widget_datetime.h \ elm_widget_dayselector.h \ @@ -114,6 +115,8 @@ includesub_HEADERS = \ elc_ctxpopup.h \ elc_ctxpopup_eo.h \ elc_ctxpopup_legacy.h \ +elc_combobox.h \ +elc_combobox_legacy.h \ elc_fileselector.h \ elc_fileselector_eo.h \ elc_fileselector_legacy.h \ @@ -415,6 +418,7 @@ elm_clock.c \ elm_cnp.c \ elm_colorselector.c \ elm_color_class.c \ +elc_combobox.c \ elm_config.c \ elm_conform.c \ elm_container.c \ @@ -531,6 +535,7 @@ elm_calendar.eo \ elm_check.eo \ elm_clock.eo \ elm_colorselector.eo \ +elm_combobox.eo \ elm_conformant.eo \ elm_container.eo \ elm_ctxpopup.eo \ diff --git a/src/lib/elc_combobox.c b/src/lib/elc_combobox.c new file mode 100644 index 0000000..7e5487f --- /dev/null +++ b/src/lib/elc_combobox.c @@ -0,0 +1,458 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EO_BASE_BETA +#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED +#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED + +#include <Elementary.h> +#include "elm_priv.h" +#include "elm_widget_combobox.h" + +#define MY_CLASS ELM_COMBOBOX_CLASS + +#define MY_CLASS_NAME "Elm_Combobox" +#define MY_CLASS_NAME_LEGACY "elm_combobox" + +static const char SIG_SELECTED[] = "selected"; +static const char SIG_DISMISSED[] = "dismissed"; +static const char SIG_EXPANDED[] = "expanded"; +static const char SIG_ITEM_PRESSED[] = "item,pressed"; +static const char SIG_FILTER_DONE[] = "filter,done"; + +static const Evas_Smart_Cb_Description _smart_callbacks[] = { + {SIG_SELECTED, ""}, + {SIG_DISMISSED, ""}, + {SIG_EXPANDED, ""}, + {SIG_ITEM_PRESSED, ""}, + {SIG_FILTER_DONE, ""}, + {"clicked", ""}, /**< handled by parent button class */ + {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ + {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ + {NULL, NULL} +}; + +static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); +static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params); + +static const Elm_Action key_actions[] = { + {"activate", _key_action_activate}, + {"move", _key_action_move}, + {NULL, NULL} +}; + +EOLIAN static Eina_Bool +_elm_combobox_elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Combobox_Data *sd) +{ + eo_do_super(obj, MY_CLASS, elm_obj_widget_translate()); + eo_do(sd->genlist, elm_obj_widget_translate()); + eo_do(sd->entry, elm_obj_widget_translate()); + + if (sd->hover) + eo_do(sd->hover, elm_obj_widget_translate()); + + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_elm_combobox_elm_widget_theme_apply(Eo *obj, Elm_Combobox_Data *sd) +{ + const char *style; + Eina_Bool int_ret = EINA_FALSE; + Eina_Bool mirrored; + char buf[128]; + + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE); + + style = elm_widget_style_get(obj); + + snprintf(buf, sizeof(buf), "combobox_vertical/%s", style); + + /* combobox's style has no extra bit for orientation but could have... */ + eina_stringshare_replace(&(wd->style), buf); + + eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply()); + if (!int_ret) return EINA_FALSE; + + mirrored = elm_widget_mirrored_get(obj); + + if (sd->hover) + elm_widget_mirrored_set(sd->hover, mirrored); + + elm_widget_mirrored_set(sd->genlist, mirrored); + elm_widget_mirrored_set(sd->entry, mirrored); + + elm_combobox_hover_end(obj); + + return EINA_TRUE; +} + +static void +_on_hover_clicked(void *data, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + elm_combobox_hover_end(data); +} + +static void +count_items_genlist(void *data) +{ + ELM_COMBOBOX_DATA_GET(data, sd); + Eina_Iterator *filter_iter; + int count = 0; + Elm_Object_Item *item; + + filter_iter = elm_genlist_filter_iterator_new(sd->genlist); + if (!filter_iter) return; + EINA_ITERATOR_FOREACH(filter_iter, item) + if (item) count++; + sd->count = count; + eina_iterator_free(filter_iter); +} + +static void +_table_resize(void *data) +{ + ELM_COMBOBOX_DATA_GET(data, sd); + if (sd->count > 0) + { + int hover_parent_w, hover_parent_h, obj_h, obj_w, obj_y, win_y_offset; + int current_height, h; + sd->item = elm_genlist_first_item_get(sd->genlist); + elm_genlist_item_selected_set(sd->item, EINA_TRUE); + //FIXME:- the height of item is zero, sometimes. + evas_object_geometry_get(elm_object_item_track(sd->item), NULL, NULL, + NULL, &h); + if (h) sd->item_height = h; + evas_object_geometry_get(sd->entry, NULL, NULL, &obj_w, NULL); + evas_object_geometry_get(data, NULL, &obj_y, NULL, &obj_h); + evas_object_geometry_get(sd->hover_parent, NULL, NULL, &hover_parent_w, + &hover_parent_h); + current_height = sd->item_height * sd->count; + if (!strcmp(elm_hover_best_content_location_get(sd->hover, + ELM_HOVER_AXIS_VERTICAL), + "bottom")) + win_y_offset = hover_parent_h - obj_y - obj_h; + else win_y_offset = obj_y; + if (current_height < win_y_offset) + evas_object_size_hint_min_set(sd->spacer, obj_w * elm_config_scale_get(), + current_height + (2 * elm_config_scale_get())); + else evas_object_size_hint_min_set(sd->spacer, obj_w * elm_config_scale_get(), + win_y_offset * elm_config_scale_get()); + } +} + +static void +_activate(Evas_Object *obj) +{ + ELM_COMBOBOX_DATA_GET(obj, sd); + if (elm_widget_disabled_get(obj)) return; + sd->expanded = EINA_TRUE; + eo_do(obj, eo_event_callback_call(ELM_COMBOBOX_EVENT_EXPANDED, NULL)); + _table_resize(obj); + evas_object_show(sd->hover); +} + +static void +_on_item_selected(void *data , Evas_Object *obj EINA_UNUSED, void *event) +{ + ELM_COMBOBOX_DATA_GET(data, sd); + elm_object_focus_set(sd->entry, EINA_TRUE); + eo_do(data, eo_event_callback_call(ELM_COMBOBOX_EVENT_SELECTED, event)); +} + +static void +_on_item_pressed(void *data , Evas_Object *obj EINA_UNUSED, void *event) +{ + eo_do(data, eo_event_callback_call(ELM_COMBOBOX_EVENT_ITEM_PRESSED, event)); +} + +static Eina_Bool +_gl_filter_finished_cb(void *data, Eo *obj EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, void *event) +{ + ELM_COMBOBOX_DATA_GET(data, sd); + eo_do(data, eo_event_callback_call(ELM_COMBOBOX_EVENT_FILTER_DONE, event)); + count_items_genlist(data); + if (sd->count > 0) + { + if (sd->expanded == EINA_TRUE) + elm_combobox_hover_end(data); + _activate(data); + } + else elm_combobox_hover_end(data); + return EINA_TRUE; +} + +static Eina_Bool +_on_aborted(void *data, Eo *obj EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + ELM_COMBOBOX_DATA_GET(data, sd); + if (sd->expanded == EINA_TRUE) elm_combobox_hover_end(data); + return EINA_TRUE; +} + +static Eina_Bool +_on_changed(void *data, Eo *obj EINA_UNUSED, + const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + elm_combobox_hover_begin(data); + return EINA_TRUE; +} + +static void +_on_clicked(void *data, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + elm_combobox_hover_begin(data); +} + +EOLIAN static void +_elm_combobox_evas_object_smart_add(Eo *obj, Elm_Combobox_Data *sd EINA_UNUSED) +{ + eo_do_super(obj, MY_CLASS, evas_obj_smart_add()); + elm_widget_sub_object_parent_add(obj); + + elm_widget_mirrored_automatic_set(obj, EINA_FALSE); + + evas_object_smart_callback_add(obj, "clicked", _on_clicked, obj); + + //What are you doing here? + eo_do(obj, elm_obj_widget_theme_apply()); +} + +EOLIAN static void +_elm_combobox_evas_object_smart_del(Eo *obj, Elm_Combobox_Data *sd) +{ + sd->hover_parent = NULL; + eo_do_super(obj, MY_CLASS, evas_obj_smart_del()); +} + +EOLIAN static void +_elm_combobox_evas_object_smart_show(Eo *obj, Elm_Combobox_Data *sd) +{ + eo_do_super(obj, MY_CLASS, evas_obj_smart_show()); + if (sd->expanded) evas_object_show(sd->hover); +} + +EOLIAN static void +_elm_combobox_evas_object_smart_hide(Eo *obj, Elm_Combobox_Data *sd) +{ + eo_do_super(obj, MY_CLASS, evas_obj_smart_hide()); + if (sd->hover) evas_object_hide(sd->hover); +} + +EOLIAN static Eina_Bool +_elm_combobox_elm_button_admits_autorepeat_get(Eo *obj EINA_UNUSED, + Elm_Combobox_Data *sd EINA_UNUSED) +{ + return EINA_FALSE; +} + +EAPI Evas_Object * +elm_combobox_add(Evas_Object *parent) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); + Evas_Object *obj = eo_add(MY_CLASS, parent); + return obj; +} + +EOLIAN static Eo * +_elm_combobox_eo_base_constructor(Eo *obj, Elm_Combobox_Data *sd) +{ + Evas_Object *gl; + Evas_Object *entry; + char buf[128]; + + eo_do_super(obj, MY_CLASS, eo_constructor()); + + eo_do(obj, + evas_obj_type_set(MY_CLASS_NAME_LEGACY), + evas_obj_smart_callbacks_descriptions_set(_smart_callbacks), + elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_GLASS_PANE)); + + //hover-parent + sd->hover_parent = elm_object_parent_widget_get(obj); + + //hover + sd->hover = eo_add(ELM_HOVER_CLASS, sd->hover_parent); + elm_widget_mirrored_automatic_set(sd->hover, EINA_FALSE); + elm_hover_target_set(sd->hover, obj); + + //table + sd->tbl = elm_table_add(obj); + evas_object_size_hint_weight_set(sd->tbl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(sd->tbl, EVAS_HINT_FILL, EVAS_HINT_FILL); + + //spacer + sd->spacer = evas_object_rectangle_add(evas_object_evas_get(sd->hover_parent)); + evas_object_size_hint_weight_set(sd->spacer, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(sd->spacer, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_color_set(sd->spacer, 0, 0, 0, 0); + elm_table_pack(sd->tbl, sd->spacer, 0, 0, 1, 1); + evas_object_show(sd->tbl); + + // This is the genlist object that will take over the genlist call + sd->genlist = gl = eo_add(ELM_GENLIST_CLASS, obj); + elm_widget_mirrored_automatic_set(gl, EINA_FALSE); + elm_widget_mirrored_set(gl, elm_widget_mirrored_get(obj)); + evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_smart_callback_add(gl, "selected", _on_item_selected, obj); + evas_object_smart_callback_add(gl, "pressed", _on_item_pressed, obj); + eo_do(gl, eo_event_callback_add(ELM_GENLIST_EVENT_FILTER_DONE, + _gl_filter_finished_cb, obj)); + elm_genlist_homogeneous_set(gl, EINA_TRUE); + elm_table_pack(sd->tbl, gl, 0, 0, 1, 1); + evas_object_show(sd->genlist); + + // This is the entry object that will take over the entry call + sd->entry = entry = eo_add(ELM_ENTRY_CLASS, obj); + elm_widget_mirrored_automatic_set(entry, EINA_FALSE); + elm_widget_mirrored_set(entry, elm_widget_mirrored_get(obj)); + elm_scroller_policy_set(entry, ELM_SCROLLER_POLICY_OFF, + ELM_SCROLLER_POLICY_OFF); + elm_entry_scrollable_set(entry, EINA_TRUE); + elm_entry_single_line_set(entry, EINA_TRUE); + eo_do(entry, eo_event_callback_add(ELM_ENTRY_EVENT_CHANGED_USER, + _on_changed, obj)); + eo_do(entry, eo_event_callback_add(ELM_ENTRY_EVENT_ABORTED, + _on_aborted, obj)); + evas_object_show(entry); + + snprintf(buf, sizeof(buf), "combobox_vertical/%s", elm_widget_style_get(obj)); + elm_object_style_set(sd->hover, buf); + evas_object_smart_callback_add(sd->hover, "clicked", _on_hover_clicked, obj); + elm_object_part_content_set(sd->hover, elm_hover_best_content_location_get + (sd->hover, ELM_HOVER_AXIS_VERTICAL), sd->tbl); + eo_do(obj, + eo_composite_attach(gl), + eo_composite_attach(entry)); + + elm_object_part_content_set(obj, "elm.swallow.content", entry); + return obj; +} + +EOLIAN static void +_elm_combobox_hover_begin(Eo *obj EINA_UNUSED, Elm_Combobox_Data *sd) +{ + if (!sd->hover) return; + elm_object_focus_set(sd->entry, EINA_TRUE); + elm_genlist_filter_set(sd->genlist, (void *)elm_object_text_get(sd->entry)); +} + +EOLIAN static void +_elm_combobox_hover_end(Eo *obj, Elm_Combobox_Data *sd) +{ + if (!sd->hover) return; + + sd->expanded = EINA_FALSE; + evas_object_hide(sd->hover); + eo_do(obj, eo_event_callback_call(ELM_COMBOBOX_EVENT_DISMISSED, NULL)); +} + +EOLIAN static Eina_Bool +_elm_combobox_expanded_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *sd) +{ + return sd->expanded; +} + +static Eina_Bool +_key_action_move(Evas_Object *obj, const char *params) +{ + ELM_COMBOBOX_DATA_GET(obj, sd); + Elm_Object_Item *it = NULL; + const char *dir = params; + if (!sd->hover) return EINA_FALSE; + + if (!strcmp(dir, "return")) + eo_do(obj, eo_event_callback_call(ELM_COMBOBOX_EVENT_CLICKED, NULL)); + else if (!strcmp(dir, "up")) + { + it = sd->item; + it = elm_genlist_item_prev_get(it); + if (!it) sd->item = elm_genlist_last_item_get(sd->genlist); + else sd->item = it; + elm_genlist_item_selected_set(sd->item, EINA_TRUE); + } + else if (!strcmp(dir, "down")) + { + it = sd->item; + it = elm_genlist_item_next_get(it); + if (!it) sd->item = elm_genlist_first_item_get(sd->genlist); + else sd->item = it; + elm_genlist_item_selected_set(sd->item, EINA_TRUE); + } + else return EINA_FALSE; + return EINA_TRUE; +} + +static Eina_Bool +_key_action_activate(Evas_Object *obj, const char *params EINA_UNUSED) +{ + elm_combobox_hover_begin(obj); + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_elm_combobox_elm_widget_event(Eo *obj, Elm_Combobox_Data *sd, + Evas_Object *src EINA_UNUSED, + Evas_Callback_Type type, void *event_info) +{ + Evas_Event_Key_Down *ev = event_info; + if (!sd || !sd->hover) return EINA_FALSE; + if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; + if (!_elm_config_key_binding_call(obj, MY_CLASS_NAME, ev, key_actions)) + return EINA_FALSE; + + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + return EINA_TRUE; +} + +static void +_elm_combobox_class_constructor(Eo_Class *klass) +{ + evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); +} + +EOLIAN const Elm_Atspi_Action * +_elm_combobox_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, + Elm_Combobox_Data *pd + EINA_UNUSED) +{ + static Elm_Atspi_Action atspi_actions[] = { + {"activate", "activate", "return", _key_action_activate}, + {"move,up", "move", "up", _key_action_move}, + {"move,down", "move", "down", _key_action_move}, + {NULL, NULL, NULL, NULL} + }; + return &atspi_actions[0]; +} + +EOLIAN void +_elm_combobox_elm_widget_part_text_set(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd, + const char * part, const char *label) +{ + elm_object_part_text_set(pd->entry, part, label); +} + +EOLIAN const char * +_elm_combobox_elm_widget_part_text_get(Eo *obj EINA_UNUSED, Elm_Combobox_Data *pd, + const char * part) +{ + return elm_object_part_text_get(pd->entry, part); +} + +EOLIAN static void +_elm_combobox_evas_object_smart_resize(Eo *obj, Elm_Combobox_Data *pd, + Evas_Coord w, Evas_Coord h) +{ + eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h)); + if (pd->count > 0) _table_resize(obj); +} +#include "elm_combobox.eo.c" diff --git a/src/lib/elc_combobox.h b/src/lib/elc_combobox.h new file mode 100644 index 0000000..80e1ae4 --- /dev/null +++ b/src/lib/elc_combobox.h @@ -0,0 +1,64 @@ +/** + * @defgroup Combobox Combobox + * @ingroup Elementary + * + * @image html combobox_inheritance_tree.png + * @image latex combobox_inheritance_tree.eps + * + * @image html img/widget/combobox/preview-00.png + * @image latex img/widget/combobox/preview-00.eps + * + * A combobox is a button displaying an entry that pops up a list of items + * (automatically choosing the direction to display). It is a convenience + * widget to avoid the need to do all the piecing together yourself. It is + * intended for manipulating a large number of items in the combobox menu. + * + * This widget inherits from the @ref Button, @ref Genlist and @ref Entry + * one, so that all the functions acting on it also work for combobox objects. + * + * This widget emits the following signals, besides the ones sent from + * @ref Button: + * - @c "clicked" - the user clicked the combobox button and popped up + * the sel + * - @c "selected" - an item in the combobox list is selected. event_info + * is the selected item + * - @c "dismissed" - the hover is dismissed + * - @c "expanded" - This is called on clicking combobox and elm_combobox_hover_begin(). + * - @c "language,changed" - the program's language changed (since 1.9) + * - @c "item,focused" - When the combobox item has received focus. (since 1.10) + * - @c "item,unfocused" - When the combobox item has lost focus. (since 1.10) + * + * Default content parts of the combobox widget that you can use for are: + * @li "icon" - An icon of the combobox + * + * Default text parts of the combobox widget that you can use for are: + * @li "default" - A label of the combobox + * + * Supported elm_object common APIs. + * @li @ref elm_object_disabled_set + * @li @ref elm_object_disabled_get + * @li @ref elm_object_part_text_set + * @li @ref elm_object_part_text_get + * @li @ref elm_object_part_content_set + * @li @ref elm_object_part_content_unset + * + * Supported elm_object_item common APIs. + * @li elm_object_item_del + * @li elm_object_item_part_text_get + * @li elm_object_item_signal_emit - this works only when the item is created. + * @li elm_object_item_style_set - this works only when the item is created. + * @li elm_object_item_style_get - this works only when the item is created. + * + * See @ref tutorial_combobox for an example. + * @{ + */ + +#ifdef EFL_EO_API_SUPPORT +#include "elm_combobox.eo.h" +#endif +#ifndef EFL_NOLEGACY_API_SUPPORT +#include "elc_combobox_legacy.h" +#endif +/** + * @} + */ diff --git a/src/lib/elc_combobox_legacy.h b/src/lib/elc_combobox_legacy.h new file mode 100644 index 0000000..0719c78 --- /dev/null +++ b/src/lib/elc_combobox_legacy.h @@ -0,0 +1,11 @@ +/** + * @brief Add a new Combobox object + * + * @param parent The parent object + * @return The new object or NULL if it cannot be created + * + * @ingroup Combobox + */ +EAPI Evas_Object *elm_combobox_add(Evas_Object *parent); + +#include "elm_combobox.eo.legacy.h" diff --git a/src/lib/elm_authors.h b/src/lib/elm_authors.h index 71cc0f6..f3ff5db 100644 --- a/src/lib/elm_authors.h +++ b/src/lib/elm_authors.h @@ -163,6 +163,7 @@ * @author Subodh Kumar <s7158.kumar@@samsung.com> * @author Kumar Navneet <k.navneet@@samsung.com> * @author Godly T Alias <godly.talias@@samsung.com> + * @author Divyesh Purohit <div.puro...@samsung.com> <purohit....@gmail.com> * * Please contact <enlightenment-de...@lists.sourceforge.net> to get in * contact with the developers and maintainers. diff --git a/src/lib/elm_combobox.eo b/src/lib/elm_combobox.eo new file mode 100644 index 0000000..96cbb7e --- /dev/null +++ b/src/lib/elm_combobox.eo @@ -0,0 +1,54 @@ +class Elm_Combobox (Elm.Button, Evas.Selectable_Interface, + Elm_Interface_Atspi_Widget_Action, + Elm.Entry, Elm.Genlist, Elm.Hover) +{ + eo_prefix: elm_obj_combobox; + methods { + @property expanded { + get { + [[Returns whether the combobox is expanded. + + This will return EINA_TRUE if the combobox is expanded or + EINA_FALSE if it is not expanded. + ]] + return: bool; + } + } + hover_begin { + [[This triggers the combobox popup from code, the same as if the user + had clicked the button. + ]] + } + hover_end { + [[This dismisses the combobox popup as if the user had clicked + outside the hover. + ]] + } + } + implements { + class.constructor; + Eo.Base.constructor; + Evas.Object_Smart.hide; + Evas.Object_Smart.show; + Evas.Object_Smart.add; + Evas.Object_Smart.del; + Evas.Object_Smart.resize; + Elm.Widget.part_text.set; + Elm.Widget.part_text.get; + Elm.Widget.theme_apply; + Elm.Widget.translate; + Elm.Widget.event; + Elm.Button.admits_autorepeat.get; + Elm_Interface_Atspi_Widget_Action.elm_actions.get; + } + events { + selected; + dismissed; + expanded; + clicked; + item,pressed; + filter,done; + language,changed; + access,changed; + } +} diff --git a/src/lib/elm_config.c b/src/lib/elm_config.c index 3496c6c..88595dc 100644 --- a/src/lib/elm_config.c +++ b/src/lib/elm_config.c @@ -1848,6 +1848,33 @@ _config_update(void) _elm_config->cursor_engine_only = 0; IFCFGEND + IFCFG(0x0007) + Elm_Config_Bindings_Widget *wb, *twb = NULL; + Eina_List *l; + + EINA_LIST_FOREACH(tcfg->bindings, l, wb) + { + if (wb->name && !strcmp(wb->name, "Elm_Combobox")) + { + twb = wb; + break; + } + } + if (twb) + { + EINA_LIST_FOREACH(_elm_config->bindings, l, wb) + { + if (wb->name && !strcmp(wb->name, "Elm_Combobox")) + { + // simply swap bindngs for Elm_Combobox with system ones + Eina_List *tmp = wb->key_bindings; + wb->key_bindings = twb->key_bindings; + twb->key_bindings = tmp; + break; + } + } + } + IFCFGEND /** * Fix user config for current ELM_CONFIG_EPOCH here. **/ diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h index 0c83e73..f0dfd01 100644 --- a/src/lib/elm_priv.h +++ b/src/lib/elm_priv.h @@ -134,7 +134,7 @@ struct _Elm_Theme * the users config doesn't need to be wiped - simply new values need * to be put in */ -#define ELM_CONFIG_FILE_GENERATION 0x0006 +#define ELM_CONFIG_FILE_GENERATION 0x0007 #define ELM_CONFIG_VERSION_EPOCH_OFFSET 16 #define ELM_CONFIG_VERSION ((ELM_CONFIG_EPOCH << ELM_CONFIG_VERSION_EPOCH_OFFSET) | \ ELM_CONFIG_FILE_GENERATION) diff --git a/src/lib/elm_widget_combobox.h b/src/lib/elm_widget_combobox.h new file mode 100644 index 0000000..80ffe25 --- /dev/null +++ b/src/lib/elm_widget_combobox.h @@ -0,0 +1,80 @@ +#ifndef ELM_WIDGET_COMBOBOX_H +#define ELM_WIDGET_COMBOBOX_H + +#include "Elementary.h" + +/* DO NOT USE THIS HEADER UNLESS YOU ARE PREPARED FOR BREAKING OF YOUR + * CODE. THIS IS ELEMENTARY'S INTERNAL WIDGET API (for now) AND IS NOT + * FINAL. CALL elm_widget_api_check(ELM_INTERNAL_API_VERSION) TO CHECK + * IT AT RUNTIME. + */ + +/** + * @addtogroup Widget + * @{ + * + * @section elm-combobox-class The Elementary Combobox Class + * + * Elementary, besides having the @ref Combobox widget, exposes its + * foundation -- the Elementary Combobox Class -- in order to create other + * widgets which are a combobox with some more logic on top. + */ + +/** + * Base button smart data extended with combobox instance data. + */ +typedef struct _Elm_Combobox_Data Elm_Combobox_Data; +struct _Elm_Combobox_Data +{ + /* aggregates a hover */ + Evas_Object *hover; + Evas_Object *hover_parent; + Evas_Object *genlist; + Evas_Object *entry; + Evas_Object *tbl; + Evas_Object *spacer; + Elm_Object_Item *item; + const char *style; + int count; + int item_height; + Eina_Bool expanded:1; +}; + +/** + * @} + */ + +#define ELM_COMBOBOX_DATA_GET(o, sd) \ + Elm_Combobox_Data * sd = eo_data_scope_get(o, ELM_COMBOBOX_CLASS) + +#define ELM_COMBOBOX_DATA_GET_OR_RETURN(o, ptr) \ + ELM_COMBOBOX_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + CRI("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return; \ + } + +#define ELM_COMBOBOX_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + ELM_COMBOBOX_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + CRI("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return val; \ + } + +#define ELM_COMBOBOX_CHECK(obj) \ + if (EINA_UNLIKELY(!eo_isa((obj), ELM_COMBOBOX_CLASS))) \ + return + +#define ELM_COMBOBOX_ITEM_CHECK(it) \ + ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, ); \ + ELM_COMBOBOX_CHECK(it->base.widget); + +#define ELM_COMBOBOX_ITEM_CHECK_OR_RETURN(it, ...) \ + ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \ + ELM_COMBOBOX_CHECK(it->base.widget) __VA_ARGS__; + +#endif --