From ed86a65957ef5b8020c9304f6665eb33fdf42544 Mon Sep 17 00:00:00 2001 From: Woochan Lee Date: Fri, 15 Sep 2017 17:13:30 +0900 Subject: elm: rename elm_multibuttonentry to Efl.Ui.Multibuttonentry Summary: @ref T5358 Reviewers: woohyun, jpeg, cedric, Jaehyun_Cho Reviewed By: Jaehyun_Cho Subscribers: Jaehyun, bu5hm4n, cedric, jpeg Maniphest Tasks: T5358 Differential Revision: https://phab.enlightenment.org/D5169 --- .../elementary/themes/edc/elm/multibuttonentry.edc | 48 + po/POTFILES.in | 2 +- src/Makefile_Elementary.am | 10 +- src/bin/elementary/test.c | 2 + src/bin/elementary/test_multibuttonentry.c | 75 +- src/lib/elementary/efl_ui_multibuttonentry.c | 2188 ++++++++++++++++++++ src/lib/elementary/efl_ui_multibuttonentry.eo | 201 ++ src/lib/elementary/efl_ui_multibuttonentry.h | 69 + src/lib/elementary/efl_ui_multibuttonentry_eo.h | 2 + .../efl_ui_multibuttonentry_internal_part.eo | 9 + .../elementary/efl_ui_multibuttonentry_private.h | 153 ++ src/lib/elementary/elc_multibuttonentry.c | 2161 ------------------- src/lib/elementary/elc_multibuttonentry.h | 2 +- src/lib/elementary/elc_multibuttonentry_common.h | 2 +- src/lib/elementary/elc_multibuttonentry_eo.h | 2 - src/lib/elementary/elc_multibuttonentry_legacy.h | 2 +- src/lib/elementary/elm_multibuttonentry.eo | 203 -- .../elm_multibuttonentry_internal_part.eo | 9 - src/lib/elementary/elm_widget_multibuttonentry.h | 153 -- 19 files changed, 2755 insertions(+), 2538 deletions(-) create mode 100644 src/lib/elementary/efl_ui_multibuttonentry.c create mode 100644 src/lib/elementary/efl_ui_multibuttonentry.eo create mode 100644 src/lib/elementary/efl_ui_multibuttonentry.h create mode 100644 src/lib/elementary/efl_ui_multibuttonentry_eo.h create mode 100644 src/lib/elementary/efl_ui_multibuttonentry_internal_part.eo create mode 100644 src/lib/elementary/efl_ui_multibuttonentry_private.h delete mode 100644 src/lib/elementary/elc_multibuttonentry.c delete mode 100644 src/lib/elementary/elc_multibuttonentry_eo.h delete mode 100644 src/lib/elementary/elm_multibuttonentry.eo delete mode 100644 src/lib/elementary/elm_multibuttonentry_internal_part.eo delete mode 100644 src/lib/elementary/elm_widget_multibuttonentry.h diff --git a/data/elementary/themes/edc/elm/multibuttonentry.edc b/data/elementary/themes/edc/elm/multibuttonentry.edc index cefb816419..73be6f8279 100644 --- a/data/elementary/themes/edc/elm/multibuttonentry.edc +++ b/data/elementary/themes/edc/elm/multibuttonentry.edc @@ -27,6 +27,54 @@ group { name: "elm/multibuttonentry/base/default"; } } +group { name: "elm/multibuttonentry/base/entry_separate"; + data.item: "horizontal_pad" 0; + data.item: "vertical_pad" 0; + data.item: "closed_height" 0; + parts { + part { name: "bg"; + type: RECT; + scale: 1; + description { state: "default" 0.0; + color_class: "multibuttonentry_bg"; + } + } + part { name: "elm.swallow.background"; + type: SWALLOW; + scale: 1; + description { state: "default" 0.0; + rel1.to: "bg"; + rel2.to: "bg"; + } + } + part { name: "entry.swallow"; type: SWALLOW; + description { state: "default" 0.0; + rel1 { + to: "bg"; + relative: 0.0 1.0; + } + rel2 { + to: "bg"; + relative: 1.0 1.0; + } + align: 0.5 1.0; + } + } + part { name: "box.swallow"; type: SWALLOW; + description { state: "default" 0.0; + rel1 { + to: "bg"; + relative: 0.0 0.0; + } + rel2 { + to: "entry.swallow"; + relative: 1.0 0.0; + } + } + } + } +} + group { name: "elm/multibuttonentry/label/default"; parts { part { name: "elm.text"; type: TEXT; mouse_events: 0; diff --git a/po/POTFILES.in b/po/POTFILES.in index 3185320c0f..ea328bae0b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -95,7 +95,7 @@ src/lib/elementary/elc_fileselector.c src/lib/elementary/elc_fileselector_button.c src/lib/elementary/elc_fileselector_entry.c src/lib/elementary/elc_hoversel.c -src/lib/elementary/elc_multibuttonentry.c +src/lib/elementary/efl_ui_multibuttonentry.c src/lib/elementary/elc_naviframe.c src/lib/elementary/elc_player.c src/lib/elementary/elc_popup.c diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index ad50ab466b..8c2e2d4a7a 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -46,7 +46,7 @@ elm_public_eolian_files = \ lib/elementary/elm_map.eo \ lib/elementary/elm_map_pan.eo \ lib/elementary/elm_menu.eo \ - lib/elementary/elm_multibuttonentry.eo \ + lib/elementary/efl_ui_multibuttonentry.eo \ lib/elementary/elm_notify.eo \ lib/elementary/efl_ui_nstate.eo \ lib/elementary/elm_pan.eo \ @@ -118,7 +118,7 @@ elm_public_eolian_files = \ lib/elementary/elm_actionslider_internal_part.eo \ lib/elementary/elm_bubble_internal_part.eo \ lib/elementary/elm_fileselector_internal_part.eo \ - lib/elementary/elm_multibuttonentry_internal_part.eo \ + lib/elementary/efl_ui_multibuttonentry_internal_part.eo \ lib/elementary/elm_code_widget.eo \ lib/elementary/efl_ui_text_interactive.eo \ lib/elementary/efl_ui_text.eo \ @@ -263,7 +263,7 @@ includesunstable_HEADERS = \ lib/elementary/elm_widget_map.h \ lib/elementary/elm_widget_mapbuf.h \ lib/elementary/elm_widget_menu.h \ - lib/elementary/elm_widget_multibuttonentry.h \ + lib/elementary/efl_ui_multibuttonentry_private.h \ lib/elementary/elm_widget_naviframe.h \ lib/elementary/elm_widget_notify.h \ lib/elementary/elm_widget_panel.h \ @@ -323,7 +323,7 @@ includesub_HEADERS = \ lib/elementary/elc_hoversel.h \ lib/elementary/elc_hoversel_legacy.h \ lib/elementary/elc_multibuttonentry.h \ - lib/elementary/elc_multibuttonentry_eo.h \ + lib/elementary/efl_ui_multibuttonentry_eo.h \ lib/elementary/elc_multibuttonentry_legacy.h \ lib/elementary/elc_multibuttonentry_common.h \ lib/elementary/elc_naviframe.h \ @@ -554,7 +554,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/elc_fileselector_button.c \ lib/elementary/elc_fileselector_entry.c \ lib/elementary/elc_hoversel.c \ - lib/elementary/elc_multibuttonentry.c \ + lib/elementary/efl_ui_multibuttonentry.c \ lib/elementary/elc_naviframe.c \ lib/elementary/elc_player.c \ lib/elementary/elc_popup.c \ diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c index 4e8f76e539..44e8f38d67 100644 --- a/src/bin/elementary/test.c +++ b/src/bin/elementary/test.c @@ -74,6 +74,7 @@ void test_entry_regex(void *data, Evas_Object *obj, void *event_info); void test_entry_notepad(void *data, Evas_Object *obj, void *event_info); void test_multibuttonentry(void *data, Evas_Object *obj, void *event_info); void test_multibuttonentry2(void *data, Evas_Object *obj, void *event_info); +void test_multibuttonentry3(void *data, Evas_Object *obj, void *event_info); void test_entry_anchor2(void *data, Evas_Object *obj, void *event_info); void test_entry_anchor(void *data, Evas_Object *obj, void *event_info); void test_entry_emoticon(void *data, Evas_Object *obj, void *event_info); @@ -740,6 +741,7 @@ add_tests: ADD_TEST(NULL, "Entries", "Entry Notepad", test_entry_notepad); ADD_TEST(NULL, "Entries", "Multibuttonentry", test_multibuttonentry); ADD_TEST(NULL, "Entries", "Multibuttonentry Shrink", test_multibuttonentry2); + ADD_TEST(NULL, "Entries", "Multibuttonentry Divide Entry", test_multibuttonentry3); ADD_TEST(NULL, "Entries", "Entry Anchor", test_entry_anchor); ADD_TEST(NULL, "Entries", "Entry Anchor2", test_entry_anchor2); ADD_TEST(NULL, "Entries", "Entry Emoticon", test_entry_emoticon); diff --git a/src/bin/elementary/test_multibuttonentry.c b/src/bin/elementary/test_multibuttonentry.c index e4c3370908..fb4bf710d0 100644 --- a/src/bin/elementary/test_multibuttonentry.c +++ b/src/bin/elementary/test_multibuttonentry.c @@ -3,7 +3,7 @@ #endif #include -static Elm_Multibuttonentry_Format_Cb format_func = NULL; +static Efl_Ui_Multibuttonentry_Format_Cb format_func = NULL; static char * _custom_format(int count, void *data EINA_UNUSED) @@ -201,6 +201,7 @@ _add_multibuttonentry(Evas_Object *parent) evas_object_size_hint_weight_set(mbe, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(mbe, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_content_set(scr, mbe); + item = elm_multibuttonentry_item_append(mbe, "mbe3", _select_cb, NULL); elm_multibuttonentry_item_prepend(mbe, "mbe1", _select_cb, NULL); elm_multibuttonentry_item_insert_before(mbe, item, "mbe2", _select_cb, NULL); @@ -345,3 +346,75 @@ test_multibuttonentry2(void *data EINA_UNUSED, evas_object_resize(win, 320, 480); evas_object_show(win); } + +static Evas_Object* +_add_multibuttonentry_divide_entry(Evas_Object *parent) +{ + Evas_Object *scr = NULL; + Evas_Object *mbe = NULL; + Evas_Object *btn = NULL; + void *data = NULL; + + scr = elm_scroller_add(parent); + elm_scroller_bounce_set(scr, EINA_FALSE, EINA_TRUE); + elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF,ELM_SCROLLER_POLICY_AUTO); + evas_object_show(scr); + + mbe = elm_multibuttonentry_add(parent); + elm_object_style_set(mbe, "entry_separate"); + elm_object_text_set(mbe, "To: "); + elm_object_part_text_set(mbe, "guide", "Tap to add recipient"); + evas_object_size_hint_weight_set(mbe, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(mbe, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_content_set(scr, mbe); + + // Add "item,selected","item,added", "item,deleted", "clicked", "unfocused", + // "expanded", "contracted" and "contracted,state,changed" smart callback + evas_object_smart_callback_add(mbe, "item,selected", _item_selected_cb, NULL); + evas_object_smart_callback_add(mbe, "item,added", _item_added_cb, NULL); + evas_object_smart_callback_add(mbe, "item,deleted", _item_deleted_cb, NULL); + evas_object_smart_callback_add(mbe, "item,clicked", _item_clicked_cb, NULL); + + evas_object_smart_callback_add(mbe, "clicked", _mbe_clicked_cb, NULL); + evas_object_smart_callback_add(mbe, "focused", _mbe_focused_cb, NULL); + evas_object_smart_callback_add(mbe, "unfocused", _mbe_unfocused_cb, NULL); + + evas_object_smart_callback_add(mbe, "expanded", _expanded_cb, NULL); + evas_object_smart_callback_add(mbe, "contracted", _contracted_cb, NULL); + evas_object_smart_callback_add(mbe, "expand,state,changed", _expand_state_changed_cb, NULL); + evas_object_smart_callback_add(mbe, "item,longpressed", _longpressed_cb, NULL); + + btn = _format_change_btn_add(mbe); + elm_object_part_content_set(parent, "box", btn); + + evas_object_resize(mbe, 200, 250); + elm_object_focus_set(mbe, EINA_TRUE); + + return scr; +} + +void +test_multibuttonentry3(void *data EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Evas_Object *win, *sc; + Evas_Object *ly; + char buf[PATH_MAX]; + + win = elm_win_util_standard_add("multibuttonentry", "MultiButtonEntry"); + elm_win_autodel_set(win, EINA_TRUE); + + ly = elm_layout_add(win); + snprintf(buf, sizeof(buf), "%s/objects/multibuttonentry.edj", elm_app_data_dir_get()); + elm_layout_file_set(ly, buf, "multibuttonentry_test"); + evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, ly); + evas_object_show(ly); + + sc = _add_multibuttonentry_divide_entry(ly); + elm_object_part_content_set(ly, "multibuttonentry", sc); + + evas_object_resize(win, 200, 250); + evas_object_show(win); +} diff --git a/src/lib/elementary/efl_ui_multibuttonentry.c b/src/lib/elementary/efl_ui_multibuttonentry.c new file mode 100644 index 0000000000..35d8a47f75 --- /dev/null +++ b/src/lib/elementary/efl_ui_multibuttonentry.c @@ -0,0 +1,2188 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED +#define ELM_WIDGET_ITEM_PROTECTED +#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED + +#include +#include "elm_priv.h" +#include "efl_ui_multibuttonentry_private.h" + +#include "efl_ui_multibuttonentry_internal_part.eo.h" +#include "elm_part_helper.h" + +#define MY_CLASS EFL_UI_MULTIBUTTONENTRY_CLASS +#define MY_CLASS_PFX efl_ui_multibuttonentry + +#define MY_CLASS_NAME "Efl.Ui.Multibuttonentry" +#define MY_CLASS_NAME_LEGACY "elm_multibuttonentry" + +#define MAX_STR 256 +#define MIN_W_ENTRY 10 + +//widget signals +static const char SIG_ITEM_SELECTED[] = "item,selected"; +static const char SIG_ITEM_ADDED[] = "item,added"; +static const char SIG_ITEM_DELETED[] = "item,deleted"; +static const char SIG_ITEM_CLICKED[] = "item,clicked"; +static const char SIG_ITEM_LONGPRESSED[] = "item,longpressed"; +static const char SIG_CLICKED[] = "clicked"; +static const char SIG_FOCUSED[] = "focused"; +static const char SIG_UNFOCUSED[] = "unfocused"; +static const char SIG_EXPANDED[] = "expanded"; +static const char SIG_CONTRACTED[] = "contracted"; +static const char SIG_EXPAND_STATE_CHANGED[] = "expand,state,changed"; +static const Evas_Smart_Cb_Description _smart_callbacks[] = { + {SIG_ITEM_SELECTED, ""}, + {SIG_ITEM_ADDED, ""}, + {SIG_ITEM_DELETED, ""}, + {SIG_ITEM_CLICKED, ""}, + {SIG_ITEM_LONGPRESSED, ""}, + {SIG_CLICKED, ""}, + {SIG_FOCUSED, ""}, + {SIG_UNFOCUSED, ""}, + {SIG_EXPANDED, ""}, + {SIG_CONTRACTED, ""}, + {SIG_EXPAND_STATE_CHANGED, ""}, + {NULL, NULL} +}; + +static Eina_Bool _efl_ui_multibuttonentry_smart_focus_next_enable = EINA_FALSE; +static Eina_Bool _efl_ui_multibuttonentry_smart_focus_direction_enable = EINA_TRUE; + +static void _entry_changed_cb(void *data, const Efl_Event *event); +static void _entry_focus_in_cb(void *data, const Efl_Event *event); +static void _entry_focus_out_cb(void *data, const Efl_Event *event); +static void _entry_clicked_cb(void *data, const Efl_Event *event); + +EFL_CALLBACKS_ARRAY_DEFINE(_multi_buttonentry_cb, + { ELM_ENTRY_EVENT_CHANGED, _entry_changed_cb }, + { ELM_WIDGET_EVENT_FOCUSED, _entry_focus_in_cb }, + { ELM_WIDGET_EVENT_UNFOCUSED, _entry_focus_out_cb }, + { EFL_UI_EVENT_CLICKED, _entry_clicked_cb } +); + +EOLIAN void +_efl_ui_multibuttonentry_elm_widget_translate(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + Elm_Object_Item *it; + Eina_List *l; + + EINA_LIST_FOREACH(sd->items, l, it) + elm_wdg_item_translate(it); + + elm_obj_widget_translate(efl_super(obj, MY_CLASS)); +} + +static char * +_format_count(int count, void *data EINA_UNUSED) +{ + char buf[32]; + + if (!snprintf(buf, sizeof(buf), "+%d", count)) return NULL; + return strdup(buf); +} + +EOLIAN static Efl_Ui_Theme_Apply +_efl_ui_multibuttonentry_elm_widget_theme_apply(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd) +{ + const char *str; + int hpad = 0, vpad = 0; + Eina_List *l; + Elm_Object_Item *eo_item; + double pad_scale; + + Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED; + int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); + if (!int_ret) return EFL_UI_THEME_APPLY_FAILED; + + str = elm_layout_data_get(obj, "horizontal_pad"); + if (str) hpad = atoi(str); + str = elm_layout_data_get(obj, "vertical_pad"); + if (str) vpad = atoi(str); + pad_scale = efl_ui_scale_get(obj) * elm_config_scale_get() + / edje_object_base_scale_get(elm_layout_edje_get(obj)); + elm_box_padding_set(sd->box, (hpad * pad_scale), (vpad * pad_scale)); + + EINA_LIST_FOREACH(sd->items, l, eo_item) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + if (VIEW(item)) + if (!elm_layout_theme_set + (VIEW(item), "multibuttonentry", "btn", elm_widget_style_get(obj))) + CRI("Failed to set layout!"); + } + + elm_widget_theme_object_set + (obj, sd->label, "multibuttonentry", "label", + elm_widget_style_get(obj)); + elm_widget_theme_object_set + (obj, sd->end, "multibuttonentry", "closedbutton", + elm_widget_style_get(obj)); + elm_widget_theme_object_set + (obj,sd->guide_text, "multibuttonentry", "guidetext", + elm_widget_style_get(obj)); + + sd->style = elm_widget_style_get(obj); + if (!strncmp(sd->style, "entry_separate", 14)) + { + elm_box_unpack(sd->box, sd->entry); + elm_layout_content_set(obj, "entry.swallow", sd->entry); + } + + elm_layout_sizing_eval(obj); + + return int_ret; +} + +static void +_visual_guide_text_set(Evas_Object *obj) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + elm_box_unpack(sd->box, sd->guide_text); + elm_box_unpack(sd->box, sd->entry); + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) return; + + if (!elm_widget_focus_get(obj)) + elm_object_focus_set(sd->entry, EINA_FALSE); + + if ((!eina_list_count(sd->items)) && sd->guide_text + && (!elm_widget_focus_get(obj)) && (!sd->n_str)) + { + evas_object_hide(sd->entry); + elm_box_pack_end(sd->box, sd->guide_text); + evas_object_show(sd->guide_text); + sd->view_state = MULTIBUTTONENTRY_VIEW_GUIDETEXT; + } + else + { + evas_object_hide(sd->guide_text); + + if (sd->editable) + { + if (!strncmp(sd->style, "entry_separate", 14)) + elm_layout_content_set(obj, "entry.swallow", sd->entry); + else + elm_box_pack_end(sd->box, sd->entry); + evas_object_show(sd->entry); + if (elm_widget_focus_get(obj)) + { + if (!sd->selected_it) + elm_object_focus_set(sd->entry, EINA_TRUE); + } + } + sd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY; + } +} + +static void +_shrink_mode_set(Evas_Object *obj, + Eina_Bool shrink) +{ + int count; + Eina_List *l; + Elm_Object_Item *eo_item; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + if (!sd->items) return; + if (sd->view_state == MULTIBUTTONENTRY_VIEW_ENTRY) + evas_object_hide(sd->entry); + else if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) + evas_object_hide(sd->guide_text); + else if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + evas_object_hide(sd->end); + + if (shrink == EINA_TRUE) + { + Evas_Coord w = 0, w_tmp = 0; + Evas_Coord box_inner_item_width_padding = 0; + + elm_box_padding_get(sd->box, &box_inner_item_width_padding, NULL); + // unpack all items and entry + elm_box_unpack_all(sd->box); + EINA_LIST_FOREACH(sd->items, l, eo_item) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + evas_object_hide(VIEW(item)); + item->visible = EINA_FALSE; + } + // pack buttons only 1line + w = sd->w_box; + + if (sd->label && sd->label_packed) + { + elm_box_pack_end(sd->box, sd->label); + efl_gfx_size_hint_combined_min_get(sd->label, &w_tmp, NULL); + w -= w_tmp; + w -= box_inner_item_width_padding; + } + + eo_item = NULL; + count = eina_list_count(sd->items); + + EINA_LIST_FOREACH(sd->items, l, eo_item) + { + Evas_Coord item_w, w_label_count = 0, h = 0; + char *buf; + + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + elm_box_pack_end(sd->box, VIEW(item)); + evas_object_show(VIEW(item)); + item->visible = EINA_TRUE; + + efl_gfx_size_hint_combined_min_get(VIEW(item), &item_w, NULL); + + w -= item_w; + w -= box_inner_item_width_padding; + count--; + + if (count > 0) + { + buf = sd->format_func(count, (void *)sd->format_func_data); + if (buf) + { + edje_object_part_text_escaped_set + (sd->end, "elm.text", buf); + free(buf); + } + + edje_object_size_min_calc(sd->end, &w_label_count, NULL); + elm_coords_finger_size_adjust(1, &w_label_count, 1, NULL); + } + + if ((w < 0) || (w < w_label_count)) + { + elm_box_unpack(sd->box, VIEW(item)); + evas_object_hide(VIEW(item)); + item->visible = EINA_FALSE; + count++; + + buf = sd->format_func(count, (void *)sd->format_func_data); + if (buf) + { + edje_object_part_text_escaped_set + (sd->end, "elm.text", buf); + free(buf); + } + + edje_object_size_min_calc(sd->end, &w_label_count, &h); + elm_coords_finger_size_adjust(1, &w_label_count, 1, &h); + evas_object_size_hint_min_set + (sd->end, w_label_count, h); + elm_box_pack_end(sd->box, sd->end); + evas_object_show(sd->end); + + break; + } + } + + if (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK) + { + sd->view_state = MULTIBUTTONENTRY_VIEW_SHRINK; + efl_event_callback_legacy_call + (obj, EFL_UI_MULTIBUTTONENTRY_EVENT_EXPAND_STATE_CHANGED, (void *)1); + } + } + else + { + // unpack all items and entry + elm_box_unpack_all(sd->box); + EINA_LIST_FOREACH(sd->items, l, eo_item) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + evas_object_hide(VIEW(item)); + item->visible = EINA_FALSE; + } + evas_object_hide(sd->end); + + // pack buttons only 1line + + if (sd->label && sd->label_packed) elm_box_pack_end(sd->box, sd->label); + + // pack remain btns + eo_item = NULL; + EINA_LIST_FOREACH(sd->items, l, eo_item) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + elm_box_pack_end(sd->box, VIEW(item)); + evas_object_show(VIEW(item)); + item->visible = EINA_TRUE; + } + + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + { + sd->view_state = MULTIBUTTONENTRY_VIEW_NONE; + efl_event_callback_legacy_call + (obj, EFL_UI_MULTIBUTTONENTRY_EVENT_EXPAND_STATE_CHANGED, (void *)(uintptr_t)sd->shrink); + } + } + + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + _efl_ui_multibuttonentry_smart_focus_direction_enable = EINA_FALSE; + else + _efl_ui_multibuttonentry_smart_focus_direction_enable = EINA_TRUE; + + if (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK) + _visual_guide_text_set(obj); +} + +static void +_view_update(Efl_Ui_Multibuttonentry_Data *sd) +{ + Evas_Coord width = 1, height = 1; + Evas_Object *obj = sd->parent; + + if (sd->w_box <= 0) return; + + // update label + if (sd->label) + efl_gfx_size_hint_combined_min_get(sd->label, &width, &height); + + if (sd->guide_text) + { + Evas_Coord guide_text_width = sd->w_box - width; + + evas_object_size_hint_min_set(sd->guide_text, guide_text_width, height); + } + + // update buttons in shrink mode + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + _shrink_mode_set(obj, EINA_TRUE); + + // update guidetext + _visual_guide_text_set(obj); +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_elm_widget_on_focus(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd, Elm_Object_Item *item EINA_UNUSED) +{ + if (elm_widget_focus_get(obj)) + { + // ACCESS + if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) goto end; + + if (sd->editable) + { + if ((sd->selected_it)) + { + elm_layout_signal_emit(VIEW(sd->selected_it), "elm,state,focused", "elm"); + elm_object_focus_set(VIEW(sd->selected_it), EINA_TRUE); + efl_ui_text_input_panel_show(sd->entry); + } + else if (((!sd->selected_it) || (!eina_list_count(sd->items)))) + { + _view_update(sd); + efl_ui_text_input_panel_show(sd->entry); + } + } + + efl_event_callback_legacy_call + (obj, ELM_WIDGET_EVENT_FOCUSED, NULL); + } + else + { + if (sd->editable) + { + _view_update(sd); + efl_ui_text_input_panel_hide(sd->entry); + } + + if (sd->selected_it) + elm_layout_signal_emit(VIEW(sd->selected_it), "elm,state,unfocused", "elm"); + + efl_event_callback_legacy_call + (obj, ELM_WIDGET_EVENT_UNFOCUSED, NULL); + } + +end: + return EINA_TRUE; +} + +static void +_item_del(Elm_Multibuttonentry_Item_Data *item) +{ + Evas_Object *obj = WIDGET(item); + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + sd->items = eina_list_remove(sd->items, EO_OBJ(item)); + elm_box_unpack(sd->box, VIEW(item)); + + efl_event_callback_legacy_call + (obj, EFL_UI_MULTIBUTTONENTRY_EVENT_ITEM_DELETED, EO_OBJ(item)); + + if (sd->selected_it == item) + sd->selected_it = NULL; + + if (sd->focused_it == item) + sd->focused_it = NULL; + + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + _shrink_mode_set(obj, EINA_TRUE); + + if (!eina_list_count(sd->items)) + _visual_guide_text_set(obj); +} + +static void +_current_item_state_change(Evas_Object *obj, + Multibuttonentry_Button_State state) +{ + Elm_Multibuttonentry_Item_Data *item; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + item = sd->selected_it; + + if (!item) return; + + switch (state) + { + case MULTIBUTTONENTRY_BUTTON_STATE_SELECTED: + elm_layout_signal_emit(VIEW(item), "elm,state,focused", "elm"); + efl_event_callback_legacy_call + (obj, EFL_UI_MULTIBUTTONENTRY_EVENT_ITEM_SELECTED, EO_OBJ(item)); + break; + case MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT: + default: + elm_layout_signal_emit(VIEW(item), "elm,state,default", "elm"); + sd->selected_it = NULL; + break; + } +} + +static void +_current_item_change(Evas_Object *obj, + Elm_Object_Item *eo_it) +{ + Eina_List *l; + Elm_Object_Item *eo_temp_it; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); + + // change the state of previous item to "default" + _current_item_state_change(obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT); + + // change the current + EINA_LIST_FOREACH(sd->items, l, eo_temp_it) + { + if (eo_temp_it == eo_it) + { + sd->selected_it = it; + break; + } + } + // change the state of current item to "focused" + _current_item_state_change(obj, MULTIBUTTONENTRY_BUTTON_STATE_SELECTED); +} + +static void +_item_select(Evas_Object *obj, + Elm_Multibuttonentry_Item_Data *it) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + if (it) + { + _current_item_change(obj, EO_OBJ(it)); + + if (it->func) it->func((void *)(WIDGET_ITEM_DATA_GET(EO_OBJ(it))), WIDGET(it), EO_OBJ(it)); + + if (elm_widget_focus_get(obj)) + { + elm_object_focus_set(sd->entry, EINA_FALSE); + elm_object_focus_set(VIEW(it), EINA_TRUE); + + // ACCESS + if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF) + { + Evas_Object *ao, *po; + Eina_Strbuf *buf; + const char *part; + + part = "elm.btn.text"; + po = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(VIEW(it)), part); + ao = evas_object_data_get(po, "_part_access_obj"); + _elm_access_highlight_set(ao); + + buf = eina_strbuf_new(); + eina_strbuf_append_printf(buf, + "multi button entry item %s is selected", + edje_object_part_text_get(elm_layout_edje_get(VIEW(it)), part)); + + _elm_access_say(eina_strbuf_string_get(buf)); + eina_strbuf_free(buf); + } + } + } + else + { + _current_item_state_change + (obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT); + if (elm_widget_focus_get(obj) && sd->editable) + elm_object_focus_set(sd->entry, EINA_TRUE); + } +} + +static void +_on_item_clicked(void *data, + Evas_Object *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Elm_Object_Item *eo_it = data; + + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); + + _item_select(WIDGET(it), it); + + if (_elm_config->atspi_mode) + elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, + ELM_ATSPI_STATE_CHECKED, + EINA_TRUE); + + if (sd->selected_it) + efl_event_callback_legacy_call + (WIDGET(it), EFL_UI_MULTIBUTTONENTRY_EVENT_ITEM_CLICKED, eo_it); +} + +static void +_on_item_deleted(void *data, + Evas_Object *obj, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eina_List *l; + Elm_Object_Item *eo_it = data; + Elm_Object_Item *eo_temp_it; + + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); + // change the current + EINA_LIST_FOREACH(sd->items, l, eo_temp_it) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_temp_it, temp_it); + if (VIEW(temp_it) == obj) + { + elm_wdg_item_del(eo_temp_it); + break; + } + } +} + +static void +_on_item_focused(void *data, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Elm_Multibuttonentry_Item_Data *it = data; + if (!it) return; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); + + sd->focused_it = it; +} + +static void +_on_item_unfocused(void *data, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Elm_Multibuttonentry_Item_Data *it = data; + if (!it) return; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); + + sd->focused_it = NULL; +} + +static Eina_Bool +_long_press_cb(void *data) +{ + Elm_Multibuttonentry_Item_Data *it = data; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd); + + sd->longpress_timer = NULL; + + efl_event_callback_legacy_call + (WIDGET(it), EFL_UI_MULTIBUTTONENTRY_EVENT_ITEM_LONGPRESSED, EO_OBJ(it)); + + return ECORE_CALLBACK_CANCEL; +} + +static void +_mouse_down_cb(void *data, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + Elm_Multibuttonentry_Item_Data *it = data; + Evas_Event_Mouse_Down *ev = event_info; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); + + if (ev->button != 1) return; + + ecore_timer_del(sd->longpress_timer); + sd->longpress_timer = ecore_timer_add + (_elm_config->longpress_timeout, _long_press_cb, it); +} + +static void +_mouse_up_cb(void *data, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Elm_Multibuttonentry_Item_Data *it = data; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); + + ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del); +} + +EOLIAN static void +_elm_multibuttonentry_item_elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED, + Elm_Multibuttonentry_Item_Data *item, + const char *emission, + const char *source) +{ + elm_layout_signal_emit(VIEW(item), emission, source); +} + +EOLIAN static void +_elm_multibuttonentry_item_elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED, + Elm_Multibuttonentry_Item_Data *item, + const char *part, + const char *label) +{ + const char *dest_part = NULL; + Evas_Coord minw = -1, minh = -1, boxw; + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(item), sd); + + if (!part || !strcmp(part, "elm.text")) + dest_part = "elm.btn.text"; + else + dest_part = part; + + edje_object_part_text_escaped_set(elm_layout_edje_get(VIEW(item)), dest_part, label); + + elm_coords_finger_size_adjust(1, &minw, 1, &minh); + edje_object_size_min_restricted_calc + (elm_layout_edje_get(VIEW(item)), &minw, &minh, minw, minh); + evas_object_size_hint_min_set(VIEW(item), minw, minh); + evas_object_geometry_get(sd->box, NULL, NULL, &boxw, NULL); + + if (minw > boxw) + { + evas_object_size_hint_min_set(VIEW(item), boxw, minh); + evas_object_resize(VIEW(item), boxw, minh); + } +} + +EOLIAN static const char * +_elm_multibuttonentry_item_elm_widget_item_part_text_get(Eo *eo_item EINA_UNUSED, + Elm_Multibuttonentry_Item_Data *item, + const char *part) +{ + const char *src_part = NULL; + + if (!part || !strcmp(part, "elm.text")) + src_part = "elm.btn.text"; + else + src_part = part; + + return edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), src_part); +} + +EOLIAN static void +_elm_multibuttonentry_item_efl_object_destructor(Eo *eo_it, + Elm_Multibuttonentry_Item_Data *it) +{ + if (_elm_config->atspi_mode) + elm_interface_atspi_accessible_children_changed_del_signal_emit(WIDGET(it), eo_it); + _item_del(it); + + efl_destructor(efl_super(eo_it, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); +} + +static void +_access_multibuttonentry_label_register(Evas_Object *obj, Eina_Bool is_access) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + Evas_Object *po; + + po = (Evas_Object *)edje_object_part_object_get(sd->label, "elm.text"); + if (is_access) + { + Evas_Object *ao; + ao = _elm_access_edje_object_part_object_register + (obj, sd->label, "elm.text"); + _elm_access_text_set(_elm_access_info_get(ao), + ELM_ACCESS_TYPE, E_("multi button entry label")); + } + else + _elm_access_edje_object_part_object_unregister + (obj, sd->label, "elm.text"); + + evas_object_pass_events_set(po, !is_access); + evas_object_propagate_events_set(sd->label, !is_access); +} + +static void +_access_multibuttonentry_item_register(Evas_Object *obj, + Elm_Object_Item *eo_item, + Eina_Bool is_access) +{ + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + if (is_access) + { + Evas_Object *ao; + ao = _elm_access_edje_object_part_object_register + (obj, elm_layout_edje_get(VIEW(item)), "elm.btn.text"); + _elm_access_text_set(_elm_access_info_get(ao), + ELM_ACCESS_TYPE, E_("multi button entry item")); + } + else + _elm_access_edje_object_part_object_unregister + (obj, elm_layout_edje_get(VIEW(item)), "elm.btn.text"); + + /* cannot read item because mouse-in event is delivered to + the multibuttonentry resize_obj which is registered as an access + object, so the mouse-in event should be blocked here */ + evas_object_propagate_events_set(VIEW(item), !is_access); +} + +EOLIAN static Eo * +_elm_multibuttonentry_item_efl_object_constructor(Eo *eo_item, Elm_Multibuttonentry_Item_Data *item) +{ + eo_item = efl_constructor(efl_super(eo_item, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); + item->base = efl_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS); + + return eo_item; +} + +static Elm_Object_Item * +_item_new(Efl_Ui_Multibuttonentry_Data *sd, + const char *str, + Multibuttonentry_Pos pos, + Elm_Object_Item *efl_reference, + Evas_Smart_Cb func, + void *data) +{ + Eina_List *l; + Eo *eo_item; + Elm_Multibuttonentry_Item_Filter *item_filter; + Elm_Multibuttonentry_Item_Data *reference = efl_reference? + efl_data_scope_get(efl_reference, ELM_MULTIBUTTONENTRY_ITEM_CLASS): + NULL; + Evas_Object *obj; + int minw, minh, boxw; + + obj = sd->parent; + + if (!str) return NULL; + + EINA_LIST_FOREACH(sd->filter_list, l, item_filter) + { + if (!(item_filter->callback_func(obj, str, data, item_filter->data))) + return NULL; + } + + eo_item = efl_add(ELM_MULTIBUTTONENTRY_ITEM_CLASS, obj); + if (!eo_item) + return NULL; + WIDGET_ITEM_DATA_SET(eo_item, data); + + elm_interface_atspi_accessible_role_set(eo_item, ELM_ATSPI_ROLE_RADIO_BUTTON); + + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + VIEW(item) = elm_layout_add(obj); + + elm_interface_atspi_accessible_type_set(VIEW(item), ELM_ATSPI_TYPE_DISABLED); + + if (!elm_layout_theme_set + (VIEW(item), "multibuttonentry", "btn", elm_widget_style_get(obj))) + CRI("Failed to set layout!"); + + elm_object_part_text_set(VIEW(item), "elm.btn.text", str); + + //entry is cleared when text is made to button + efl_text_set(sd->entry, ""); + + elm_layout_signal_callback_add + (VIEW(item), "mouse,clicked,1", "*", _on_item_clicked, EO_OBJ(item)); + elm_layout_signal_callback_add + (VIEW(item), "elm,deleted", "elm", _on_item_deleted, EO_OBJ(item)); + evas_object_smart_callback_add + (VIEW(item), "focused", _on_item_focused, item); + evas_object_smart_callback_add + (VIEW(item), "unfocused", _on_item_unfocused, item); + evas_object_event_callback_add + (VIEW(item), + EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, item); + evas_object_event_callback_add + (VIEW(item), + EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, item); + + evas_object_show(VIEW(item)); + + evas_object_smart_calculate(VIEW(item)); + efl_gfx_size_hint_combined_min_get(VIEW(item), &minw, &minh); + evas_object_geometry_get(sd->box, NULL, NULL, &boxw, NULL); + + if (sd->w_box && minw > boxw) + { + elm_coords_finger_size_adjust(1, &boxw, 1, &minh); + evas_object_size_hint_min_set(VIEW(item), boxw, minh); + evas_object_resize(VIEW(item), boxw, minh); + } + + elm_object_focus_allow_set(VIEW(item), EINA_TRUE); + + item->visible = EINA_TRUE; + + // ACCESS + if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) + { + Eina_Strbuf *buf; + buf = eina_strbuf_new(); + + eina_strbuf_append_printf(buf, + "multi button entry item %s is added", + edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), "elm.btn.text")); + + _elm_access_say(eina_strbuf_string_get(buf)); + eina_strbuf_free(buf); + + _access_multibuttonentry_item_register(obj, eo_item, EINA_TRUE); + } + + if (func) + { + item->func = func; + } + + switch (pos) + { + case MULTIBUTTONENTRY_POS_START: + sd->items = eina_list_prepend(sd->items, eo_item); + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + { + elm_widget_sub_object_add(obj, VIEW(item)); + _shrink_mode_set(obj, EINA_TRUE); + } + else + { + if (sd->label && sd->label_packed) + elm_box_pack_after(sd->box, VIEW(item), sd->label); + else + elm_box_pack_start(sd->box, VIEW(item)); + if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) + _visual_guide_text_set(obj); + } + break; + + case MULTIBUTTONENTRY_POS_END: + sd->items = eina_list_append(sd->items, eo_item); + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + { + elm_widget_sub_object_add(obj, VIEW(item)); + evas_object_hide(VIEW(item)); + } + else + { + if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) + _visual_guide_text_set(obj); + + if (sd->editable) + { + if (!strncmp(sd->style, "entry_separate", 14)) + elm_box_pack_end(sd->box, VIEW(item)); + else + elm_box_pack_before(sd->box, VIEW(item), sd->entry); + } + else + elm_box_pack_end(sd->box, VIEW(item)); + } + break; + + case MULTIBUTTONENTRY_POS_BEFORE: + if (efl_reference) + sd->items = eina_list_prepend_relative(sd->items, eo_item, efl_reference); + else + sd->items = eina_list_append(sd->items, eo_item); + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + { + elm_widget_sub_object_add(obj, VIEW(item)); + evas_object_hide(VIEW(item)); + _shrink_mode_set(obj, EINA_TRUE); + } + else + { + if (efl_reference) + elm_box_pack_before(sd->box, VIEW(item), VIEW(reference)); + else + { + if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) + _visual_guide_text_set(obj); + if (sd->editable) + { + if (!strncmp(sd->style, "entry_separate", 14)) + elm_box_pack_end(sd->box, VIEW(item)); + else + elm_box_pack_before(sd->box, VIEW(item), sd->entry); + } + else + elm_box_pack_end(sd->box, VIEW(item)); + } + } + break; + + case MULTIBUTTONENTRY_POS_AFTER: + if (efl_reference) + sd->items = eina_list_append_relative(sd->items, eo_item, efl_reference); + else + sd->items = eina_list_append(sd->items, eo_item); + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + { + elm_widget_sub_object_add(obj, VIEW(item)); + _shrink_mode_set(obj, EINA_TRUE); + } + else + { + if (efl_reference) + elm_box_pack_after(sd->box, VIEW(item), VIEW(reference)); + else + { + if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) + _visual_guide_text_set(obj); + if (sd->editable) + { + if (!strncmp(sd->style, "entry_separate", 14)) + elm_box_pack_end(sd->box, VIEW(item)); + else + elm_box_pack_before(sd->box, VIEW(item), sd->entry); + } + else + elm_box_pack_end(sd->box, VIEW(item)); + } + } + break; + + default: + break; + } + + if (!elm_object_focus_get(obj) && sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK && sd->w_box) + _shrink_mode_set(obj, EINA_TRUE); + + + efl_event_callback_legacy_call + (obj, EFL_UI_MULTIBUTTONENTRY_EVENT_ITEM_ADDED, eo_item); + + if (_elm_config->atspi_mode) + { + elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, eo_item); + elm_interface_atspi_accessible_added(eo_item); + } + + return eo_item; +} + +//FIXME: having an empty event handling function and reacting on Evas +//events on specific objects is crazy, someone should fix that. +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_elm_widget_widget_event(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd EINA_UNUSED, const Efl_Event *eo_event EINA_UNUSED, Evas_Object *src EINA_UNUSED) +{ + // ACCESS + if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) return EINA_FALSE; + + return EINA_TRUE; +} + +EOLIAN static void +_efl_ui_multibuttonentry_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd EINA_UNUSED) +{ + Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; + + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + elm_coords_finger_size_adjust(1, &minw, 1, &minh); + edje_object_size_min_restricted_calc + (wd->resize_obj, &minw, &minh, minw, minh); + elm_coords_finger_size_adjust(1, &minw, 1, &minh); + evas_object_size_hint_min_set(obj, minw, minh); + evas_object_size_hint_max_set(obj, maxw, maxh); +} + +static void +_mouse_clicked_signal_cb(void *data EINA_UNUSED, + Evas_Object *obj, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + if (sd->editable) efl_ui_text_input_panel_show(sd->entry); + + efl_event_callback_legacy_call(obj, EFL_UI_EVENT_CLICKED, NULL); +} + +static void +_box_resize_cb(void *data, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event EINA_UNUSED) +{ + Evas_Coord w, h, mnw, mnh; + Eina_List *l; + Elm_Object_Item *eo_it; + int hpad; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + + evas_object_geometry_get(sd->box, NULL, NULL, &w, &h); + if ((w <= elm_config_finger_size_get()) || (h <= elm_config_finger_size_get())) return; + + elm_box_padding_get(obj, &hpad, NULL); + + if (sd->h_box < h) + efl_event_callback_legacy_call + (sd->parent, EFL_UI_MULTIBUTTONENTRY_EVENT_EXPANDED, NULL); + else if (sd->h_box > h) + efl_event_callback_legacy_call + (sd->parent, EFL_UI_MULTIBUTTONENTRY_EVENT_CONTRACTED, NULL); + + if (sd->items && sd->w_box != w) + { + EINA_LIST_FOREACH (sd->items, l, eo_it) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); + + elm_layout_sizing_eval(VIEW(it)); + evas_object_smart_calculate(VIEW(it)); + + efl_gfx_size_hint_combined_min_get(VIEW(it), &mnw, &mnh); + + if (mnw > w - hpad) + { + mnw = w - hpad; + evas_object_size_hint_min_set(VIEW(it), mnw, mnh); + evas_object_resize(VIEW(it), mnw, mnh); + } + } + } + + sd->w_box = w; + sd->h_box = h; + + if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) + _shrink_mode_set(data, EINA_TRUE); +} + +static void +_entry_resize_cb(void *data, + Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + + if (elm_widget_focus_get(sd->parent)) + { + Eina_Rectangle sr = {}; + + evas_object_geometry_get(sd->entry, &sr.x, &sr.y, &sr.w, &sr.h); + elm_widget_show_region_set(sd->entry, sr, EINA_TRUE); + } +} + +static void +_entry_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + const char *str; + + str = efl_text_get(sd->entry); + sd->n_str = str ? strlen(str) : 0; +} + +static void +_entry_focus_in_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + Elm_Multibuttonentry_Item_Data *item = NULL; + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + + if (sd->selected_it) + { + item = sd->selected_it; + elm_object_focus_set(sd->entry, EINA_FALSE); + elm_object_focus_set(VIEW(item), EINA_TRUE); + } +} + +static void +_entry_focus_out_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + const char *str; + + str = efl_text_get(sd->entry); + if (str && str[0]) + _item_new(sd, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL); +} + +static void +_entry_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + + _current_item_state_change(sd->parent, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT); + elm_object_focus_set(sd->entry, EINA_TRUE); +} + +static void +_layout_key_down_cb(void *data, + Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info; + + if (!sd->box) return; + + if (sd->last_it_select) + { + if (sd->selected_it && + ((!strcmp(ev->key, "BackSpace")) || + (!strcmp(ev->key, "Delete")))) + { + Elm_Multibuttonentry_Item_Data *item = sd->selected_it; + if (item && sd->editable) + { + elm_wdg_item_del(EO_OBJ(item)); + elm_object_focus_set(sd->entry, EINA_TRUE); + } + } + else if (sd->focused_it && + ((!strcmp(ev->key, "KP_Enter")) || + (!strcmp(ev->key, "Return")))) + { + Elm_Multibuttonentry_Item_Data *item = sd->focused_it; + if (item) + _on_item_clicked(EO_OBJ(item), NULL, NULL, NULL); + } + else if (((!sd->selected_it && (sd->n_str == 0) && + (!strcmp(ev->key, "BackSpace"))) || + (!strcmp(ev->key, "Delete")))) + { + Elm_Object_Item *eo_item = eina_list_data_get(eina_list_last(sd->items)); + if (eo_item) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + _item_select(sd->parent, item); + } + } + } + else + sd->last_it_select = EINA_TRUE; +} + +static void +_entry_key_down_cb(void *data, + Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info; + + if (sd->n_str == 1 && + (!strcmp(ev->key, "BackSpace") || !strcmp(ev->key, "Delete"))) + sd->last_it_select = EINA_FALSE; +} + +static void +_entry_key_up_cb(void *data, + Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); + Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info; + const char *str; + + if (!sd->box) return; + + str = efl_text_get(sd->entry); + if (!str) return; + + if (strlen(str) && + (!strcmp(ev->key, "KP_Enter") || !strcmp(ev->key, "Return"))) + { + _item_new(sd, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL); + sd->n_str = 0; + } +} + +static void +_callbacks_register(Evas_Object *obj) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + elm_layout_signal_callback_add + (obj, "mouse,clicked,1", "*", _mouse_clicked_signal_cb, NULL); + + evas_object_event_callback_add + (wd->resize_obj, EVAS_CALLBACK_KEY_DOWN, + _layout_key_down_cb, obj); + + evas_object_event_callback_add + (sd->box, EVAS_CALLBACK_RESIZE, _box_resize_cb, obj); + + evas_object_event_callback_add + (sd->entry, EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj); + evas_object_event_callback_add + (sd->entry, EVAS_CALLBACK_KEY_DOWN, _entry_key_down_cb, obj); + evas_object_event_callback_add + (sd->entry, EVAS_CALLBACK_RESIZE, _entry_resize_cb, obj); + efl_event_callback_array_add(sd->entry, _multi_buttonentry_cb(), obj); +} + +static void +_label_set(Evas_Object *obj, + const char *str) +{ + Evas_Coord width, height; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + if (!str) return; + + eina_stringshare_replace(&sd->label_str, str); + + edje_object_part_text_escaped_set(sd->label, "elm.text", str); + + if (!strlen(str)) + { + sd->label_packed = EINA_FALSE; + elm_box_unpack(sd->box, sd->label); + evas_object_hide(sd->label); + } + else + { + if (sd->label_packed) + elm_box_unpack(sd->box, sd->label); + sd->label_packed = EINA_TRUE; + edje_object_size_min_calc(sd->label, &width, &height); + evas_object_size_hint_min_set(sd->label, width, height); + elm_box_pack_start(sd->box, sd->label); + evas_object_show(sd->label); + } + + _view_update(sd); +} + +static void +_guide_text_set(Evas_Object *obj, + const char *str) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + if (!str) return; + + eina_stringshare_replace(&sd->guide_text_str, str); + if (sd->guide_text == NULL) + sd->guide_text = edje_object_add(evas_object_evas_get(obj)); + + if (sd->guide_text) + { + elm_widget_theme_object_set(obj, sd->guide_text, "multibuttonentry", + "guidetext", elm_widget_style_get(obj)); + evas_object_size_hint_weight_set + (sd->guide_text, 0.0, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set + (sd->guide_text, EVAS_HINT_FILL, EVAS_HINT_FILL); + edje_object_part_text_escaped_set(sd->guide_text, "elm.text", str); + _view_update(sd); + } +} + +static Elm_Multibuttonentry_Item_Filter * +_filter_new(Elm_Multibuttonentry_Item_Filter_Cb func, + void *data) +{ + Elm_Multibuttonentry_Item_Filter *item_filter = + ELM_NEW(Elm_Multibuttonentry_Item_Filter); + if (!item_filter) return NULL; + + item_filter->callback_func = func; + item_filter->data = data; + + return item_filter; +} + +static void +_filter_free(Elm_Multibuttonentry_Item_Filter *item_filter) +{ + free(item_filter); +} + +static Eina_Bool +_box_min_size_calculate(Evas_Object *box, + Evas_Object_Box_Data *priv, + int *line_height, + void *data EINA_UNUSED) +{ + Evas_Coord mnw, mnh, w, minw, minh = 0, linew = 0, lineh = 0; + int line_num; + Eina_List *l; + Evas_Object_Box_Option *opt; + + evas_object_geometry_get(box, NULL, NULL, &w, NULL); + efl_gfx_size_hint_combined_min_get(box, &minw, NULL); + + if (!w) return EINA_FALSE; + + line_num = 1; + EINA_LIST_FOREACH(priv->children, l, opt) + { + efl_gfx_size_hint_combined_min_get(opt->obj, &mnw, &mnh); + + linew += mnw; + if (lineh < mnh) lineh = mnh; + + if (linew > w) + { + linew = mnw; + line_num++; + } + + if ((linew != 0) && (l != eina_list_last(priv->children))) + linew += priv->pad.h; + } + minh = lineh * line_num + (line_num - 1) * priv->pad.v; + + evas_object_size_hint_min_set(box, minw, minh); + *line_height = lineh; + + return EINA_TRUE; +} + +static void +_box_layout_cb(Evas_Object *o, + Evas_Object_Box_Data *priv, + void *data) +{ + Evas_Coord x, y, w, h, xx, yy; + Evas_Coord minw, minh, linew = 0, lineh = 0; + Evas_Object_Box_Option *opt; + const Eina_List *l, *l_next; + Evas_Object *obj; + double ax, ay; + Eina_Bool rtl; + + if (!_box_min_size_calculate(o, priv, &lineh, data)) return; + + evas_object_geometry_get(o, &x, &y, &w, &h); + + efl_gfx_size_hint_combined_min_get(o, &minw, &minh); + evas_object_size_hint_align_get(o, &ax, &ay); + + rtl = efl_ui_mirrored_get(data); + if (rtl) ax = 1.0 - ax; + + if (w < minw) + { + x = x + ((w - minw) * (1.0 - ax)); + w = minw; + } + if (h < minh) + { + y = y + ((h - minh) * (1.0 - ay)); + h = minh; + } + + xx = x; + yy = y; + + EINA_LIST_FOREACH_SAFE(priv->children, l, l_next, opt) + { + Evas_Coord mnw, mnh; + Evas_Coord ww, hh, ow, oh; + double wx, wy; + int fw, fh; + + obj = opt->obj; + evas_object_size_hint_align_get(obj, &ax, &ay); + evas_object_size_hint_weight_get(obj, &wx, &wy); + efl_gfx_size_hint_combined_min_get(obj, &mnw, &mnh); + + fw = fh = EINA_FALSE; + if (EINA_DBL_EQ(ax, -1)) {fw = 1; ax = 0.5; } + if (EINA_DBL_EQ(ay, -1)) {fh = 1; ay = 0.5; } + if (rtl) ax = 1.0 - ax; + + ww = mnw; + if (!EINA_DBL_EQ(wx, 0)) + { + if (ww <= w - linew) ww = w - linew; + else ww = w; + } + hh = lineh; + + ow = mnw; + if (fw) ow = ww; + oh = mnh; + if (fh) oh = hh; + + linew += ww; + if (linew > w && l != priv->children) + { + xx = x; + yy += hh; + yy += priv->pad.v; + linew = ww; + } + + evas_object_move(obj, + ((!rtl) ? (xx) : (x + (w - (xx - x) - ww))) + + (Evas_Coord)(((double)(ww - ow)) * ax), + yy + (Evas_Coord)(((double)(hh - oh)) * ay)); + evas_object_resize(obj, ow, oh); + + xx += ww; + xx += priv->pad.h; + + if (linew > w) + { + opt = eina_list_data_get(l_next); + if (opt && opt->obj && efl_isa(opt->obj, ELM_ENTRY_CLASS)) + { + xx = x; + yy += hh; + yy += priv->pad.v; + linew = 0; + } + } + if ((linew != 0) && (l != eina_list_last(priv->children))) + linew += priv->pad.h; + } +} + +static void +_view_init(Evas_Object *obj, Efl_Ui_Multibuttonentry_Data *sd) +{ + const char *str; + double pad_scale; + int hpad = 0, vpad = 0; + + sd->box = elm_box_add(obj); + + if (!sd->box) return; + + str = elm_layout_data_get(obj, "horizontal_pad"); + if (str) hpad = atoi(str); + str = elm_layout_data_get(obj, "vertical_pad"); + if (str) vpad = atoi(str); + pad_scale = efl_ui_scale_get(obj) * elm_config_scale_get() + / edje_object_base_scale_get(elm_layout_edje_get(obj)); + elm_box_padding_set(sd->box, (hpad * pad_scale), (vpad * pad_scale)); + + elm_box_layout_set(sd->box, _box_layout_cb, obj, NULL); + elm_box_homogeneous_set(sd->box, EINA_FALSE); + elm_layout_content_set(obj, "box.swallow", sd->box); + + sd->label = edje_object_add(evas_object_evas_get(obj)); + if (!sd->label) return; + elm_widget_theme_object_set + (obj, sd->label, "multibuttonentry", "label", + elm_widget_style_get(obj)); + + // ACCESS + if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) + _access_multibuttonentry_label_register(obj, EINA_TRUE); + + sd->entry = efl_add(EFL_UI_TEXT_CLASS, sd->box, + efl_text_multiline_set(efl_added, EINA_FALSE), + efl_text_set(efl_added, ""), + efl_ui_text_cnp_mode_set(efl_added, EINA_FALSE), + efl_ui_text_input_panel_enabled_set(efl_added, EINA_FALSE), + efl_ui_text_interactive_editable_set(efl_added, EINA_TRUE), + efl_composite_attach(obj, efl_added)); + + evas_object_size_hint_min_set(sd->entry, MIN_W_ENTRY, 0); + evas_object_size_hint_weight_set + (sd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(sd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL); + + elm_box_pack_end(sd->box, sd->entry); + + sd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY; + + { + Evas_Coord button_min_width = 0, button_min_height = 0; + + sd->end = edje_object_add(evas_object_evas_get(obj)); + if (!sd->end) return; + elm_widget_theme_object_set + (obj, sd->end, "multibuttonentry", "closedbutton", + elm_widget_style_get(obj)); + + edje_object_size_min_calc(sd->end, &button_min_width, &button_min_height); + elm_coords_finger_size_adjust(1, &button_min_width, 1, &button_min_height); + evas_object_size_hint_min_set(sd->end, button_min_width, button_min_height); + elm_widget_sub_object_add(obj, sd->end); + } +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_text_set(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd EINA_UNUSED, const char *part, const char *label) +{ + Eina_Bool int_ret = EINA_TRUE; + + if (!part || !strcmp(part, "default") || !strcmp(part, "elm.text")) + { + if (label) _label_set(obj, label); + int_ret = EINA_TRUE; + } + else if (!strcmp(part, "guide")) + { + if (label) _guide_text_set(obj, label); + int_ret = EINA_TRUE; + } + else + efl_text_set(efl_part(efl_super(obj, MY_CLASS), part), label); + + return int_ret; +} + +EOLIAN static const char* +_efl_ui_multibuttonentry_text_get(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd, const char *part) +{ + const char *text = NULL; + + if (!part || !strcmp(part, "default")) + { + text = sd->label_str; + } + else if (!strcmp(part, "guide")) + { + text = sd->guide_text_str; + } + else + text = efl_text_get(efl_part(efl_super(obj, MY_CLASS), part)); + + return text; +} + +static char * +_access_info_cb(void *data EINA_UNUSED, Evas_Object *obj) +{ + char *ret; + Eina_Strbuf *buf; + Eina_List *l = NULL; + Elm_Object_Item *eo_item; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); + + if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) + { + if (sd->guide_text_str) return strdup(sd->guide_text_str); + return NULL; + } + + buf = eina_strbuf_new(); + + if (sd->label_str) eina_strbuf_append(buf, sd->label_str); + + int invisible_its = 0; + EINA_LIST_FOREACH (sd->items, l, eo_item) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + if (item->visible) + eina_strbuf_append_printf(buf, ", %s", + edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), "elm.btn.text")); + else + invisible_its++; + } + + if (invisible_its) + eina_strbuf_append_printf(buf, ", and %d more", invisible_its); + + ret = eina_strbuf_string_steal(buf); + eina_strbuf_free(buf); + return ret; +} + +EOLIAN static void +_efl_ui_multibuttonentry_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Multibuttonentry_Data *priv) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + + efl_canvas_group_add(efl_super(obj, MY_CLASS)); + elm_widget_sub_object_parent_add(obj); + + if (!elm_layout_theme_set + (obj, "multibuttonentry", "base", elm_widget_style_get(obj))) + CRI("Failed to set layout!"); + + elm_widget_can_focus_set(obj, EINA_TRUE); + + priv->last_it_select = EINA_TRUE; + priv->editable = EINA_TRUE; + priv->parent = obj; + priv->format_func = _format_count; + priv->style = "defualt"; + + _view_init(obj, priv); + _callbacks_register(obj); + + // ACCESS + _elm_access_object_register(obj, wd->resize_obj); + _elm_access_text_set + (_elm_access_info_get(obj), ELM_ACCESS_TYPE, E_("multi button entry")); + _elm_access_callback_set + (_elm_access_info_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL); +} + +EOLIAN static void +_efl_ui_multibuttonentry_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd) +{ + Eina_List *l; + Elm_Object_Item *eo_item; + Elm_Multibuttonentry_Item_Filter *_item_filter = NULL; + + EINA_LIST_FOREACH(sd->items, l, eo_item) + efl_del(eo_item); + + sd->items = eina_list_free(sd->items); + + sd->selected_it = NULL; + sd->focused_it = NULL; + + eina_stringshare_del(sd->label_str); + eina_stringshare_del(sd->guide_text_str); + evas_object_del(sd->entry); + evas_object_del(sd->label); + evas_object_del(sd->guide_text); + evas_object_del(sd->end); + ecore_timer_del(sd->longpress_timer); + + EINA_LIST_FREE(sd->filter_list, _item_filter) + _filter_free(_item_filter); + + efl_canvas_group_del(efl_super(obj, MY_CLASS)); +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd EINA_UNUSED) +{ + return _efl_ui_multibuttonentry_smart_focus_direction_enable; +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_elm_widget_focus_direction(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight) +{ + Eina_Bool ret; + Eina_List *items = NULL; + + items = eina_list_append(items, sd->box); + + ret = elm_widget_focus_list_direction_get + (obj, base, items, eina_list_data_get, degree, direction, direction_item, weight); + eina_list_free(items); + + return ret; +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd EINA_UNUSED) +{ + return _efl_ui_multibuttonentry_smart_focus_next_enable; +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_elm_widget_focus_next(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) +{ + Eina_Bool int_ret = EINA_FALSE; + + Eina_List *items = NULL; + Eina_List *l = NULL; + Elm_Object_Item *eo_item; + Evas_Object *ao; + Evas_Object *po; + + if (!elm_widget_focus_get(obj)) + { + *next = (Evas_Object *)obj; + return EINA_TRUE; + } + + if (sd->label) + { + po = (Evas_Object *)edje_object_part_object_get(sd->label, "elm.text"); + ao = evas_object_data_get(po, "_part_access_obj"); + int_ret = elm_widget_focus_get(ao); + items = eina_list_append(items, ao); + } + + EINA_LIST_FOREACH (sd->items, l, eo_item) + { + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); + po = (Evas_Object *)edje_object_part_object_get + (elm_layout_edje_get(VIEW(item)), "elm.btn.text"); + ao = evas_object_data_get(po, "_part_access_obj"); + int_ret = int_ret || elm_widget_focus_get(ao); + items = eina_list_append(items, ao); + } + + if (sd->entry) + { + int_ret = int_ret || elm_widget_focus_get(sd->entry); + /* elm_widget_list_focus_liset_next_get() check parent of item + because parent sd->entry is not multibuttnentry but sd->box + so append sd->box instead of sd->entry, is this proper? */ + items = eina_list_append(items, sd->box); + } + + if (int_ret) + return elm_widget_focus_list_next_get + (obj, items, eina_list_data_get, dir, next, next_item); + + return EINA_FALSE; +} + +static void +_access_obj_process(Evas_Object *obj, Eina_Bool is_access) +{ + Eina_List *l; + Elm_Object_Item *it; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); + + /* label */ + _access_multibuttonentry_label_register(obj, is_access); + + /* buttons */ + EINA_LIST_FOREACH(sd->items, l, it) + _access_multibuttonentry_item_register(obj, it, is_access); +} + +EOLIAN static void +_efl_ui_multibuttonentry_elm_widget_on_access_update(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd EINA_UNUSED, Eina_Bool acs) +{ + _efl_ui_multibuttonentry_smart_focus_next_enable = acs; + _access_obj_process(obj, _efl_ui_multibuttonentry_smart_focus_next_enable); +} + +EAPI Evas_Object * +elm_multibuttonentry_add(Evas_Object *parent) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); + return efl_add(MY_CLASS, parent, efl_canvas_object_legacy_ctor(efl_added)); +} + +EOLIAN static Eo * +_efl_ui_multibuttonentry_efl_object_constructor(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd EINA_UNUSED) +{ + obj = efl_constructor(efl_super(obj, MY_CLASS)); + efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); + evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); + elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_PANEL); + + return obj; +} + +EOLIAN static Evas_Object* +_efl_ui_multibuttonentry_entry_get(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + return sd->entry; +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_expanded_get(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + return sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK ? + EINA_FALSE : EINA_TRUE; +} + +EOLIAN static void +_efl_ui_multibuttonentry_format_function_set(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, Efl_Ui_Multibuttonentry_Format_Cb f_func, const void *data) +{ + sd->format_func = f_func; + if (!sd->format_func) sd->format_func = _format_count; + + sd->format_func_data = data; + + _view_update(sd); +} + +EOLIAN static void +_efl_ui_multibuttonentry_expanded_set(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd, Eina_Bool expanded) +{ + if (((sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) ? + EINA_FALSE : EINA_TRUE) == expanded) return; + + if (expanded) + _shrink_mode_set(obj, EINA_FALSE); + else + _shrink_mode_set(obj, EINA_TRUE); +} + +EOLIAN static void +_efl_ui_multibuttonentry_editable_set(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, Eina_Bool editable) +{ + editable = !!editable; + if (sd->editable == editable) return; + sd->editable = editable; + + if (sd->editable && (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK)) + { + if (!strncmp(sd->style, "entry_separate", 14)) + elm_layout_content_set(obj, "entry.swallow", sd->entry); + else + elm_box_pack_end(sd->box, sd->entry); + + evas_object_show(sd->entry); + } + else + { + if (!strncmp(sd->style, "entry_separate", 14)) + elm_layout_content_unset(obj, "entry.swallow"); + else + elm_box_unpack(sd->box, sd->entry); + evas_object_hide(sd->entry); + } +} + +EOLIAN static Eina_Bool +_efl_ui_multibuttonentry_editable_get(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + return sd->editable; +} + +EOLIAN static Elm_Object_Item* +_efl_ui_multibuttonentry_item_prepend(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, const char *label, Evas_Smart_Cb func, void *data) +{ + return _item_new(sd, label, MULTIBUTTONENTRY_POS_START, NULL, func, data); +} + +EOLIAN static Elm_Object_Item* +_efl_ui_multibuttonentry_item_append(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, const char *label, Evas_Smart_Cb func, void *data) +{ + return _item_new(sd, label, MULTIBUTTONENTRY_POS_END, NULL, func, data); +} + +EOLIAN static Elm_Object_Item* +_efl_ui_multibuttonentry_item_insert_before(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, Elm_Object_Item *before, const char *label, Evas_Smart_Cb func, void *data) +{ + return _item_new(sd, label, MULTIBUTTONENTRY_POS_BEFORE, before, func, data); +} + +EOLIAN static Elm_Object_Item* +_efl_ui_multibuttonentry_item_insert_after(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, Elm_Object_Item *after, const char *label, Evas_Smart_Cb func, void *data) +{ + return _item_new(sd, label, MULTIBUTTONENTRY_POS_AFTER, after, func, data); +} + +EOLIAN static const Eina_List* +_efl_ui_multibuttonentry_items_get(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + return sd->items; +} + +EOLIAN static Elm_Object_Item* +_efl_ui_multibuttonentry_first_item_get(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + return eina_list_data_get(sd->items); +} + +EOLIAN static Elm_Object_Item* +_efl_ui_multibuttonentry_last_item_get(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + return eina_list_data_get(eina_list_last(sd->items)); +} + +EOLIAN static Elm_Object_Item* +_efl_ui_multibuttonentry_selected_item_get(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + return EO_OBJ(sd->selected_it); +} + +EOLIAN static void +_elm_multibuttonentry_item_selected_set(Eo *eo_item EINA_UNUSED, + Elm_Multibuttonentry_Item_Data *item, + Eina_Bool selected) +{ + if (selected) _item_select(WIDGET(item), item); + else _item_select(WIDGET(item), NULL); +} + +EOLIAN static Eina_Bool +_elm_multibuttonentry_item_selected_get(Eo *eo_item, + Elm_Multibuttonentry_Item_Data *item) +{ + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(item), sd, EINA_FALSE); + if (!eo_item) return EINA_FALSE; + if (EO_OBJ(sd->selected_it) == eo_item) + return EINA_TRUE; + + return EINA_FALSE; +} + +EOLIAN static void +_efl_ui_multibuttonentry_clear(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd) +{ + while (sd->items) + elm_wdg_item_del(eina_list_data_get(sd->items)); + + sd->selected_it = NULL; + _view_update(sd); +} + +EOLIAN static Elm_Object_Item * +_elm_multibuttonentry_item_prev_get(const Eo *eo_it, + Elm_Multibuttonentry_Item_Data *it) +{ + Eina_List *l; + Elm_Object_Item *eo_temp_it; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, NULL); + + EINA_LIST_FOREACH(sd->items, l, eo_temp_it) + { + if (eo_temp_it == eo_it) + { + l = eina_list_prev(l); + if (!l) return NULL; + return eina_list_data_get(l); + } + } + return NULL; +} + +EOLIAN static Elm_Object_Item * +_elm_multibuttonentry_item_next_get(const Eo *eo_it, + Elm_Multibuttonentry_Item_Data *it) +{ + Eina_List *l; + Elm_Object_Item *eo_temp_it; + + EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, NULL); + + EINA_LIST_FOREACH(sd->items, l, eo_temp_it) + { + if (eo_temp_it == eo_it) + { + l = eina_list_next(l); + if (!l) return NULL; + return eina_list_data_get(l); + } + } + return NULL; +} + +EOLIAN static void +_elm_multibuttonentry_item_elm_widget_item_disable(Eo *eo_it, Elm_Multibuttonentry_Item_Data *it) +{ + const char* emission; + if (elm_wdg_item_disabled_get(eo_it)) + emission = "elm,state,disabled"; + else + emission = "elm,state,enabled"; + + elm_layout_signal_emit(VIEW(it), emission, "elm"); +} + +EINA_DEPRECATED EAPI void * +elm_multibuttonentry_item_data_get(const Elm_Object_Item *it) +{ + return (void *)WIDGET_ITEM_DATA_GET(it); +} + +EINA_DEPRECATED EAPI void +elm_multibuttonentry_item_data_set(Elm_Object_Item *it, + void *data) +{ + WIDGET_ITEM_DATA_SET(it, data); +} + +EOLIAN static void +_efl_ui_multibuttonentry_item_filter_append(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data) +{ + Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL; + Elm_Multibuttonentry_Item_Filter *_item_filter = NULL; + Eina_List *l; + + EINA_SAFETY_ON_NULL_RETURN(func); + + EINA_LIST_FOREACH(sd->filter_list, l, _item_filter) + { + if (_item_filter && ((_item_filter->callback_func == func) + && (_item_filter->data == data))) + { + INF("Already Registered this item filter!!!!\n"); + return; + } + } + new_item_filter = _filter_new(func, data); + if (!new_item_filter) return; + + sd->filter_list = eina_list_append(sd->filter_list, new_item_filter); +} + +EOLIAN static void +_efl_ui_multibuttonentry_item_filter_prepend(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data) +{ + Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL; + Elm_Multibuttonentry_Item_Filter *_item_filter = NULL; + Eina_List *l; + + EINA_SAFETY_ON_NULL_RETURN(func); + + new_item_filter = _filter_new(func, data); + if (!new_item_filter) return; + + EINA_LIST_FOREACH(sd->filter_list, l, _item_filter) + { + if (_item_filter && ((_item_filter->callback_func == func) + && (_item_filter->data == data))) + { + INF("Already Registered this item filter!!!!\n"); + _filter_free(new_item_filter); + return; + } + } + sd->filter_list = eina_list_prepend(sd->filter_list, new_item_filter); +} + +EOLIAN static void +_efl_ui_multibuttonentry_item_filter_remove(Eo *obj EINA_UNUSED, Efl_Ui_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data) +{ + Eina_List *l; + Elm_Multibuttonentry_Item_Filter *item_filter; + + EINA_SAFETY_ON_NULL_RETURN(func); + + EINA_LIST_FOREACH(sd->filter_list, l, item_filter) + { + if ((item_filter->callback_func == func) + && ((!data) || (item_filter->data == data))) + { + sd->filter_list = eina_list_remove_list(sd->filter_list, l); + _filter_free(item_filter); + return; + } + } +} + +static void +_efl_ui_multibuttonentry_class_constructor(Efl_Class *klass) +{ + evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); + + if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF) + _efl_ui_multibuttonentry_smart_focus_next_enable = EINA_TRUE; +} + +EOLIAN static Eina_List* +_efl_ui_multibuttonentry_elm_interface_atspi_accessible_children_get(Eo *obj, Efl_Ui_Multibuttonentry_Data *sd) +{ + Eina_List *ret; + ret = elm_interface_atspi_accessible_children_get(efl_super(obj, EFL_UI_MULTIBUTTONENTRY_CLASS)); + return eina_list_merge(eina_list_clone(sd->items), ret); +} + +EOLIAN static const char* +_elm_multibuttonentry_item_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Multibuttonentry_Item_Data *item) +{ + const char *ret; + ret = elm_interface_atspi_accessible_name_get(efl_super(obj, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); + if (ret) return ret; + + const char *txt = elm_object_part_text_get(VIEW(item), "elm.btn.text"); + return txt; +} + +EOLIAN static Elm_Atspi_State_Set +_elm_multibuttonentry_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_it, Elm_Multibuttonentry_Item_Data *sd EINA_UNUSED) +{ + Elm_Atspi_State_Set ret; + Eina_Bool sel; + + ret = elm_interface_atspi_accessible_state_set_get(efl_super(eo_it, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); + + sel = elm_obj_multibuttonentry_item_selected_get(eo_it); + + STATE_TYPE_SET(ret, ELM_ATSPI_STATE_EDITABLE); + + if (sel) + STATE_TYPE_SET(ret, ELM_ATSPI_STATE_CHECKED); + + return ret; +} + +static Eina_Bool +_key_action_activate(Eo *obj, const char *params EINA_UNUSED) +{ + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it); + elm_layout_signal_emit(VIEW(it), "mouse,clicked,1", "elm"); + return EINA_TRUE; +} + +static Eina_Bool +_key_action_delete(Eo *obj, const char *params EINA_UNUSED) +{ + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it); + elm_layout_signal_emit(VIEW(it), "elm,deleted", "elm"); + return EINA_TRUE; +} + +static Eina_Bool +_key_action_longpress(Eo *obj, const char *params EINA_UNUSED) +{ + ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it); + efl_event_callback_legacy_call + (WIDGET(it), EFL_UI_MULTIBUTTONENTRY_EVENT_ITEM_LONGPRESSED, obj); + return EINA_TRUE; +} + +EOLIAN const Elm_Atspi_Action * +_elm_multibuttonentry_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Item_Data *pd EINA_UNUSED) +{ + static Elm_Atspi_Action atspi_actions[] = { + { "activate", NULL, NULL, _key_action_activate }, + { "delete", NULL, NULL, _key_action_delete}, + { "longpress", NULL, NULL, _key_action_longpress}, + { NULL, NULL, NULL, NULL} + }; + return &atspi_actions[0]; +} + +/* Efl.Part begin */ + +ELM_PART_OVERRIDE(efl_ui_multibuttonentry, EFL_UI_MULTIBUTTONENTRY, EFL_UI_LAYOUT, Efl_Ui_Multibuttonentry_Data, Elm_Part_Data) +ELM_PART_OVERRIDE_TEXT_SET(efl_ui_multibuttonentry, EFL_UI_MULTIBUTTONENTRY, EFL_UI_LAYOUT, Efl_Ui_Multibuttonentry_Data, Elm_Part_Data) +ELM_PART_OVERRIDE_TEXT_GET(efl_ui_multibuttonentry, EFL_UI_MULTIBUTTONENTRY, EFL_UI_LAYOUT, Efl_Ui_Multibuttonentry_Data, Elm_Part_Data) +#include "efl_ui_multibuttonentry_internal_part.eo.c" + +/* Efl.Part end */ +/* Internal EO APIs and hidden overrides */ + +#define EFL_UI_MULTIBUTTONENTRY_EXTRA_OPS \ + ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_multibuttonentry), \ + EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_multibuttonentry) + +#include "elm_multibuttonentry_item.eo.c" +#include "efl_ui_multibuttonentry.eo.c" diff --git a/src/lib/elementary/efl_ui_multibuttonentry.eo b/src/lib/elementary/efl_ui_multibuttonentry.eo new file mode 100644 index 0000000000..2396393e95 --- /dev/null +++ b/src/lib/elementary/efl_ui_multibuttonentry.eo @@ -0,0 +1,201 @@ +type Elm_Multibuttonentry_Item_Filter_Cb: __undefined_type; [[Elementary multibuttonentry item filter callback type]] +type Efl_Ui_Multibuttonentry_Format_Cb: __undefined_type; [[Elementary multibuttonentry format callback type]] + +class Efl.Ui.Multibuttonentry (Efl.Ui.Layout) +{ + [[Elementary multibuttonentry class]] + legacy_prefix: elm_multibuttonentry; + methods { + @property editable { + [[Control if the multibuttonentry is to be editable or not. + + @since 1.7]] + set { + } + get { + } + values { + editable: bool; [[If $true, user can add/delete item in multibuttonentry, if not, the multibuttonentry is non-editable.]] + } + } + @property expanded { + [[Control the multibuttonentry to expanded state. + + In expanded state, the complete entry will be displayed. + Otherwise, only single line of the entry will be displayed.]] + set { + } + get { + } + values { + expanded: bool; [[The value of expanded state. Set this to $true for expanded state. Set + this to $false for single line state.]] + } + } + @property format_function { + set { + [[Set a function to format the string that will be used to display the hidden items counter. + + If $format_function is $NULL, the default format will be used, + which is $"... + %d". + + @since 1.9]] + } + values { + format_function: Efl_Ui_Multibuttonentry_Format_Cb @nullable; [[Format_function The actual format function]] + data: const(void_ptr) @optional; [[Data User data to passed to $format_function]] + } + } + @property items { + get { + [[Get a list of items in the multibuttonentry]] + + return: const(list); [[The list of items, or NULL if none]] + } + } + @property first_item { + get { + [[Get the first item in the multibuttonentry]] + + return: Elm.Widget.Item; [[The first item, or NULL if none]] + } + } + @property last_item { + get { + [[Get the last item in the multibuttonentry]] + + return: Elm.Widget.Item; [[The last item, or NULL if none]] + } + } + @property entry { + get { + [[Get the entry of the multibuttonentry object]] + + return: Efl.Canvas.Object; [[The entry object, or NULL if none]] + } + } + @property selected_item { + get { + [[Get the selected item in the multibuttonentry]] + + return: Elm.Widget.Item; [[The selected item, or NULL if none]] + } + } + item_prepend { + [[Prepend a new item to the multibuttonentry + + See @Elm.Widget.Item.del to delete the item.]] + + return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] + params { + @in label: string; [[The label of new item]] + @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] + @in data: void_ptr @optional; [[The pointer to the data to be attached]] + } + } + clear { + [[Remove all items in the multibuttonentry.]] + + } + item_filter_remove { + [[Remove a filter from the list + + Removes the given callback from the filter list. See elm_multibuttonentry_item_filter_append() + for more information.]] + + params { + @in func: Elm_Multibuttonentry_Item_Filter_Cb; [[The filter function to remove]] + @in data: void_ptr; [[The user data passed when adding the function]] + } + } + item_insert_before { + [[Add a new item to the multibuttonentry before the indicated object reference. + + See @Elm.Widget.Item.del to delete the item.]] + + return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] + params { + @in before: Elm.Widget.Item; [[The item before which to add it]] + @in label: string; [[The label of new item]] + @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] + @in data: void_ptr @optional; [[The pointer to the data to be attached]] + } + } + item_append { + [[Append a new item to the multibuttonentry + + See @Elm.Widget.Item.del to delete the item.]] + + return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] + params { + @in label: string; [[The label of new item]] + @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] + @in data: void_ptr @optional; [[The pointer to the data to be attached]] + } + } + item_filter_prepend { + [[Prepend a filter function for text inserted in the Multibuttonentry + + Prepend the given callback to the list. See elm_multibuttonentry_item_filter_append() + for more information]] + params { + @in func: Elm_Multibuttonentry_Item_Filter_Cb; [[The function to use as text filter]] + @in data: void_ptr; [[User data to pass to $func]] + } + } + item_filter_append { + [[Append an item filter function for text inserted in the Multibuttonentry + + Append the given callback to the list. This functions will be called + whenever any text is inserted into the Multibuttonentry, with the text to be inserted + as a parameter. The callback function is free to alter the text in any way + it wants, but it must remember to free the given pointer and update it. + If the new text is to be discarded, the function can free it and set it text + parameter to NULL. This will also prevent any following filters from being + called.]] + + params { + @in func: Elm_Multibuttonentry_Item_Filter_Cb; [[The function to use as item filter]] + @in data: void_ptr; [[User data to pass to $func]] + } + } + item_insert_after { + [[Add a new item to the multibuttonentry after the indicated object + + See @Elm.Widget.Item.del to delete the item.]] + + return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] + params { + @in after: Elm.Widget.Item; [[The item after which to add it]] + @in label: string; [[The label of new item]] + @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] + @in data: void_ptr @optional; [[The pointer to the data to be attached]] + } + } + } + implements { + class.constructor; + Efl.Object.constructor; + Elm.Widget.theme_apply; + Elm.Widget.focus_next_manager_is; + Elm.Widget.focus_direction_manager_is; + Elm.Widget.on_access_update; + Elm.Widget.focus_direction; + Elm.Widget.focus_next; + Elm.Widget.on_focus; + Elm.Widget.translate; + Elm.Widget.widget_event; + Elm.Interface.Atspi_Accessible.children { get; } + Efl.Part.part; + } + events { + item,selected; [[Called when item was selected]] + item,added; [[Called when item was added]] + item,deleted; [[Called when item was deleted]] + item,clicked; [[Called when item was clicked]] + item,longpressed; [[Called when item got a longpress]] + expanded; [[Called when expanded]] + contracted; [[Called when contracted]] + expand,state,changed; [[Called when expanded state changed]] + } +} diff --git a/src/lib/elementary/efl_ui_multibuttonentry.h b/src/lib/elementary/efl_ui_multibuttonentry.h new file mode 100644 index 0000000000..3c76aa76c7 --- /dev/null +++ b/src/lib/elementary/efl_ui_multibuttonentry.h @@ -0,0 +1,69 @@ +/** + * @defgroup efl_ui_multibuttonentry + * @ingroup Elementary + * + * @image html multibuttonentry_inheritance_tree.png + * @image latex multibuttonentry_inheritance_tree.eps + * + * A multi-button entry is a widget letting an user enter text and + * each chunk of text managed as a set of buttons. Each text button is + * inserted by pressing the "return" key. If there is no space in the + * current row, a new button is added to the next row. When a text + * button is pressed, it will become focused. Backspace removes the + * focus. When the multi-button entry loses focus, items longer than + * one line are shrunk to one line. + * + * The typical use case of multi-button entry is composing + * emails/messages to a group of addresses, each of which is an item + * that can be clicked for further actions. + * + * This widget inherits from the @ref Layout one, so that all the + * functions acting on it also work for multi-button entry objects (since 1.8). + * + * This widget emits the following signals, besides the ones sent from + * @ref Layout: + * - @c "item,selected" - this is called when an item is selected by + * api, user interaction, and etc. this is also called when a + * user press back space while cursor is on the first field of + * entry. + * - @c "item,added" - when a new multi-button entry item is added. + * - @c "item,deleted" - when a multi-button entry item is deleted. + * - @c "item,clicked" - this is called when an item is clicked by user + * interaction. Both "item,selected" and "item,clicked" are needed. + * - @c "item,longpressed" - when multi-button entry item is pressed for a long time. + * - @c "clicked" - when multi-button entry is clicked. + * - @c "focused" - when multi-button entry is focused. + * - @c "unfocused" - when multi-button entry is unfocused. + * - @c "expanded" - when multi-button entry is expanded. + * - @c "contracted" - when multi-button entry is contracted. + * - @c "expand,state,changed" - when shrink mode state of + * multi-button entry is changed. + * + * Default text parts of the multi-button entry widget that you can use are: + * @li "default" - A label of the multi-button entry + * + * Default text parts of multi-button entry @b items that you can use are: + * @li "default" - A label of the multi-button entry item + * + * Supported elm_object_item common APIs. + * @li @ref elm_object_item_del + * @li @ref elm_object_item_part_text_set + * @li @ref elm_object_item_part_text_get + */ + + +/** + * @addtogroup Multibuttonentry + * @{ + */ + +#include "efl_ui_multibuttonentry_common.h" +#ifdef EFL_EO_API_SUPPORT +#include "efl_ui_multibuttonentry_eo.h" +#endif +#ifndef EFL_NOLEGACY_API_SUPPORT +#include "elc_multibuttonentry_legacy.h" +#endif +/** + * @} + */ diff --git a/src/lib/elementary/efl_ui_multibuttonentry_eo.h b/src/lib/elementary/efl_ui_multibuttonentry_eo.h new file mode 100644 index 0000000000..b6158a8927 --- /dev/null +++ b/src/lib/elementary/efl_ui_multibuttonentry_eo.h @@ -0,0 +1,2 @@ +#include "elm_multibuttonentry_item.eo.h" +#include "efl_ui_multibuttonentry.eo.h" diff --git a/src/lib/elementary/efl_ui_multibuttonentry_internal_part.eo b/src/lib/elementary/efl_ui_multibuttonentry_internal_part.eo new file mode 100644 index 0000000000..097800000b --- /dev/null +++ b/src/lib/elementary/efl_ui_multibuttonentry_internal_part.eo @@ -0,0 +1,9 @@ +class Efl.Ui.Multibuttonentry.Internal.Part (Efl.Ui.Layout.Internal.Part, Efl.Text) +{ + [[Elementary multibuttonentry internal part class]] + data: null; + implements { + Efl.Text.text { set; get; } + } +} + diff --git a/src/lib/elementary/efl_ui_multibuttonentry_private.h b/src/lib/elementary/efl_ui_multibuttonentry_private.h new file mode 100644 index 0000000000..5b7500f7e5 --- /dev/null +++ b/src/lib/elementary/efl_ui_multibuttonentry_private.h @@ -0,0 +1,153 @@ +#ifndef ELM_WIDGET_MULTIBUTTONENTRY_H +#define ELM_WIDGET_MULTIBUTTONENTRY_H + +#include "elm_widget_layout.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-multibuttonentry-class The Elementary Multi Button Entry Class + * + * Elementary, besides having the @ref Multibuttonentry widget, + * exposes its foundation -- the Elementary Multi Button Entry Class -- + * in order to create other widgets which are a multi button entry with + * some more logic on top. + */ + +/** + * Base widget smart data extended with multibuttonentry instance data. + */ + +typedef enum _Multibuttonentry_Pos +{ + MULTIBUTTONENTRY_POS_START, + MULTIBUTTONENTRY_POS_END, + MULTIBUTTONENTRY_POS_BEFORE, + MULTIBUTTONENTRY_POS_AFTER, +} Multibuttonentry_Pos; + +typedef enum _Multibuttonentry_Button_State +{ + MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT, + MULTIBUTTONENTRY_BUTTON_STATE_SELECTED, +} Multibuttonentry_Button_State; + +typedef enum _MultiButtonEntry_Closed_Button_Type +{ + MULTIBUTTONENTRY_CLOSED_IMAGE, + MULTIBUTTONENTRY_CLOSED_LABEL +} MultiButtonEntry_Closed_Button_Type; + +typedef enum _Multibuttonentry_View_State +{ + MULTIBUTTONENTRY_VIEW_NONE, + MULTIBUTTONENTRY_VIEW_GUIDETEXT, + MULTIBUTTONENTRY_VIEW_ENTRY, + MULTIBUTTONENTRY_VIEW_SHRINK +} Multibuttonentry_View_State; + +typedef struct _Multibuttonentry_Item Elm_Multibuttonentry_Item_Data; + +struct _Multibuttonentry_Item +{ + Elm_Widget_Item_Data *base; + + Evas_Coord vw, rw; // vw: visual width, real width + Eina_Bool visible : 1; + Evas_Smart_Cb func; +}; + +typedef struct _Elm_Multibuttonentry_Item_Filter +{ + Elm_Multibuttonentry_Item_Filter_Cb callback_func; + void *data; +} Elm_Multibuttonentry_Item_Filter; + +typedef struct _Efl_Ui_Multibuttonentry_Data + Efl_Ui_Multibuttonentry_Data; +struct _Efl_Ui_Multibuttonentry_Data +{ + Evas_Object *parent; + Evas_Object *box; + Evas_Object *entry; + Evas_Object *label; + Evas_Object *guide_text; + Evas_Object *end; /* used to represent the + * total number of + * invisible buttons */ + + Eina_List *items; + Eina_List *filter_list; + Elm_Multibuttonentry_Item_Data *selected_it; /* selected item */ + Elm_Multibuttonentry_Item_Data *focused_it; + + Efl_Ui_Multibuttonentry_Format_Cb format_func; + const void *format_func_data; + + const char *label_str, *guide_text_str, *style; + + int n_str; + Multibuttonentry_View_State view_state; + + Evas_Coord w_box, h_box; + int shrink; + + Elm_Multibuttonentry_Item_Filter_Cb add_callback; + void *add_callback_data; + + Eina_Bool last_it_select : 1; + Eina_Bool editable : 1; + Eina_Bool focused : 1; + Eina_Bool label_packed : 1; + + Ecore_Timer *longpress_timer; +}; + +/** + * @} + */ + +#define EFL_UI_MULTIBUTTONENTRY_DATA_GET(o, sd) \ + Efl_Ui_Multibuttonentry_Data *sd = efl_data_scope_get(o, EFL_UI_MULTIBUTTONENTRY_CLASS); + +#define EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(o, ptr) \ + EFL_UI_MULTIBUTTONENTRY_DATA_GET(o, ptr); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + CRI("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return; \ + } + +#define EFL_UI_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + Efl_Ui_Multibuttonentry_Data * ptr = efl_data_scope_get(o, EFL_UI_MULTIBUTTONENTRY_CLASS); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + CRI("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return val; \ + } + +#define ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(o, sd) \ + Elm_Multibuttonentry_Item_Data *sd = efl_data_scope_get(o, ELM_MULTIBUTTONENTRY_ITEM_CLASS) + +#define ELM_MULTIBUTTONENTRY_CHECK(obj) \ + if (EINA_UNLIKELY(!efl_isa((obj), ELM_MULTIBUTTONENTRY_CLASS))) \ + return + +#define ELM_MULTIBUTTONENTRY_ITEM_CHECK(it) \ + if (EINA_UNLIKELY(!efl_isa((it->base->eo_obj), ELM_MULTIBUTTONENTRY_ITEM_CLASS))) \ + return + +#define ELM_MULTIBUTTONENTRY_ITEM_CHECK_OR_RETURN(it, ...) \ + if (EINA_UNLIKELY(!efl_isa((it->base->eo_obj), ELM_MULTIBUTTONENTRY_ITEM_CLASS))) \ + return __VA_ARGS__; + +#endif diff --git a/src/lib/elementary/elc_multibuttonentry.c b/src/lib/elementary/elc_multibuttonentry.c deleted file mode 100644 index 8a14381926..0000000000 --- a/src/lib/elementary/elc_multibuttonentry.c +++ /dev/null @@ -1,2161 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "elementary_config.h" -#endif - -#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED -#define ELM_WIDGET_ITEM_PROTECTED -#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED - -#include -#include "elm_priv.h" -#include "elm_widget_multibuttonentry.h" - -#include "elm_multibuttonentry_internal_part.eo.h" -#include "elm_part_helper.h" - -#define MY_CLASS ELM_MULTIBUTTONENTRY_CLASS - -#define MY_CLASS_NAME "Elm_Multibuttonentry" -#define MY_CLASS_NAME_LEGACY "elm_multibuttonentry" - -#define MAX_STR 256 -#define MIN_W_ENTRY 10 - -//widget signals -static const char SIG_ITEM_SELECTED[] = "item,selected"; -static const char SIG_ITEM_ADDED[] = "item,added"; -static const char SIG_ITEM_DELETED[] = "item,deleted"; -static const char SIG_ITEM_CLICKED[] = "item,clicked"; -static const char SIG_ITEM_LONGPRESSED[] = "item,longpressed"; -static const char SIG_CLICKED[] = "clicked"; -static const char SIG_FOCUSED[] = "focused"; -static const char SIG_UNFOCUSED[] = "unfocused"; -static const char SIG_EXPANDED[] = "expanded"; -static const char SIG_CONTRACTED[] = "contracted"; -static const char SIG_EXPAND_STATE_CHANGED[] = "expand,state,changed"; -static const Evas_Smart_Cb_Description _smart_callbacks[] = { - {SIG_ITEM_SELECTED, ""}, - {SIG_ITEM_ADDED, ""}, - {SIG_ITEM_DELETED, ""}, - {SIG_ITEM_CLICKED, ""}, - {SIG_ITEM_LONGPRESSED, ""}, - {SIG_CLICKED, ""}, - {SIG_FOCUSED, ""}, - {SIG_UNFOCUSED, ""}, - {SIG_EXPANDED, ""}, - {SIG_CONTRACTED, ""}, - {SIG_EXPAND_STATE_CHANGED, ""}, - {NULL, NULL} -}; - -static Eina_Bool _elm_multibuttonentry_smart_focus_next_enable = EINA_FALSE; -static Eina_Bool _elm_multibuttonentry_smart_focus_direction_enable = EINA_TRUE; - -static void _entry_changed_cb(void *data, const Efl_Event *event); -static void _entry_focus_in_cb(void *data, const Efl_Event *event); -static void _entry_focus_out_cb(void *data, const Efl_Event *event); -static void _entry_clicked_cb(void *data, const Efl_Event *event); - -EFL_CALLBACKS_ARRAY_DEFINE(_multi_buttonentry_cb, - { ELM_ENTRY_EVENT_CHANGED, _entry_changed_cb }, - { ELM_WIDGET_EVENT_FOCUSED, _entry_focus_in_cb }, - { ELM_WIDGET_EVENT_UNFOCUSED, _entry_focus_out_cb }, - { EFL_UI_EVENT_CLICKED, _entry_clicked_cb } -); - -EOLIAN static void -_elm_multibuttonentry_elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - Elm_Object_Item *it; - Eina_List *l; - - EINA_LIST_FOREACH(sd->items, l, it) - elm_wdg_item_translate(it); - - elm_obj_widget_translate(efl_super(obj, MY_CLASS)); -} - -static char * -_format_count(int count, void *data EINA_UNUSED) -{ - char buf[32]; - - if (!snprintf(buf, sizeof(buf), "+%d", count)) return NULL; - return strdup(buf); -} - -EOLIAN static Efl_Ui_Theme_Apply -_elm_multibuttonentry_elm_widget_theme_apply(Eo *obj, Elm_Multibuttonentry_Data *sd) -{ - const char *str; - int hpad = 0, vpad = 0; - Eina_List *l; - Elm_Object_Item *eo_item; - double pad_scale; - - Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED; - int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); - if (!int_ret) return EFL_UI_THEME_APPLY_FAILED; - - str = elm_layout_data_get(obj, "horizontal_pad"); - if (str) hpad = atoi(str); - str = elm_layout_data_get(obj, "vertical_pad"); - if (str) vpad = atoi(str); - pad_scale = efl_ui_scale_get(obj) * elm_config_scale_get() - / edje_object_base_scale_get(elm_layout_edje_get(obj)); - elm_box_padding_set(sd->box, (hpad * pad_scale), (vpad * pad_scale)); - - EINA_LIST_FOREACH(sd->items, l, eo_item) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - if (VIEW(item)) - if (!elm_layout_theme_set - (VIEW(item), "multibuttonentry", "btn", elm_widget_style_get(obj))) - CRI("Failed to set layout!"); - } - - elm_widget_theme_object_set - (obj, sd->label, "multibuttonentry", "label", - elm_widget_style_get(obj)); - elm_widget_theme_object_set - (obj, sd->end, "multibuttonentry", "closedbutton", - elm_widget_style_get(obj)); - elm_widget_theme_object_set - (obj,sd->guide_text, "multibuttonentry", "guidetext", - elm_widget_style_get(obj)); - - elm_layout_sizing_eval(obj); - - return int_ret; -} - -static void -_visual_guide_text_set(Evas_Object *obj) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - elm_box_unpack(sd->box, sd->guide_text); - elm_box_unpack(sd->box, sd->entry); - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) return; - - if (!elm_widget_focus_get(obj)) - elm_object_focus_set(sd->entry, EINA_FALSE); - - if ((!eina_list_count(sd->items)) && sd->guide_text - && (!elm_widget_focus_get(obj)) && (!sd->n_str)) - { - evas_object_hide(sd->entry); - elm_box_pack_end(sd->box, sd->guide_text); - evas_object_show(sd->guide_text); - sd->view_state = MULTIBUTTONENTRY_VIEW_GUIDETEXT; - } - else - { - evas_object_hide(sd->guide_text); - - if (sd->editable) - { - elm_box_pack_end(sd->box, sd->entry); - evas_object_show(sd->entry); - if (elm_widget_focus_get(obj)) - { - if (!sd->selected_it) - elm_object_focus_set(sd->entry, EINA_TRUE); - } - } - sd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY; - } -} - -static void -_shrink_mode_set(Evas_Object *obj, - Eina_Bool shrink) -{ - int count; - Eina_List *l; - Elm_Object_Item *eo_item; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - if (sd->view_state == MULTIBUTTONENTRY_VIEW_ENTRY) - evas_object_hide(sd->entry); - else if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) - evas_object_hide(sd->guide_text); - else if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - evas_object_hide(sd->end); - - if (shrink == EINA_TRUE) - { - Evas_Coord w = 0, w_tmp = 0; - Evas_Coord box_inner_item_width_padding = 0; - - elm_box_padding_get(sd->box, &box_inner_item_width_padding, NULL); - // unpack all items and entry - elm_box_unpack_all(sd->box); - EINA_LIST_FOREACH(sd->items, l, eo_item) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - evas_object_hide(VIEW(item)); - item->visible = EINA_FALSE; - } - // pack buttons only 1line - w = sd->w_box; - - if (sd->label && sd->label_packed) - { - elm_box_pack_end(sd->box, sd->label); - efl_gfx_size_hint_combined_min_get(sd->label, &w_tmp, NULL); - w -= w_tmp; - w -= box_inner_item_width_padding; - } - - eo_item = NULL; - count = eina_list_count(sd->items); - - EINA_LIST_FOREACH(sd->items, l, eo_item) - { - Evas_Coord item_w, w_label_count = 0, h = 0; - char *buf; - - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - elm_box_pack_end(sd->box, VIEW(item)); - evas_object_show(VIEW(item)); - item->visible = EINA_TRUE; - - efl_gfx_size_hint_combined_min_get(VIEW(item), &item_w, NULL); - - w -= item_w; - w -= box_inner_item_width_padding; - count--; - - if (count > 0) - { - buf = sd->format_func(count, (void *)sd->format_func_data); - if (buf) - { - edje_object_part_text_escaped_set - (sd->end, "elm.text", buf); - free(buf); - } - - edje_object_size_min_calc(sd->end, &w_label_count, NULL); - elm_coords_finger_size_adjust(1, &w_label_count, 1, NULL); - } - - if ((w < 0) || (w < w_label_count)) - { - elm_box_unpack(sd->box, VIEW(item)); - evas_object_hide(VIEW(item)); - item->visible = EINA_FALSE; - count++; - - buf = sd->format_func(count, (void *)sd->format_func_data); - if (buf) - { - edje_object_part_text_escaped_set - (sd->end, "elm.text", buf); - free(buf); - } - - edje_object_size_min_calc(sd->end, &w_label_count, &h); - elm_coords_finger_size_adjust(1, &w_label_count, 1, &h); - evas_object_size_hint_min_set - (sd->end, w_label_count, h); - elm_box_pack_end(sd->box, sd->end); - evas_object_show(sd->end); - - break; - } - } - - if (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK) - { - sd->view_state = MULTIBUTTONENTRY_VIEW_SHRINK; - efl_event_callback_legacy_call - (obj, ELM_MULTIBUTTONENTRY_EVENT_EXPAND_STATE_CHANGED, (void *)1); - } - } - else - { - // unpack all items and entry - elm_box_unpack_all(sd->box); - EINA_LIST_FOREACH(sd->items, l, eo_item) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - evas_object_hide(VIEW(item)); - item->visible = EINA_FALSE; - } - evas_object_hide(sd->end); - - // pack buttons only 1line - - if (sd->label && sd->label_packed) elm_box_pack_end(sd->box, sd->label); - - // pack remain btns - eo_item = NULL; - EINA_LIST_FOREACH(sd->items, l, eo_item) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - elm_box_pack_end(sd->box, VIEW(item)); - evas_object_show(VIEW(item)); - item->visible = EINA_TRUE; - } - - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - { - sd->view_state = MULTIBUTTONENTRY_VIEW_NONE; - efl_event_callback_legacy_call - (obj, ELM_MULTIBUTTONENTRY_EVENT_EXPAND_STATE_CHANGED, (void *)(uintptr_t)sd->shrink); - } - } - - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - _elm_multibuttonentry_smart_focus_direction_enable = EINA_FALSE; - else - _elm_multibuttonentry_smart_focus_direction_enable = EINA_TRUE; - - if (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK) - _visual_guide_text_set(obj); -} - -static void -_view_update(Elm_Multibuttonentry_Data *sd) -{ - Evas_Coord width = 1, height = 1; - Evas_Object *obj = sd->parent; - - if (sd->w_box <= 0) return; - - // update label - if (sd->label) - efl_gfx_size_hint_combined_min_get(sd->label, &width, &height); - - if (sd->guide_text) - { - Evas_Coord guide_text_width = sd->w_box - width; - - evas_object_size_hint_min_set(sd->guide_text, guide_text_width, height); - } - - // update buttons in shrink mode - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - _shrink_mode_set(obj, EINA_TRUE); - - // update guidetext - _visual_guide_text_set(obj); -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_elm_widget_on_focus(Eo *obj, Elm_Multibuttonentry_Data *sd, Elm_Object_Item *item EINA_UNUSED) -{ - if (elm_widget_focus_get(obj)) - { - if (sd->focused) goto end; - sd->focused = EINA_TRUE; - - // ACCESS - if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) goto end; - - if (sd->editable) - { - if ((sd->selected_it)) - { - elm_layout_signal_emit(VIEW(sd->selected_it), "elm,state,focused", "elm"); - elm_object_focus_set(VIEW(sd->selected_it), EINA_TRUE); - elm_entry_input_panel_show(sd->entry); - } - else if (((!sd->selected_it) || (!eina_list_count(sd->items)))) - { - elm_entry_cursor_end_set(sd->entry); - _view_update(sd); - elm_entry_input_panel_show(sd->entry); - } - } - efl_event_callback_legacy_call - (obj, ELM_WIDGET_EVENT_FOCUSED, NULL); - } - else - { - if (sd->focused) goto end; - sd->focused = EINA_FALSE; - - if (sd->editable) - { - _view_update(sd); - elm_entry_input_panel_hide(sd->entry); - } - - if (sd->selected_it) - elm_layout_signal_emit(VIEW(sd->selected_it), "elm,state,unfocused", "elm"); - - efl_event_callback_legacy_call - (obj, ELM_WIDGET_EVENT_UNFOCUSED, NULL); - } - -end: - return EINA_TRUE; -} - -static void -_item_del(Elm_Multibuttonentry_Item_Data *item) -{ - Evas_Object *obj = WIDGET(item); - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - sd->items = eina_list_remove(sd->items, EO_OBJ(item)); - elm_box_unpack(sd->box, VIEW(item)); - - efl_event_callback_legacy_call - (obj, ELM_MULTIBUTTONENTRY_EVENT_ITEM_DELETED, EO_OBJ(item)); - - if (sd->selected_it == item) - sd->selected_it = NULL; - - if (sd->focused_it == item) - sd->focused_it = NULL; - - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - _shrink_mode_set(obj, EINA_TRUE); - - if (!eina_list_count(sd->items)) - _visual_guide_text_set(obj); -} - -static void -_current_item_state_change(Evas_Object *obj, - Multibuttonentry_Button_State state) -{ - Elm_Multibuttonentry_Item_Data *item; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - item = sd->selected_it; - - if (!item) return; - - switch (state) - { - case MULTIBUTTONENTRY_BUTTON_STATE_SELECTED: - elm_layout_signal_emit(VIEW(item), "elm,state,focused", "elm"); - efl_event_callback_legacy_call - (obj, ELM_MULTIBUTTONENTRY_EVENT_ITEM_SELECTED, EO_OBJ(item)); - break; - case MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT: - default: - elm_layout_signal_emit(VIEW(item), "elm,state,default", "elm"); - sd->selected_it = NULL; - break; - } -} - -static void -_current_item_change(Evas_Object *obj, - Elm_Object_Item *eo_it) -{ - Eina_List *l; - Elm_Object_Item *eo_temp_it; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); - - // change the state of previous item to "default" - _current_item_state_change(obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT); - - // change the current - EINA_LIST_FOREACH(sd->items, l, eo_temp_it) - { - if (eo_temp_it == eo_it) - { - sd->selected_it = it; - break; - } - } - // change the state of current item to "focused" - _current_item_state_change(obj, MULTIBUTTONENTRY_BUTTON_STATE_SELECTED); -} - -static void -_item_select(Evas_Object *obj, - Elm_Multibuttonentry_Item_Data *it) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - if (it) - { - _current_item_change(obj, EO_OBJ(it)); - - if (it->func) it->func((void *)(WIDGET_ITEM_DATA_GET(EO_OBJ(it))), WIDGET(it), EO_OBJ(it)); - - if (elm_widget_focus_get(obj)) - { - elm_object_focus_set(sd->entry, EINA_FALSE); - elm_object_focus_set(VIEW(it), EINA_TRUE); - - // ACCESS - if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF) - { - Evas_Object *ao, *po; - Eina_Strbuf *buf; - const char *part; - - part = "elm.btn.text"; - po = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(VIEW(it)), part); - ao = evas_object_data_get(po, "_part_access_obj"); - _elm_access_highlight_set(ao); - - buf = eina_strbuf_new(); - eina_strbuf_append_printf(buf, - "multi button entry item %s is selected", - edje_object_part_text_get(elm_layout_edje_get(VIEW(it)), part)); - - _elm_access_say(eina_strbuf_string_get(buf)); - eina_strbuf_free(buf); - } - } - } - else - { - _current_item_state_change - (obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT); - if (elm_widget_focus_get(obj) && sd->editable) - elm_object_focus_set(sd->entry, EINA_TRUE); - } -} - -static void -_on_item_clicked(void *data, - Evas_Object *obj EINA_UNUSED, - const char *emission EINA_UNUSED, - const char *source EINA_UNUSED) -{ - Elm_Object_Item *eo_it = data; - - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); - - _item_select(WIDGET(it), it); - - if (_elm_config->atspi_mode) - elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, - ELM_ATSPI_STATE_CHECKED, - EINA_TRUE); - - if (sd->selected_it) - efl_event_callback_legacy_call - (WIDGET(it), ELM_MULTIBUTTONENTRY_EVENT_ITEM_CLICKED, eo_it); -} - -static void -_on_item_deleted(void *data, - Evas_Object *obj, - const char *emission EINA_UNUSED, - const char *source EINA_UNUSED) -{ - Eina_List *l; - Elm_Object_Item *eo_it = data; - Elm_Object_Item *eo_temp_it; - - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); - // change the current - EINA_LIST_FOREACH(sd->items, l, eo_temp_it) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_temp_it, temp_it); - if (VIEW(temp_it) == obj) - { - elm_wdg_item_del(eo_temp_it); - break; - } - } -} - -static void -_on_item_focused(void *data, - Evas_Object *obj EINA_UNUSED, - void *event_info EINA_UNUSED) -{ - Elm_Multibuttonentry_Item_Data *it = data; - if (!it) return; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); - - sd->focused_it = it; -} - -static void -_on_item_unfocused(void *data, - Evas_Object *obj EINA_UNUSED, - void *event_info EINA_UNUSED) -{ - Elm_Multibuttonentry_Item_Data *it = data; - if (!it) return; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); - - sd->focused_it = NULL; -} - -static Eina_Bool -_long_press_cb(void *data) -{ - Elm_Multibuttonentry_Item_Data *it = data; - - ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd); - - sd->longpress_timer = NULL; - - efl_event_callback_legacy_call - (WIDGET(it), ELM_MULTIBUTTONENTRY_EVENT_ITEM_LONGPRESSED, EO_OBJ(it)); - - return ECORE_CALLBACK_CANCEL; -} - -static void -_mouse_down_cb(void *data, - Evas *evas EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event_info) -{ - Elm_Multibuttonentry_Item_Data *it = data; - Evas_Event_Mouse_Down *ev = event_info; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); - - if (ev->button != 1) return; - - ecore_timer_del(sd->longpress_timer); - sd->longpress_timer = ecore_timer_add - (_elm_config->longpress_timeout, _long_press_cb, it); -} - -static void -_mouse_up_cb(void *data, - Evas *evas EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event_info EINA_UNUSED) -{ - Elm_Multibuttonentry_Item_Data *it = data; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd); - - ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del); -} - -EOLIAN static void -_elm_multibuttonentry_item_elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED, - Elm_Multibuttonentry_Item_Data *item, - const char *emission, - const char *source) -{ - elm_layout_signal_emit(VIEW(item), emission, source); -} - -EOLIAN static void -_elm_multibuttonentry_item_elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED, - Elm_Multibuttonentry_Item_Data *item, - const char *part, - const char *label) -{ - const char *dest_part = NULL; - Evas_Coord minw = -1, minh = -1, boxw; - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(item), sd); - - if (!part || !strcmp(part, "elm.text")) - dest_part = "elm.btn.text"; - else - dest_part = part; - - edje_object_part_text_escaped_set(elm_layout_edje_get(VIEW(item)), dest_part, label); - - elm_coords_finger_size_adjust(1, &minw, 1, &minh); - edje_object_size_min_restricted_calc - (elm_layout_edje_get(VIEW(item)), &minw, &minh, minw, minh); - evas_object_size_hint_min_set(VIEW(item), minw, minh); - evas_object_geometry_get(sd->box, NULL, NULL, &boxw, NULL); - - if (minw > boxw) - { - evas_object_size_hint_min_set(VIEW(item), boxw, minh); - evas_object_resize(VIEW(item), boxw, minh); - } -} - -EOLIAN static const char * -_elm_multibuttonentry_item_elm_widget_item_part_text_get(Eo *eo_item EINA_UNUSED, - Elm_Multibuttonentry_Item_Data *item, - const char *part) -{ - const char *src_part = NULL; - - if (!part || !strcmp(part, "elm.text")) - src_part = "elm.btn.text"; - else - src_part = part; - - return edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), src_part); -} - -EOLIAN static void -_elm_multibuttonentry_item_efl_object_destructor(Eo *eo_it, - Elm_Multibuttonentry_Item_Data *it) -{ - if (_elm_config->atspi_mode) - elm_interface_atspi_accessible_children_changed_del_signal_emit(WIDGET(it), eo_it); - _item_del(it); - - efl_destructor(efl_super(eo_it, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); -} - -static void -_access_multibuttonentry_label_register(Evas_Object *obj, Eina_Bool is_access) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - Evas_Object *po; - - po = (Evas_Object *)edje_object_part_object_get(sd->label, "elm.text"); - if (is_access) - { - Evas_Object *ao; - ao = _elm_access_edje_object_part_object_register - (obj, sd->label, "elm.text"); - _elm_access_text_set(_elm_access_info_get(ao), - ELM_ACCESS_TYPE, E_("multi button entry label")); - } - else - _elm_access_edje_object_part_object_unregister - (obj, sd->label, "elm.text"); - - evas_object_pass_events_set(po, !is_access); - evas_object_propagate_events_set(sd->label, !is_access); -} - -static void -_access_multibuttonentry_item_register(Evas_Object *obj, - Elm_Object_Item *eo_item, - Eina_Bool is_access) -{ - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - if (is_access) - { - Evas_Object *ao; - ao = _elm_access_edje_object_part_object_register - (obj, elm_layout_edje_get(VIEW(item)), "elm.btn.text"); - _elm_access_text_set(_elm_access_info_get(ao), - ELM_ACCESS_TYPE, E_("multi button entry item")); - } - else - _elm_access_edje_object_part_object_unregister - (obj, elm_layout_edje_get(VIEW(item)), "elm.btn.text"); - - /* cannot read item because mouse-in event is delivered to - the multibuttonentry resize_obj which is registered as an access - object, so the mouse-in event should be blocked here */ - evas_object_propagate_events_set(VIEW(item), !is_access); -} - -EOLIAN static Eo * -_elm_multibuttonentry_item_efl_object_constructor(Eo *eo_item, Elm_Multibuttonentry_Item_Data *item) -{ - eo_item = efl_constructor(efl_super(eo_item, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); - item->base = efl_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS); - - return eo_item; -} - -static Elm_Object_Item * -_item_new(Elm_Multibuttonentry_Data *sd, - const char *str, - Multibuttonentry_Pos pos, - Elm_Object_Item *efl_reference, - Evas_Smart_Cb func, - void *data) -{ - Eina_List *l; - Eo *eo_item; - Elm_Multibuttonentry_Item_Filter *item_filter; - Elm_Multibuttonentry_Item_Data *reference = efl_reference? - efl_data_scope_get(efl_reference, ELM_MULTIBUTTONENTRY_ITEM_CLASS): - NULL; - Evas_Object *obj; - int minw, minh, boxw; - - obj = sd->parent; - - if (!str) return NULL; - - EINA_LIST_FOREACH(sd->filter_list, l, item_filter) - { - if (!(item_filter->callback_func(obj, str, data, item_filter->data))) - return NULL; - } - - eo_item = efl_add(ELM_MULTIBUTTONENTRY_ITEM_CLASS, obj); - if (!eo_item) - return NULL; - WIDGET_ITEM_DATA_SET(eo_item, data); - - elm_interface_atspi_accessible_role_set(eo_item, ELM_ATSPI_ROLE_RADIO_BUTTON); - - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - VIEW(item) = elm_layout_add(obj); - - elm_interface_atspi_accessible_type_set(VIEW(item), ELM_ATSPI_TYPE_DISABLED); - - if (!elm_layout_theme_set - (VIEW(item), "multibuttonentry", "btn", elm_widget_style_get(obj))) - CRI("Failed to set layout!"); - - elm_object_part_text_set(VIEW(item), "elm.btn.text", str); - - //entry is cleared when text is made to button - elm_object_text_set(sd->entry, ""); - - elm_layout_signal_callback_add - (VIEW(item), "mouse,clicked,1", "*", _on_item_clicked, EO_OBJ(item)); - elm_layout_signal_callback_add - (VIEW(item), "elm,deleted", "elm", _on_item_deleted, EO_OBJ(item)); - evas_object_smart_callback_add - (VIEW(item), "focused", _on_item_focused, item); - evas_object_smart_callback_add - (VIEW(item), "unfocused", _on_item_unfocused, item); - evas_object_event_callback_add - (VIEW(item), - EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, item); - evas_object_event_callback_add - (VIEW(item), - EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, item); - - evas_object_show(VIEW(item)); - - evas_object_smart_calculate(VIEW(item)); - efl_gfx_size_hint_combined_min_get(VIEW(item), &minw, &minh); - evas_object_geometry_get(sd->box, NULL, NULL, &boxw, NULL); - - if (sd->w_box && minw > boxw) - { - elm_coords_finger_size_adjust(1, &boxw, 1, &minh); - evas_object_size_hint_min_set(VIEW(item), boxw, minh); - evas_object_resize(VIEW(item), boxw, minh); - } - - elm_object_focus_allow_set(VIEW(item), EINA_TRUE); - - item->visible = EINA_TRUE; - - // ACCESS - if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) - { - Eina_Strbuf *buf; - buf = eina_strbuf_new(); - - eina_strbuf_append_printf(buf, - "multi button entry item %s is added", - edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), "elm.btn.text")); - - _elm_access_say(eina_strbuf_string_get(buf)); - eina_strbuf_free(buf); - - _access_multibuttonentry_item_register(obj, eo_item, EINA_TRUE); - } - - if (func) - { - item->func = func; - } - - switch (pos) - { - case MULTIBUTTONENTRY_POS_START: - sd->items = eina_list_prepend(sd->items, eo_item); - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - { - elm_widget_sub_object_add(obj, VIEW(item)); - _shrink_mode_set(obj, EINA_TRUE); - } - else - { - if (sd->label && sd->label_packed) - elm_box_pack_after(sd->box, VIEW(item), sd->label); - else - elm_box_pack_start(sd->box, VIEW(item)); - if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) - _visual_guide_text_set(obj); - } - break; - - case MULTIBUTTONENTRY_POS_END: - sd->items = eina_list_append(sd->items, eo_item); - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - { - elm_widget_sub_object_add(obj, VIEW(item)); - evas_object_hide(VIEW(item)); - } - else - { - if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) - _visual_guide_text_set(obj); - - if (sd->editable) - elm_box_pack_before(sd->box, VIEW(item), sd->entry); - else - elm_box_pack_end(sd->box, VIEW(item)); - } - break; - - case MULTIBUTTONENTRY_POS_BEFORE: - if (efl_reference) - sd->items = eina_list_prepend_relative(sd->items, eo_item, efl_reference); - else - sd->items = eina_list_append(sd->items, eo_item); - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - { - elm_widget_sub_object_add(obj, VIEW(item)); - evas_object_hide(VIEW(item)); - _shrink_mode_set(obj, EINA_TRUE); - } - else - { - if (efl_reference) - elm_box_pack_before(sd->box, VIEW(item), VIEW(reference)); - else - { - if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) - _visual_guide_text_set(obj); - if (sd->editable) - { - elm_box_pack_before(sd->box, VIEW(item), sd->entry); - } - else - elm_box_pack_end(sd->box, VIEW(item)); - } - } - break; - - case MULTIBUTTONENTRY_POS_AFTER: - if (efl_reference) - sd->items = eina_list_append_relative(sd->items, eo_item, efl_reference); - else - sd->items = eina_list_append(sd->items, eo_item); - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - { - elm_widget_sub_object_add(obj, VIEW(item)); - _shrink_mode_set(obj, EINA_TRUE); - } - else - { - if (efl_reference) - elm_box_pack_after(sd->box, VIEW(item), VIEW(reference)); - else - { - if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) - _visual_guide_text_set(obj); - if (sd->editable) - { - elm_box_pack_before(sd->box, VIEW(item), sd->entry); - } - else - elm_box_pack_end(sd->box, VIEW(item)); - } - } - break; - - default: - break; - } - - if (!elm_object_focus_get(obj) && sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK && sd->w_box) - _shrink_mode_set(obj, EINA_TRUE); - - - efl_event_callback_legacy_call - (obj, ELM_MULTIBUTTONENTRY_EVENT_ITEM_ADDED, eo_item); - - if (_elm_config->atspi_mode) - { - elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, eo_item); - elm_interface_atspi_accessible_added(eo_item); - } - - return eo_item; -} - -//FIXME: having an empty event handling function and reacting on Evas -//events on specific objects is crazy, someone should fix that. -EOLIAN static Eina_Bool -_elm_multibuttonentry_elm_widget_widget_event(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd EINA_UNUSED, const Efl_Event *eo_event EINA_UNUSED, Evas_Object *src EINA_UNUSED) -{ - // ACCESS - if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) return EINA_FALSE; - - return EINA_TRUE; -} - -EOLIAN static void -_elm_multibuttonentry_elm_layout_sizing_eval(Eo *obj, Elm_Multibuttonentry_Data *sd EINA_UNUSED) -{ - Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; - - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); - - elm_coords_finger_size_adjust(1, &minw, 1, &minh); - edje_object_size_min_restricted_calc - (wd->resize_obj, &minw, &minh, minw, minh); - elm_coords_finger_size_adjust(1, &minw, 1, &minh); - evas_object_size_hint_min_set(obj, minw, minh); - evas_object_size_hint_max_set(obj, maxw, maxh); -} - -static void -_mouse_clicked_signal_cb(void *data EINA_UNUSED, - Evas_Object *obj, - const char *emission EINA_UNUSED, - const char *source EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - if (sd->editable) elm_entry_input_panel_show(sd->entry); - - efl_event_callback_legacy_call(obj, EFL_UI_EVENT_CLICKED, NULL); -} - -static void -_box_resize_cb(void *data, - Evas *evas EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event EINA_UNUSED) -{ - Evas_Coord w, h, mnw, mnh; - Eina_List *l; - Elm_Object_Item *eo_it; - int hpad; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - - evas_object_geometry_get(sd->box, NULL, NULL, &w, &h); - if ((w <= elm_config_finger_size_get()) || (h <= elm_config_finger_size_get())) return; - - elm_box_padding_get(obj, &hpad, NULL); - - if (sd->h_box < h) - efl_event_callback_legacy_call - (sd->parent, ELM_MULTIBUTTONENTRY_EVENT_EXPANDED, NULL); - else if (sd->h_box > h) - efl_event_callback_legacy_call - (sd->parent, ELM_MULTIBUTTONENTRY_EVENT_CONTRACTED, NULL); - - if (sd->items && sd->w_box != w) - { - EINA_LIST_FOREACH (sd->items, l, eo_it) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it); - - elm_layout_sizing_eval(VIEW(it)); - evas_object_smart_calculate(VIEW(it)); - - efl_gfx_size_hint_combined_min_get(VIEW(it), &mnw, &mnh); - - if (mnw > w - hpad) - { - mnw = w - hpad; - evas_object_size_hint_min_set(VIEW(it), mnw, mnh); - evas_object_resize(VIEW(it), mnw, mnh); - } - } - } - - sd->w_box = w; - sd->h_box = h; - - if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) - _shrink_mode_set(data, EINA_TRUE); -} - -static void -_entry_resize_cb(void *data, - Evas *e EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event_info EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - - if (elm_widget_focus_get(sd->parent)) - { - Eina_Rectangle sr = {}; - - evas_object_geometry_get(sd->entry, &sr.x, &sr.y, &sr.w, &sr.h); - elm_widget_show_region_set(sd->entry, sr, EINA_TRUE); - } -} - -static void -_entry_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - const char *str; - - str = elm_object_text_get(sd->entry); - sd->n_str = str ? strlen(str) : 0; -} - -static void -_entry_focus_in_cb(void *data, const Efl_Event *event EINA_UNUSED) -{ - Elm_Multibuttonentry_Item_Data *item = NULL; - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - - if (sd->selected_it) - { - item = sd->selected_it; - elm_object_focus_set(sd->entry, EINA_FALSE); - elm_object_focus_set(VIEW(item), EINA_TRUE); - } -} - -static void -_entry_focus_out_cb(void *data, const Efl_Event *event EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - const char *str; - - str = elm_object_text_get(sd->entry); - if (str && str[0]) - _item_new(sd, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL); -} - -static void -_entry_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - - _current_item_state_change(sd->parent, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT); - elm_object_focus_set(sd->entry, EINA_TRUE); -} - -static void -_layout_key_down_cb(void *data, - Evas *e EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event_info) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info; - - if (!sd->box) return; - - if (sd->last_it_select) - { - if (sd->selected_it && - ((!strcmp(ev->key, "BackSpace")) || - (!strcmp(ev->key, "Delete")))) - { - Elm_Multibuttonentry_Item_Data *item = sd->selected_it; - if (item && sd->editable) - { - elm_wdg_item_del(EO_OBJ(item)); - elm_object_focus_set(sd->entry, EINA_TRUE); - } - } - else if (sd->focused_it && - ((!strcmp(ev->key, "KP_Enter")) || - (!strcmp(ev->key, "Return")))) - { - Elm_Multibuttonentry_Item_Data *item = sd->focused_it; - if (item) - _on_item_clicked(EO_OBJ(item), NULL, NULL, NULL); - } - else if (((!sd->selected_it && (sd->n_str == 0) && - (!strcmp(ev->key, "BackSpace"))) || - (!strcmp(ev->key, "Delete")))) - { - Elm_Object_Item *eo_item = eina_list_data_get(eina_list_last(sd->items)); - if (eo_item) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - _item_select(sd->parent, item); - } - } - } - else - sd->last_it_select = EINA_TRUE; -} - -static void -_entry_key_down_cb(void *data, - Evas *e EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event_info) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info; - - if (sd->n_str == 1 && - (!strcmp(ev->key, "BackSpace") || !strcmp(ev->key, "Delete"))) - sd->last_it_select = EINA_FALSE; -} - -static void -_entry_key_up_cb(void *data, - Evas *e EINA_UNUSED, - Evas_Object *obj EINA_UNUSED, - void *event_info) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd); - Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info; - const char *str; - - if (!sd->box) return; - - str = elm_object_text_get(sd->entry); - if (!str) return; - - if (strlen(str) && - (!strcmp(ev->key, "KP_Enter") || !strcmp(ev->key, "Return"))) - { - _item_new(sd, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL); - sd->n_str = 0; - } -} - -static void -_callbacks_register(Evas_Object *obj) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); - - elm_layout_signal_callback_add - (obj, "mouse,clicked,1", "*", _mouse_clicked_signal_cb, NULL); - - evas_object_event_callback_add - (wd->resize_obj, EVAS_CALLBACK_KEY_DOWN, - _layout_key_down_cb, obj); - - evas_object_event_callback_add - (sd->box, EVAS_CALLBACK_RESIZE, _box_resize_cb, obj); - - evas_object_event_callback_add - (sd->entry, EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj); - evas_object_event_callback_add - (sd->entry, EVAS_CALLBACK_KEY_DOWN, _entry_key_down_cb, obj); - evas_object_event_callback_add - (sd->entry, EVAS_CALLBACK_RESIZE, _entry_resize_cb, obj); - efl_event_callback_array_add(sd->entry, _multi_buttonentry_cb(), obj); -} - -static void -_label_set(Evas_Object *obj, - const char *str) -{ - Evas_Coord width, height; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - if (!str) return; - - eina_stringshare_replace(&sd->label_str, str); - - edje_object_part_text_escaped_set(sd->label, "elm.text", str); - - if (!strlen(str)) - { - sd->label_packed = EINA_FALSE; - elm_box_unpack(sd->box, sd->label); - evas_object_hide(sd->label); - } - else - { - if (sd->label_packed) - elm_box_unpack(sd->box, sd->label); - sd->label_packed = EINA_TRUE; - edje_object_size_min_calc(sd->label, &width, &height); - evas_object_size_hint_min_set(sd->label, width, height); - elm_box_pack_start(sd->box, sd->label); - evas_object_show(sd->label); - } - - _view_update(sd); -} - -static void -_guide_text_set(Evas_Object *obj, - const char *str) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - if (!str) return; - - eina_stringshare_replace(&sd->guide_text_str, str); - if (sd->guide_text == NULL) - sd->guide_text = edje_object_add(evas_object_evas_get(obj)); - - if (sd->guide_text) - { - elm_widget_theme_object_set(obj, sd->guide_text, "multibuttonentry", - "guidetext", elm_widget_style_get(obj)); - evas_object_size_hint_weight_set - (sd->guide_text, 0.0, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set - (sd->guide_text, EVAS_HINT_FILL, EVAS_HINT_FILL); - edje_object_part_text_escaped_set(sd->guide_text, "elm.text", str); - _view_update(sd); - } -} - -static Elm_Multibuttonentry_Item_Filter * -_filter_new(Elm_Multibuttonentry_Item_Filter_Cb func, - void *data) -{ - Elm_Multibuttonentry_Item_Filter *item_filter = - ELM_NEW(Elm_Multibuttonentry_Item_Filter); - if (!item_filter) return NULL; - - item_filter->callback_func = func; - item_filter->data = data; - - return item_filter; -} - -static void -_filter_free(Elm_Multibuttonentry_Item_Filter *item_filter) -{ - free(item_filter); -} - -static Eina_Bool -_box_min_size_calculate(Evas_Object *box, - Evas_Object_Box_Data *priv, - int *line_height, - void *data EINA_UNUSED) -{ - Evas_Coord mnw, mnh, w, minw, minh = 0, linew = 0, lineh = 0; - int line_num; - Eina_List *l; - Evas_Object_Box_Option *opt; - - evas_object_geometry_get(box, NULL, NULL, &w, NULL); - efl_gfx_size_hint_combined_min_get(box, &minw, NULL); - - if (!w) return EINA_FALSE; - - line_num = 1; - EINA_LIST_FOREACH(priv->children, l, opt) - { - efl_gfx_size_hint_combined_min_get(opt->obj, &mnw, &mnh); - - linew += mnw; - if (lineh < mnh) lineh = mnh; - - if (linew > w) - { - linew = mnw; - line_num++; - } - - if ((linew != 0) && (l != eina_list_last(priv->children))) - linew += priv->pad.h; - } - minh = lineh * line_num + (line_num - 1) * priv->pad.v; - - evas_object_size_hint_min_set(box, minw, minh); - *line_height = lineh; - - return EINA_TRUE; -} - -static void -_box_layout_cb(Evas_Object *o, - Evas_Object_Box_Data *priv, - void *data) -{ - Evas_Coord x, y, w, h, xx, yy; - Evas_Coord minw, minh, linew = 0, lineh = 0; - Evas_Object_Box_Option *opt; - const Eina_List *l, *l_next; - Evas_Object *obj; - double ax, ay; - Eina_Bool rtl; - - if (!_box_min_size_calculate(o, priv, &lineh, data)) return; - - evas_object_geometry_get(o, &x, &y, &w, &h); - - efl_gfx_size_hint_combined_min_get(o, &minw, &minh); - evas_object_size_hint_align_get(o, &ax, &ay); - - rtl = efl_ui_mirrored_get(data); - if (rtl) ax = 1.0 - ax; - - if (w < minw) - { - x = x + ((w - minw) * (1.0 - ax)); - w = minw; - } - if (h < minh) - { - y = y + ((h - minh) * (1.0 - ay)); - h = minh; - } - - xx = x; - yy = y; - - EINA_LIST_FOREACH_SAFE(priv->children, l, l_next, opt) - { - Evas_Coord mnw, mnh; - Evas_Coord ww, hh, ow, oh; - double wx, wy; - int fw, fh; - - obj = opt->obj; - evas_object_size_hint_align_get(obj, &ax, &ay); - evas_object_size_hint_weight_get(obj, &wx, &wy); - efl_gfx_size_hint_combined_min_get(obj, &mnw, &mnh); - - fw = fh = EINA_FALSE; - if (EINA_DBL_EQ(ax, -1)) {fw = 1; ax = 0.5; } - if (EINA_DBL_EQ(ay, -1)) {fh = 1; ay = 0.5; } - if (rtl) ax = 1.0 - ax; - - ww = mnw; - if (!EINA_DBL_EQ(wx, 0)) - { - if (ww <= w - linew) ww = w - linew; - else ww = w; - } - hh = lineh; - - ow = mnw; - if (fw) ow = ww; - oh = mnh; - if (fh) oh = hh; - - linew += ww; - if (linew > w && l != priv->children) - { - xx = x; - yy += hh; - yy += priv->pad.v; - linew = ww; - } - - evas_object_move(obj, - ((!rtl) ? (xx) : (x + (w - (xx - x) - ww))) - + (Evas_Coord)(((double)(ww - ow)) * ax), - yy + (Evas_Coord)(((double)(hh - oh)) * ay)); - evas_object_resize(obj, ow, oh); - - xx += ww; - xx += priv->pad.h; - - if (linew > w) - { - opt = eina_list_data_get(l_next); - if (opt && opt->obj && efl_isa(opt->obj, ELM_ENTRY_CLASS)) - { - xx = x; - yy += hh; - yy += priv->pad.v; - linew = 0; - } - } - if ((linew != 0) && (l != eina_list_last(priv->children))) - linew += priv->pad.h; - } -} - -static void -_view_init(Evas_Object *obj, Elm_Multibuttonentry_Data *sd) -{ - const char *str; - double pad_scale; - int hpad = 0, vpad = 0; - - sd->box = elm_box_add(obj); - - if (!sd->box) return; - - str = elm_layout_data_get(obj, "horizontal_pad"); - if (str) hpad = atoi(str); - str = elm_layout_data_get(obj, "vertical_pad"); - if (str) vpad = atoi(str); - pad_scale = efl_ui_scale_get(obj) * elm_config_scale_get() - / edje_object_base_scale_get(elm_layout_edje_get(obj)); - elm_box_padding_set(sd->box, (hpad * pad_scale), (vpad * pad_scale)); - - elm_box_layout_set(sd->box, _box_layout_cb, obj, NULL); - elm_box_homogeneous_set(sd->box, EINA_FALSE); - elm_layout_content_set(obj, "box.swallow", sd->box); - - sd->label = edje_object_add(evas_object_evas_get(obj)); - if (!sd->label) return; - elm_widget_theme_object_set - (obj, sd->label, "multibuttonentry", "label", - elm_widget_style_get(obj)); - - // ACCESS - if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) - _access_multibuttonentry_label_register(obj, EINA_TRUE); - - sd->entry = elm_entry_add(obj); - if (!sd->entry) return; - elm_entry_single_line_set(sd->entry, EINA_TRUE); - elm_entry_cnp_mode_set(sd->entry, ELM_CNP_MODE_PLAINTEXT); - elm_object_text_set(sd->entry, ""); - elm_entry_input_panel_enabled_set(sd->entry, EINA_FALSE); - evas_object_size_hint_min_set(sd->entry, MIN_W_ENTRY, 0); - evas_object_size_hint_weight_set - (sd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - evas_object_size_hint_align_set(sd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_box_pack_end(sd->box, sd->entry); - evas_object_show(sd->entry); - - sd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY; - - { - Evas_Coord button_min_width = 0, button_min_height = 0; - - sd->end = edje_object_add(evas_object_evas_get(obj)); - if (!sd->end) return; - elm_widget_theme_object_set - (obj, sd->end, "multibuttonentry", "closedbutton", - elm_widget_style_get(obj)); - - edje_object_size_min_calc(sd->end, &button_min_width, &button_min_height); - elm_coords_finger_size_adjust(1, &button_min_width, 1, &button_min_height); - evas_object_size_hint_min_set(sd->end, button_min_width, button_min_height); - elm_widget_sub_object_add(obj, sd->end); - } -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_text_set(Eo *obj, Elm_Multibuttonentry_Data *sd EINA_UNUSED, const char *part, const char *label) -{ - Eina_Bool int_ret = EINA_TRUE; - - if (!part || !strcmp(part, "default") || !strcmp(part, "elm.text")) - { - if (label) _label_set(obj, label); - int_ret = EINA_TRUE; - } - else if (!strcmp(part, "guide")) - { - if (label) _guide_text_set(obj, label); - int_ret = EINA_TRUE; - } - else - efl_text_set(efl_part(efl_super(obj, MY_CLASS), part), label); - - return int_ret; -} - -EOLIAN static const char* -_elm_multibuttonentry_text_get(Eo *obj, Elm_Multibuttonentry_Data *sd, const char *part) -{ - const char *text = NULL; - - if (!part || !strcmp(part, "default")) - { - text = sd->label_str; - } - else if (!strcmp(part, "guide")) - { - text = sd->guide_text_str; - } - else - text = efl_text_get(efl_part(efl_super(obj, MY_CLASS), part)); - - return text; -} - -static char * -_access_info_cb(void *data EINA_UNUSED, Evas_Object *obj) -{ - char *ret; - Eina_Strbuf *buf; - Eina_List *l = NULL; - Elm_Object_Item *eo_item; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL); - - if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT) - { - if (sd->guide_text_str) return strdup(sd->guide_text_str); - return NULL; - } - - buf = eina_strbuf_new(); - - if (sd->label_str) eina_strbuf_append(buf, sd->label_str); - - int invisible_its = 0; - EINA_LIST_FOREACH (sd->items, l, eo_item) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - if (item->visible) - eina_strbuf_append_printf(buf, ", %s", - edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), "elm.btn.text")); - else - invisible_its++; - } - - if (invisible_its) - eina_strbuf_append_printf(buf, ", and %d more", invisible_its); - - ret = eina_strbuf_string_steal(buf); - eina_strbuf_free(buf); - return ret; -} - -EOLIAN static void -_elm_multibuttonentry_efl_canvas_group_group_add(Eo *obj, Elm_Multibuttonentry_Data *priv) -{ - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); - - efl_canvas_group_add(efl_super(obj, MY_CLASS)); - elm_widget_sub_object_parent_add(obj); - - if (!elm_layout_theme_set - (obj, "multibuttonentry", "base", elm_widget_style_get(obj))) - CRI("Failed to set layout!"); - - elm_widget_can_focus_set(obj, EINA_TRUE); - - priv->last_it_select = EINA_TRUE; - priv->editable = EINA_TRUE; - priv->parent = obj; - priv->format_func = _format_count; - - _view_init(obj, priv); - _callbacks_register(obj); - - // ACCESS - _elm_access_object_register(obj, wd->resize_obj); - _elm_access_text_set - (_elm_access_info_get(obj), ELM_ACCESS_TYPE, E_("multi button entry")); - _elm_access_callback_set - (_elm_access_info_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL); -} - -EOLIAN static void -_elm_multibuttonentry_efl_canvas_group_group_del(Eo *obj, Elm_Multibuttonentry_Data *sd) -{ - Eina_List *l; - Elm_Object_Item *eo_item; - Elm_Multibuttonentry_Item_Filter *_item_filter = NULL; - - EINA_LIST_FOREACH(sd->items, l, eo_item) - efl_del(eo_item); - - sd->items = eina_list_free(sd->items); - - sd->selected_it = NULL; - sd->focused_it = NULL; - - eina_stringshare_del(sd->label_str); - eina_stringshare_del(sd->guide_text_str); - evas_object_del(sd->entry); - evas_object_del(sd->label); - evas_object_del(sd->guide_text); - evas_object_del(sd->end); - ecore_timer_del(sd->longpress_timer); - - EINA_LIST_FREE(sd->filter_list, _item_filter) - _filter_free(_item_filter); - - efl_canvas_group_del(efl_super(obj, MY_CLASS)); -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd EINA_UNUSED) -{ - return _elm_multibuttonentry_smart_focus_direction_enable; -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_elm_widget_focus_direction(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight) -{ - Eina_Bool ret; - Eina_List *items = NULL; - - items = eina_list_append(items, sd->box); - - ret = elm_widget_focus_list_direction_get - (obj, base, items, eina_list_data_get, degree, direction, direction_item, weight); - eina_list_free(items); - - return ret; -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd EINA_UNUSED) -{ - return _elm_multibuttonentry_smart_focus_next_enable; -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_elm_widget_focus_next(Eo *obj, Elm_Multibuttonentry_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) -{ - Eina_Bool int_ret = EINA_FALSE; - - Eina_List *items = NULL; - Eina_List *l = NULL; - Elm_Object_Item *eo_item; - Evas_Object *ao; - Evas_Object *po; - - if (!elm_widget_focus_get(obj)) - { - *next = (Evas_Object *)obj; - return EINA_TRUE; - } - - if (sd->label) - { - po = (Evas_Object *)edje_object_part_object_get(sd->label, "elm.text"); - ao = evas_object_data_get(po, "_part_access_obj"); - int_ret = elm_widget_focus_get(ao); - items = eina_list_append(items, ao); - } - - EINA_LIST_FOREACH (sd->items, l, eo_item) - { - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item); - po = (Evas_Object *)edje_object_part_object_get - (elm_layout_edje_get(VIEW(item)), "elm.btn.text"); - ao = evas_object_data_get(po, "_part_access_obj"); - int_ret = int_ret || elm_widget_focus_get(ao); - items = eina_list_append(items, ao); - } - - if (sd->entry) - { - int_ret = int_ret || elm_widget_focus_get(sd->entry); - /* elm_widget_list_focus_liset_next_get() check parent of item - because parent sd->entry is not multibuttnentry but sd->box - so append sd->box instead of sd->entry, is this proper? */ - items = eina_list_append(items, sd->box); - } - - if (int_ret) - return elm_widget_focus_list_next_get - (obj, items, eina_list_data_get, dir, next, next_item); - - return EINA_FALSE; -} - -static void -_access_obj_process(Evas_Object *obj, Eina_Bool is_access) -{ - Eina_List *l; - Elm_Object_Item *it; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd); - - /* label */ - _access_multibuttonentry_label_register(obj, is_access); - - /* buttons */ - EINA_LIST_FOREACH(sd->items, l, it) - _access_multibuttonentry_item_register(obj, it, is_access); -} - -EOLIAN static void -_elm_multibuttonentry_elm_widget_on_access_update(Eo *obj, Elm_Multibuttonentry_Data *sd EINA_UNUSED, Eina_Bool acs) -{ - _elm_multibuttonentry_smart_focus_next_enable = acs; - _access_obj_process(obj, _elm_multibuttonentry_smart_focus_next_enable); -} - -EAPI Evas_Object * -elm_multibuttonentry_add(Evas_Object *parent) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); - return efl_add(MY_CLASS, parent, efl_canvas_object_legacy_ctor(efl_added)); -} - -EOLIAN static Eo * -_elm_multibuttonentry_efl_object_constructor(Eo *obj, Elm_Multibuttonentry_Data *sd EINA_UNUSED) -{ - obj = efl_constructor(efl_super(obj, MY_CLASS)); - efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); - evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); - elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_PANEL); - - return obj; -} - -EOLIAN static Evas_Object* -_elm_multibuttonentry_entry_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - return sd->entry; -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_expanded_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - return sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK ? - EINA_FALSE : EINA_TRUE; -} - -EOLIAN static void -_elm_multibuttonentry_format_function_set(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Format_Cb f_func, const void *data) -{ - sd->format_func = f_func; - if (!sd->format_func) sd->format_func = _format_count; - - sd->format_func_data = data; - - _view_update(sd); -} - -EOLIAN static void -_elm_multibuttonentry_expanded_set(Eo *obj, Elm_Multibuttonentry_Data *sd, Eina_Bool expanded) -{ - if (((sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) ? - EINA_FALSE : EINA_TRUE) == expanded) return; - - if (expanded) - _shrink_mode_set(obj, EINA_FALSE); - else - _shrink_mode_set(obj, EINA_TRUE); -} - -EOLIAN static void -_elm_multibuttonentry_editable_set(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Eina_Bool editable) -{ - editable = !!editable; - if (sd->editable == editable) return; - sd->editable = editable; - - if (sd->editable && (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK)) - { - elm_box_pack_end(sd->box, sd->entry); - evas_object_show(sd->entry); - } - else - { - elm_box_unpack(sd->box, sd->entry); - evas_object_hide(sd->entry); - } -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_editable_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - return sd->editable; -} - -EOLIAN static Elm_Object_Item* -_elm_multibuttonentry_item_prepend(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, const char *label, Evas_Smart_Cb func, void *data) -{ - return _item_new(sd, label, MULTIBUTTONENTRY_POS_START, NULL, func, data); -} - -EOLIAN static Elm_Object_Item* -_elm_multibuttonentry_item_append(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, const char *label, Evas_Smart_Cb func, void *data) -{ - return _item_new(sd, label, MULTIBUTTONENTRY_POS_END, NULL, func, data); -} - -EOLIAN static Elm_Object_Item* -_elm_multibuttonentry_item_insert_before(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Object_Item *before, const char *label, Evas_Smart_Cb func, void *data) -{ - return _item_new(sd, label, MULTIBUTTONENTRY_POS_BEFORE, before, func, data); -} - -EOLIAN static Elm_Object_Item* -_elm_multibuttonentry_item_insert_after(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Object_Item *after, const char *label, Evas_Smart_Cb func, void *data) -{ - return _item_new(sd, label, MULTIBUTTONENTRY_POS_AFTER, after, func, data); -} - -EOLIAN static const Eina_List* -_elm_multibuttonentry_items_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - return sd->items; -} - -EOLIAN static Elm_Object_Item* -_elm_multibuttonentry_first_item_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - return eina_list_data_get(sd->items); -} - -EOLIAN static Elm_Object_Item* -_elm_multibuttonentry_last_item_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - return eina_list_data_get(eina_list_last(sd->items)); -} - -EOLIAN static Elm_Object_Item* -_elm_multibuttonentry_selected_item_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - return EO_OBJ(sd->selected_it); -} - -EOLIAN static void -_elm_multibuttonentry_item_selected_set(Eo *eo_item EINA_UNUSED, - Elm_Multibuttonentry_Item_Data *item, - Eina_Bool selected) -{ - if (selected) _item_select(WIDGET(item), item); - else _item_select(WIDGET(item), NULL); -} - -EOLIAN static Eina_Bool -_elm_multibuttonentry_item_selected_get(Eo *eo_item, - Elm_Multibuttonentry_Item_Data *item) -{ - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(item), sd, EINA_FALSE); - if (!eo_item) return EINA_FALSE; - if (EO_OBJ(sd->selected_it) == eo_item) - return EINA_TRUE; - - return EINA_FALSE; -} - -EOLIAN static void -_elm_multibuttonentry_clear(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd) -{ - while (sd->items) - elm_wdg_item_del(eina_list_data_get(sd->items)); - - sd->selected_it = NULL; - _view_update(sd); -} - -EOLIAN static Elm_Object_Item * -_elm_multibuttonentry_item_prev_get(const Eo *eo_it, - Elm_Multibuttonentry_Item_Data *it) -{ - Eina_List *l; - Elm_Object_Item *eo_temp_it; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, NULL); - - EINA_LIST_FOREACH(sd->items, l, eo_temp_it) - { - if (eo_temp_it == eo_it) - { - l = eina_list_prev(l); - if (!l) return NULL; - return eina_list_data_get(l); - } - } - return NULL; -} - -EOLIAN static Elm_Object_Item * -_elm_multibuttonentry_item_next_get(const Eo *eo_it, - Elm_Multibuttonentry_Item_Data *it) -{ - Eina_List *l; - Elm_Object_Item *eo_temp_it; - - ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, NULL); - - EINA_LIST_FOREACH(sd->items, l, eo_temp_it) - { - if (eo_temp_it == eo_it) - { - l = eina_list_next(l); - if (!l) return NULL; - return eina_list_data_get(l); - } - } - return NULL; -} - -EOLIAN static void -_elm_multibuttonentry_item_elm_widget_item_disable(Eo *eo_it, Elm_Multibuttonentry_Item_Data *it) -{ - const char* emission; - if (elm_wdg_item_disabled_get(eo_it)) - emission = "elm,state,disabled"; - else - emission = "elm,state,enabled"; - - elm_layout_signal_emit(VIEW(it), emission, "elm"); -} - -EINA_DEPRECATED EAPI void * -elm_multibuttonentry_item_data_get(const Elm_Object_Item *it) -{ - return (void *)WIDGET_ITEM_DATA_GET(it); -} - -EINA_DEPRECATED EAPI void -elm_multibuttonentry_item_data_set(Elm_Object_Item *it, - void *data) -{ - WIDGET_ITEM_DATA_SET(it, data); -} - -EOLIAN static void -_elm_multibuttonentry_item_filter_append(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data) -{ - Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL; - Elm_Multibuttonentry_Item_Filter *_item_filter = NULL; - Eina_List *l; - - EINA_SAFETY_ON_NULL_RETURN(func); - - EINA_LIST_FOREACH(sd->filter_list, l, _item_filter) - { - if (_item_filter && ((_item_filter->callback_func == func) - && (_item_filter->data == data))) - { - INF("Already Registered this item filter!!!!\n"); - return; - } - } - new_item_filter = _filter_new(func, data); - if (!new_item_filter) return; - - sd->filter_list = eina_list_append(sd->filter_list, new_item_filter); -} - -EOLIAN static void -_elm_multibuttonentry_item_filter_prepend(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data) -{ - Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL; - Elm_Multibuttonentry_Item_Filter *_item_filter = NULL; - Eina_List *l; - - EINA_SAFETY_ON_NULL_RETURN(func); - - new_item_filter = _filter_new(func, data); - if (!new_item_filter) return; - - EINA_LIST_FOREACH(sd->filter_list, l, _item_filter) - { - if (_item_filter && ((_item_filter->callback_func == func) - && (_item_filter->data == data))) - { - INF("Already Registered this item filter!!!!\n"); - _filter_free(new_item_filter); - return; - } - } - sd->filter_list = eina_list_prepend(sd->filter_list, new_item_filter); -} - -EOLIAN static void -_elm_multibuttonentry_item_filter_remove(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data) -{ - Eina_List *l; - Elm_Multibuttonentry_Item_Filter *item_filter; - - EINA_SAFETY_ON_NULL_RETURN(func); - - EINA_LIST_FOREACH(sd->filter_list, l, item_filter) - { - if ((item_filter->callback_func == func) - && ((!data) || (item_filter->data == data))) - { - sd->filter_list = eina_list_remove_list(sd->filter_list, l); - _filter_free(item_filter); - return; - } - } -} - -static void -_elm_multibuttonentry_class_constructor(Efl_Class *klass) -{ - evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); - - if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF) - _elm_multibuttonentry_smart_focus_next_enable = EINA_TRUE; -} - -EOLIAN static Eina_List* -_elm_multibuttonentry_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Multibuttonentry_Data *sd) -{ - Eina_List *ret; - ret = elm_interface_atspi_accessible_children_get(efl_super(obj, ELM_MULTIBUTTONENTRY_CLASS)); - return eina_list_merge(eina_list_clone(sd->items), ret); -} - -EOLIAN static const char* -_elm_multibuttonentry_item_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Multibuttonentry_Item_Data *item) -{ - const char *ret; - ret = elm_interface_atspi_accessible_name_get(efl_super(obj, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); - if (ret) return ret; - - const char *txt = elm_object_part_text_get(VIEW(item), "elm.btn.text"); - return txt; -} - -EOLIAN static Elm_Atspi_State_Set -_elm_multibuttonentry_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_it, Elm_Multibuttonentry_Item_Data *sd EINA_UNUSED) -{ - Elm_Atspi_State_Set ret; - Eina_Bool sel; - - ret = elm_interface_atspi_accessible_state_set_get(efl_super(eo_it, ELM_MULTIBUTTONENTRY_ITEM_CLASS)); - - sel = elm_obj_multibuttonentry_item_selected_get(eo_it); - - STATE_TYPE_SET(ret, ELM_ATSPI_STATE_EDITABLE); - - if (sel) - STATE_TYPE_SET(ret, ELM_ATSPI_STATE_CHECKED); - - return ret; -} - -static Eina_Bool -_key_action_activate(Eo *obj, const char *params EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it); - elm_layout_signal_emit(VIEW(it), "mouse,clicked,1", "elm"); - return EINA_TRUE; -} - -static Eina_Bool -_key_action_delete(Eo *obj, const char *params EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it); - elm_layout_signal_emit(VIEW(it), "elm,deleted", "elm"); - return EINA_TRUE; -} - -static Eina_Bool -_key_action_longpress(Eo *obj, const char *params EINA_UNUSED) -{ - ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it); - efl_event_callback_legacy_call - (WIDGET(it), ELM_MULTIBUTTONENTRY_EVENT_ITEM_LONGPRESSED, obj); - return EINA_TRUE; -} - -EOLIAN const Elm_Atspi_Action * -_elm_multibuttonentry_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Item_Data *pd EINA_UNUSED) -{ - static Elm_Atspi_Action atspi_actions[] = { - { "activate", NULL, NULL, _key_action_activate }, - { "delete", NULL, NULL, _key_action_delete}, - { "longpress", NULL, NULL, _key_action_longpress}, - { NULL, NULL, NULL, NULL} - }; - return &atspi_actions[0]; -} - -/* Efl.Part begin */ - -ELM_PART_OVERRIDE(elm_multibuttonentry, ELM_MULTIBUTTONENTRY, EFL_UI_LAYOUT, Elm_Multibuttonentry_Data, Elm_Part_Data) -ELM_PART_OVERRIDE_TEXT_SET(elm_multibuttonentry, ELM_MULTIBUTTONENTRY, EFL_UI_LAYOUT, Elm_Multibuttonentry_Data, Elm_Part_Data) -ELM_PART_OVERRIDE_TEXT_GET(elm_multibuttonentry, ELM_MULTIBUTTONENTRY, EFL_UI_LAYOUT, Elm_Multibuttonentry_Data, Elm_Part_Data) -#include "elm_multibuttonentry_internal_part.eo.c" - -/* Efl.Part end */ -/* Internal EO APIs and hidden overrides */ - -#define ELM_MULTIBUTTONENTRY_EXTRA_OPS \ - ELM_LAYOUT_SIZING_EVAL_OPS(elm_multibuttonentry), \ - EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_multibuttonentry) - -#include "elm_multibuttonentry_item.eo.c" -#include "elm_multibuttonentry.eo.c" diff --git a/src/lib/elementary/elc_multibuttonentry.h b/src/lib/elementary/elc_multibuttonentry.h index 75fe7a1b99..b878f7829c 100644 --- a/src/lib/elementary/elc_multibuttonentry.h +++ b/src/lib/elementary/elc_multibuttonentry.h @@ -59,7 +59,7 @@ #include "elc_multibuttonentry_common.h" #ifdef EFL_EO_API_SUPPORT -#include "elc_multibuttonentry_eo.h" +#include "efl_ui_multibuttonentry_eo.h" #endif #ifndef EFL_NOLEGACY_API_SUPPORT #include "elc_multibuttonentry_legacy.h" diff --git a/src/lib/elementary/elc_multibuttonentry_common.h b/src/lib/elementary/elc_multibuttonentry_common.h index b076385698..8601dbffcc 100644 --- a/src/lib/elementary/elc_multibuttonentry_common.h +++ b/src/lib/elementary/elc_multibuttonentry_common.h @@ -30,4 +30,4 @@ typedef Eina_Bool (*Elm_Multibuttonentry_Item_Filter_Cb)(Evas_ * * @ingroup Multibuttonentry */ -typedef char * (*Elm_Multibuttonentry_Format_Cb)(int count, void *data); +typedef char * (*Efl_Ui_Multibuttonentry_Format_Cb)(int count, void *data); diff --git a/src/lib/elementary/elc_multibuttonentry_eo.h b/src/lib/elementary/elc_multibuttonentry_eo.h deleted file mode 100644 index 4d958bd55b..0000000000 --- a/src/lib/elementary/elc_multibuttonentry_eo.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "elm_multibuttonentry_item.eo.h" -#include "elm_multibuttonentry.eo.h" diff --git a/src/lib/elementary/elc_multibuttonentry_legacy.h b/src/lib/elementary/elc_multibuttonentry_legacy.h index 84c66d1186..157ffb645a 100644 --- a/src/lib/elementary/elc_multibuttonentry_legacy.h +++ b/src/lib/elementary/elc_multibuttonentry_legacy.h @@ -10,4 +10,4 @@ EAPI Evas_Object *elm_multibuttonentry_add(Evas_Object *parent); #include "elm_multibuttonentry_item.eo.legacy.h" -#include "elm_multibuttonentry.eo.legacy.h" +#include "efl_ui_multibuttonentry.eo.legacy.h" diff --git a/src/lib/elementary/elm_multibuttonentry.eo b/src/lib/elementary/elm_multibuttonentry.eo deleted file mode 100644 index a0358b0ca6..0000000000 --- a/src/lib/elementary/elm_multibuttonentry.eo +++ /dev/null @@ -1,203 +0,0 @@ -type Elm_Multibuttonentry_Item_Filter_Cb: __undefined_type; [[Elementary multibuttonentry item filter callback type]] -type Elm_Multibuttonentry_Format_Cb: __undefined_type; [[Elementary multibuttonentry format callback type]] - -class Elm.Multibuttonentry (Efl.Ui.Layout) -{ - [[Elementary multibuttonentry class]] - legacy_prefix: elm_multibuttonentry; - eo_prefix: elm_obj_multibuttonentry; - event_prefix: elm_multibuttonentry; - methods { - @property editable { - [[Control if the multibuttonentry is to be editable or not. - - @since 1.7]] - set { - } - get { - } - values { - editable: bool; [[If $true, user can add/delete item in multibuttonentry, if not, the multibuttonentry is non-editable.]] - } - } - @property expanded { - [[Control the multibuttonentry to expanded state. - - In expanded state, the complete entry will be displayed. - Otherwise, only single line of the entry will be displayed.]] - set { - } - get { - } - values { - expanded: bool; [[The value of expanded state. Set this to $true for expanded state. Set - this to $false for single line state.]] - } - } - @property format_function { - set { - [[Set a function to format the string that will be used to display the hidden items counter. - - If $format_function is $NULL, the default format will be used, - which is $"... + %d". - - @since 1.9]] - } - values { - format_function: Elm_Multibuttonentry_Format_Cb @nullable; [[Format_function The actual format function]] - data: const(void_ptr) @optional; [[Data User data to passed to $format_function]] - } - } - @property items { - get { - [[Get a list of items in the multibuttonentry]] - - return: const(list); [[The list of items, or NULL if none]] - } - } - @property first_item { - get { - [[Get the first item in the multibuttonentry]] - - return: Elm.Widget.Item; [[The first item, or NULL if none]] - } - } - @property last_item { - get { - [[Get the last item in the multibuttonentry]] - - return: Elm.Widget.Item; [[The last item, or NULL if none]] - } - } - @property entry { - get { - [[Get the entry of the multibuttonentry object]] - - return: Efl.Canvas.Object; [[The entry object, or NULL if none]] - } - } - @property selected_item { - get { - [[Get the selected item in the multibuttonentry]] - - return: Elm.Widget.Item; [[The selected item, or NULL if none]] - } - } - item_prepend { - [[Prepend a new item to the multibuttonentry - - See @Elm.Widget.Item.del to delete the item.]] - - return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] - params { - @in label: string; [[The label of new item]] - @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] - @in data: void_ptr @optional; [[The pointer to the data to be attached]] - } - } - clear { - [[Remove all items in the multibuttonentry.]] - - } - item_filter_remove { - [[Remove a filter from the list - - Removes the given callback from the filter list. See elm_multibuttonentry_item_filter_append() - for more information.]] - - params { - @in func: Elm_Multibuttonentry_Item_Filter_Cb; [[The filter function to remove]] - @in data: void_ptr; [[The user data passed when adding the function]] - } - } - item_insert_before { - [[Add a new item to the multibuttonentry before the indicated object reference. - - See @Elm.Widget.Item.del to delete the item.]] - - return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] - params { - @in before: Elm.Widget.Item; [[The item before which to add it]] - @in label: string; [[The label of new item]] - @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] - @in data: void_ptr @optional; [[The pointer to the data to be attached]] - } - } - item_append { - [[Append a new item to the multibuttonentry - - See @Elm.Widget.Item.del to delete the item.]] - - return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] - params { - @in label: string; [[The label of new item]] - @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] - @in data: void_ptr @optional; [[The pointer to the data to be attached]] - } - } - item_filter_prepend { - [[Prepend a filter function for text inserted in the Multibuttonentry - - Prepend the given callback to the list. See elm_multibuttonentry_item_filter_append() - for more information]] - params { - @in func: Elm_Multibuttonentry_Item_Filter_Cb; [[The function to use as text filter]] - @in data: void_ptr; [[User data to pass to $func]] - } - } - item_filter_append { - [[Append an item filter function for text inserted in the Multibuttonentry - - Append the given callback to the list. This functions will be called - whenever any text is inserted into the Multibuttonentry, with the text to be inserted - as a parameter. The callback function is free to alter the text in any way - it wants, but it must remember to free the given pointer and update it. - If the new text is to be discarded, the function can free it and set it text - parameter to NULL. This will also prevent any following filters from being - called.]] - - params { - @in func: Elm_Multibuttonentry_Item_Filter_Cb; [[The function to use as item filter]] - @in data: void_ptr; [[User data to pass to $func]] - } - } - item_insert_after { - [[Add a new item to the multibuttonentry after the indicated object - - See @Elm.Widget.Item.del to delete the item.]] - - return: Elm.Widget.Item; [[A handle to the item added or NULL if not possible]] - params { - @in after: Elm.Widget.Item; [[The item after which to add it]] - @in label: string; [[The label of new item]] - @in func: Evas_Smart_Cb @optional; [[The callback function to be invoked when this item is pressed.]] - @in data: void_ptr @optional; [[The pointer to the data to be attached]] - } - } - } - implements { - class.constructor; - Efl.Object.constructor; - Elm.Widget.theme_apply; - Elm.Widget.focus_next_manager_is; - Elm.Widget.focus_direction_manager_is; - Elm.Widget.on_access_update; - Elm.Widget.focus_direction; - Elm.Widget.focus_next; - Elm.Widget.on_focus; - Elm.Widget.translate; - Elm.Widget.widget_event; - Elm.Interface.Atspi_Accessible.children { get; } - Efl.Part.part; - } - events { - item,selected; [[Called when item was selected]] - item,added; [[Called when item was added]] - item,deleted; [[Called when item was deleted]] - item,clicked; [[Called when item was clicked]] - item,longpressed; [[Called when item got a longpress]] - expanded; [[Called when expanded]] - contracted; [[Called when contracted]] - expand,state,changed; [[Called when expanded state changed]] - } -} diff --git a/src/lib/elementary/elm_multibuttonentry_internal_part.eo b/src/lib/elementary/elm_multibuttonentry_internal_part.eo deleted file mode 100644 index 44f1abe1af..0000000000 --- a/src/lib/elementary/elm_multibuttonentry_internal_part.eo +++ /dev/null @@ -1,9 +0,0 @@ -class Elm.Multibuttonentry.Internal.Part (Efl.Ui.Layout.Internal.Part, Efl.Text) -{ - [[Elementary multibuttonentry internal part class]] - data: null; - implements { - Efl.Text.text { set; get; } - } -} - diff --git a/src/lib/elementary/elm_widget_multibuttonentry.h b/src/lib/elementary/elm_widget_multibuttonentry.h deleted file mode 100644 index ca8b58e03e..0000000000 --- a/src/lib/elementary/elm_widget_multibuttonentry.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef ELM_WIDGET_MULTIBUTTONENTRY_H -#define ELM_WIDGET_MULTIBUTTONENTRY_H - -#include "elm_widget_layout.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-multibuttonentry-class The Elementary Multi Button Entry Class - * - * Elementary, besides having the @ref Multibuttonentry widget, - * exposes its foundation -- the Elementary Multi Button Entry Class -- - * in order to create other widgets which are a multi button entry with - * some more logic on top. - */ - -/** - * Base widget smart data extended with multibuttonentry instance data. - */ - -typedef enum _Multibuttonentry_Pos -{ - MULTIBUTTONENTRY_POS_START, - MULTIBUTTONENTRY_POS_END, - MULTIBUTTONENTRY_POS_BEFORE, - MULTIBUTTONENTRY_POS_AFTER, -} Multibuttonentry_Pos; - -typedef enum _Multibuttonentry_Button_State -{ - MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT, - MULTIBUTTONENTRY_BUTTON_STATE_SELECTED, -} Multibuttonentry_Button_State; - -typedef enum _MultiButtonEntry_Closed_Button_Type -{ - MULTIBUTTONENTRY_CLOSED_IMAGE, - MULTIBUTTONENTRY_CLOSED_LABEL -} MultiButtonEntry_Closed_Button_Type; - -typedef enum _Multibuttonentry_View_State -{ - MULTIBUTTONENTRY_VIEW_NONE, - MULTIBUTTONENTRY_VIEW_GUIDETEXT, - MULTIBUTTONENTRY_VIEW_ENTRY, - MULTIBUTTONENTRY_VIEW_SHRINK -} Multibuttonentry_View_State; - -typedef struct _Multibuttonentry_Item Elm_Multibuttonentry_Item_Data; - -struct _Multibuttonentry_Item -{ - Elm_Widget_Item_Data *base; - - Evas_Coord vw, rw; // vw: visual width, real width - Eina_Bool visible : 1; - Evas_Smart_Cb func; -}; - -typedef struct _Elm_Multibuttonentry_Item_Filter -{ - Elm_Multibuttonentry_Item_Filter_Cb callback_func; - void *data; -} Elm_Multibuttonentry_Item_Filter; - -typedef struct _Elm_Multibuttonentry_Data - Elm_Multibuttonentry_Data; -struct _Elm_Multibuttonentry_Data -{ - Evas_Object *parent; - Evas_Object *box; - Evas_Object *entry; - Evas_Object *label; - Evas_Object *guide_text; - Evas_Object *end; /* used to represent the - * total number of - * invisible buttons */ - - Eina_List *items; - Eina_List *filter_list; - Elm_Multibuttonentry_Item_Data *selected_it; /* selected item */ - Elm_Multibuttonentry_Item_Data *focused_it; - - Elm_Multibuttonentry_Format_Cb format_func; - const void *format_func_data; - - const char *label_str, *guide_text_str; - - int n_str; - Multibuttonentry_View_State view_state; - - Evas_Coord w_box, h_box; - int shrink; - - Elm_Multibuttonentry_Item_Filter_Cb add_callback; - void *add_callback_data; - - Eina_Bool last_it_select : 1; - Eina_Bool editable : 1; - Eina_Bool focused : 1; // avoids infinite loop on focus in/out - Eina_Bool label_packed : 1; - - Ecore_Timer *longpress_timer; -}; - -/** - * @} - */ - -#define ELM_MULTIBUTTONENTRY_DATA_GET(o, sd) \ - Elm_Multibuttonentry_Data *sd = efl_data_scope_get(o, ELM_MULTIBUTTONENTRY_CLASS); - -#define ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(o, ptr) \ - ELM_MULTIBUTTONENTRY_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_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ - Elm_Multibuttonentry_Data * ptr = efl_data_scope_get(o, ELM_MULTIBUTTONENTRY_CLASS); \ - if (EINA_UNLIKELY(!ptr)) \ - { \ - CRI("No widget data for object %p (%s)", \ - o, evas_object_type_get(o)); \ - return val; \ - } - -#define ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(o, sd) \ - Elm_Multibuttonentry_Item_Data *sd = efl_data_scope_get(o, ELM_MULTIBUTTONENTRY_ITEM_CLASS) - -#define ELM_MULTIBUTTONENTRY_CHECK(obj) \ - if (EINA_UNLIKELY(!efl_isa((obj), ELM_MULTIBUTTONENTRY_CLASS))) \ - return - -#define ELM_MULTIBUTTONENTRY_ITEM_CHECK(it) \ - if (EINA_UNLIKELY(!efl_isa((it->base->eo_obj), ELM_MULTIBUTTONENTRY_ITEM_CLASS))) \ - return - -#define ELM_MULTIBUTTONENTRY_ITEM_CHECK_OR_RETURN(it, ...) \ - if (EINA_UNLIKELY(!efl_isa((it->base->eo_obj), ELM_MULTIBUTTONENTRY_ITEM_CLASS))) \ - return __VA_ARGS__; - -#endif -- cgit v1.2.1