summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordivyesh purohit <div.purohit@samsung.com>2016-01-04 15:22:46 -0800
committerCedric BAIL <cedric@osg.samsung.com>2016-01-04 15:24:49 -0800
commitb4f8b8c0c66095730d4436db3987c3fad34aec95 (patch)
tree34f3e64220928f7c9732769f603044e1ebb9c4bc
parent8692c32417c61a5d3297f35687d44fc6ed1e1747 (diff)
downloadelementary-b4f8b8c0c66095730d4436db3987c3fad34aec95.tar.gz
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.bail@free.fr> Signed-Off By: Divyesh Purohit <div.purohit@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 <cedric@osg.samsung.com>
-rw-r--r--AUTHORS1
-rw-r--r--config/default/base.src.in49
-rw-r--r--config/mobile/base.src.in49
-rw-r--r--config/standard/base.src.in49
-rw-r--r--data/themes/edc/elm/button.edc299
-rw-r--r--data/themes/edc/elm/hover.edc4
-rw-r--r--src/bin/Makefile.am1
-rw-r--r--src/bin/test.c2
-rw-r--r--src/bin/test_combobox.c165
-rw-r--r--src/lib/Elementary.h.in1
-rw-r--r--src/lib/Makefile.am5
-rw-r--r--src/lib/elc_combobox.c458
-rw-r--r--src/lib/elc_combobox.h64
-rw-r--r--src/lib/elc_combobox_legacy.h11
-rw-r--r--src/lib/elm_authors.h1
-rw-r--r--src/lib/elm_combobox.eo54
-rw-r--r--src/lib/elm_config.c27
-rw-r--r--src/lib/elm_priv.h2
-rw-r--r--src/lib/elm_widget_combobox.h80
19 files changed, 1318 insertions, 4 deletions
diff --git a/AUTHORS b/AUTHORS
index 0e2457b0b..5ead385ae 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -166,3 +166,4 @@ Subodh Kumar <s7158.kumar@samsung.com>
Kumar Navneet <k.navneet@samsung.com>
Godly T Alias <godly.talias@samsung.com> <godlytalias@yahoo.co.in>
Shashank Pandey <shashank.p@samsung.com> <shashank0990@gmail.com>
+Divyesh Purohit <div.purohit@samsung.com> <purohit.div@gmail.com>
diff --git a/config/default/base.src.in b/config/default/base.src.in
index 7bf77132b..e86f7d8ee 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 44bfd6739..a588aa165 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 fd60d6a9c..745e5778e 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 2134d41e3..9dd9f6186 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 8a7ed497f..75ea8138c 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 b93374a11..46db673e5 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 53f419d5b..a3ae31d1b 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 000000000..b5f11729c
--- /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 1cd7c7616..7dceefaca 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 20f6521b8..40fb59746 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 000000000..7e5487ffc
--- /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 000000000..80e1ae42f
--- /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 000000000..0719c782b
--- /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 71cc0f6c1..f3ff5dbde 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.purohit@samsung.com> <purohit.div@gmail.com>
*
* Please contact <enlightenment-devel@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 000000000..96cbb7ee3
--- /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 3496c6cf5..88595dc2b 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 0c83e739d..f0dfd01da 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 000000000..80ffe25c7
--- /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