From 7f87b0917fac25e24a7c09b45031b10eb7fcd6c1 Mon Sep 17 00:00:00 2001 From: Prasoon Singh Date: Wed, 26 Dec 2018 20:05:53 +0530 Subject: [PATCH] [spinner] Made changes for bezel less(pulse) spinner UX Change-Id: I5abd2800491cda022f2fa42dde76f5fc66b1cd16 Signed-off-by: Prasoon Singh Signed-off-by: Anuj Asher Signed-off-by: Godly T.Alias --- config/default/base.src.in | 1 + config/mobile/base.src.in | 1 + config/standard/base.src.in | 1 + src/lib/elm_config.c | 2 + src/lib/elm_datetime.c | 2 - src/lib/elm_gesture_layer.c | 7 +- src/lib/elm_priv.h | 1 + src/lib/elm_spinner.c | 579 ++++++++++++++++++++++++++++++++++++++++++- src/lib/elm_widget_spinner.h | 22 ++ 9 files changed, 602 insertions(+), 14 deletions(-) diff --git a/config/default/base.src.in b/config/default/base.src.in index 8bf5d89..7213250 100644 --- a/config/default/base.src.in +++ b/config/default/base.src.in @@ -101,6 +101,7 @@ group "Elm_Config" struct { value "popup_vertical_align" double: 0.5; value "popup_scrollable" uchar: 0; value "spinner_min_max_filter_enable" uchar: 0; + value "list_spinner" uchar: 0; group "color_palette" list { group "Elm_Custom_Palette" struct { value "palette_name" string: "default"; diff --git a/config/mobile/base.src.in b/config/mobile/base.src.in index df06a0b..d8d90c4 100644 --- a/config/mobile/base.src.in +++ b/config/mobile/base.src.in @@ -105,6 +105,7 @@ group "Elm_Config" struct { value "popup_vertical_align" double: 0.5; value "popup_scrollable" uchar: 1; value "spinner_min_max_filter_enable" uchar: 1; + value "list_spinner" uchar: 0; group "color_palette" list { group "Elm_Custom_Palette" struct { value "palette_name" string: "default"; diff --git a/config/standard/base.src.in b/config/standard/base.src.in index dbde6c9..c4131de 100644 --- a/config/standard/base.src.in +++ b/config/standard/base.src.in @@ -102,6 +102,7 @@ group "Elm_Config" struct { value "popup_vertical_align" double: 0.5; value "popup_scrollable" uchar: 0; value "spinner_min_max_filter_enable" uchar: 0; + value "list_spinner" uchar: 0; group "color_palette" list { group "Elm_Custom_Palette" struct { value "palette_name" string: "default"; diff --git a/src/lib/elm_config.c b/src/lib/elm_config.c index 4eda6f9..ddd75e0 100644 --- a/src/lib/elm_config.c +++ b/src/lib/elm_config.c @@ -464,6 +464,7 @@ _desc_init(void) ELM_CONFIG_VAL(D, T, popup_vertical_align, T_DOUBLE); ELM_CONFIG_VAL(D, T, popup_scrollable, T_UCHAR); ELM_CONFIG_VAL(D, T, spinner_min_max_filter_enable, T_UCHAR); + ELM_CONFIG_VAL(D, T, list_spinner, T_UCHAR); // TIZEN_ONLY(20150705): Genlist item align feature ELM_CONFIG_VAL(D, T, scroll_item_align_enable, T_UCHAR); ELM_CONFIG_VAL(D, T, scroll_item_valign, T_STRING); @@ -1835,6 +1836,7 @@ _config_load(void) _elm_config->indicator_service_270 = eina_stringshare_add("elm_indicator_landscape"); _elm_config->disable_external_menu = EINA_FALSE; _elm_config->magnifier_enable = EINA_TRUE; + _elm_config->list_spinner = EINA_FALSE; _elm_config->spinner_min_max_filter_enable = EINA_FALSE; _elm_config->magnifier_scale = 1.5; _elm_config->audio_mute_effect = 0; diff --git a/src/lib/elm_datetime.c b/src/lib/elm_datetime.c index e04da89..6325040 100644 --- a/src/lib/elm_datetime.c +++ b/src/lib/elm_datetime.c @@ -64,9 +64,7 @@ static const char *ignore_separators = "()"; static const char *ignore_extensions = "E0_-O^#"; static Datetime_Mod_Api *dt_mod = NULL; -static const char SIG_CHANGED[] = "changed"; static const Evas_Smart_Cb_Description _smart_callbacks[] = { - {SIG_CHANGED, ""}, {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ diff --git a/src/lib/elm_gesture_layer.c b/src/lib/elm_gesture_layer.c index 568371a..eac7c43 100644 --- a/src/lib/elm_gesture_layer.c +++ b/src/lib/elm_gesture_layer.c @@ -615,7 +615,12 @@ _state_report(Gesture_Info *gesture, { Func_Data *cb_info; EINA_INLIST_FOREACH(gesture->cbs[gesture->state], cb_info) - flags |= cb_info->cb(cb_info->user_data, info); + { + if (!cb_info || !(cb_info->cb)) + return EVAS_EVENT_FLAG_NONE; + + flags |= cb_info->cb(cb_info->user_data, info); + } } return EVAS_EVENT_FLAG_NONE; diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h index ec1ca3e..fe240cc 100644 --- a/src/lib/elm_priv.h +++ b/src/lib/elm_priv.h @@ -321,6 +321,7 @@ struct _Elm_Config unsigned char win_auto_focus_animate; unsigned char naviframe_prev_btn_auto_pushed; unsigned char spinner_min_max_filter_enable; + unsigned char list_spinner; // TIZEN_ONLY(20170120): entry: Add configuration for the default value of select_allow unsigned char entry_select_allow; // diff --git a/src/lib/elm_spinner.c b/src/lib/elm_spinner.c index a163867..f814c39 100644 --- a/src/lib/elm_spinner.c +++ b/src/lib/elm_spinner.c @@ -31,7 +31,10 @@ static const char SIG_MAX_REACHED[] = "max,reached"; //TIZEN_ONLY(20160419): Spinner entry changed callback support for datetime UX. static const char SIG_ENTRY_CHANGED[] = "entry,changed"; // - +//TIZEN_ONLY(20191226): List Spinner feature +static const char SIG_GENLIST_SHOW[] = "genlist,show"; +static const char SIG_GENLIST_HIDE[] = "genlist,hide"; +// static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_CHANGED, ""}, {SIG_DELAY_CHANGED, ""}, @@ -46,6 +49,10 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */ {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ + //TIZEN_ONLY(20191226): List Spinner feature + {SIG_GENLIST_SHOW, ""}, + {SIG_GENLIST_HIDE, ""}, + // {NULL, NULL} }; @@ -72,6 +79,12 @@ _entry_unfocused_cb(void *data, Eo *obj EINA_UNUSED, static Eina_Bool _entry_activated_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED); +//TIZEN_ONLY(20191226): List Spinner feature +static Eina_Bool +_genlist_unfocused_cb(void *data, + Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, + void *event_info EINA_UNUSED); +// EO_CALLBACKS_ARRAY_DEFINE(_inc_dec_button_cb, { EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED, _inc_dec_button_clicked_cb}, @@ -199,6 +212,95 @@ apply: elm_object_text_set(sd->ent, buf); } +//TIZEN_ONLY(20191226): List Spinner feature +static char* +_get_genlist_item_buf(Elm_Spinner_Data *sd, double val) +{ + Eina_List *l; + Elm_Spinner_Special_Value *sv; + + Eina_Strbuf *buf; + char* ret; + buf = eina_strbuf_new(); + + char fmt[32] = "%0.f"; + + EINA_LIST_FOREACH(sd->special_values, l, sv) + { + if (sv->value == val) + { + eina_strbuf_append_printf(buf, "%s", sv->label); + goto apply; + } + } + /* try to construct just the format from given label + * completely ignoring pre/post words + */ + if (sd->label) + { + const char *start = strchr(sd->label, '%'); + while (start) + { + /* handle %% */ + if (start[1] != '%') + break; + else + start = strchr(start + 2, '%'); + } + + if (start) + { + const char *itr, *end = NULL; + for (itr = start + 1; *itr != '\0'; itr++) + { + /* allowing '%d' is quite dangerous, remove it? */ + if ((*itr == 'd') || (*itr == 'f')) + { + end = itr + 1; + break; + } + } + + if ((end) && ((size_t)(end - start + 1) < sizeof(fmt))) + { + memcpy(fmt, start, end - start); + fmt[end - start] = '\0'; + } + } + } + + if (_is_label_format_integer(fmt)) + eina_strbuf_append_printf(buf, fmt, (int)val); + else + eina_strbuf_append_printf(buf, fmt, val); + +apply: + ret = eina_strbuf_string_steal(buf); + eina_strbuf_free(buf); + return ret; +} + +static char * +_genlist_item_text_get_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *part) +{ + Elm_Spinner_Item_Data* sp_item_data = (Elm_Spinner_Item_Data*)data; + if (!(strcmp(part, "elm.text")) && sp_item_data) + return _get_genlist_item_buf(sp_item_data->spinner_data, sp_item_data->value); + return NULL; +} + +static void +_genlist_item_del_cb(void *data, Evas_Object *obj EINA_UNUSED) +{ + Elm_Spinner_Item_Data* sp_item_data = (Elm_Spinner_Item_Data*)data; + if (sp_item_data) + { + free(sp_item_data); + sp_item_data = NULL; + } +} +// + static void _label_write(Evas_Object *obj) { @@ -234,6 +336,7 @@ apply: elm_layout_text_set(obj, "elm.text", buf); elm_interface_atspi_accessible_name_changed_signal_emit(obj); + if (sd->entry_visible) _entry_show(sd); } @@ -473,6 +576,104 @@ _entry_value_apply(Evas_Object *obj) // } +//TIZEN_ONLY(20191226): List Spinner feature +static void +_genlist_scroll_anim_start_cb(void *data, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Elm_Spinner_Data* sd = (Elm_Spinner_Data*)data; + + sd->scrolling = EINA_TRUE; +} + +static void +_genlist_scroll_anim_stop_cb(void *data, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Elm_Spinner_Data* sd = (Elm_Spinner_Data*)data; + + sd->scrolling = EINA_FALSE; +} + +static void +_genlist_realized_cb(void *data, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + Elm_Object_Item* item = event_info; + Elm_Spinner_Data* sd = (Elm_Spinner_Data*)data; + + if (!item) return; + + if (item == sd->prev_item) + elm_object_item_signal_emit(sd->prev_item, "elm,state,up", "elm"); + else if (item == sd->next_item) + elm_object_item_signal_emit(sd->next_item, "elm,state,down", "elm"); +} + +static void +_genlist_hide(Evas_Object *obj) +{ + ELM_SPINNER_DATA_GET(obj, sd); + + if (sd->button_layout) + { + elm_layout_signal_emit(obj, "elm,state,button,active", "elm"); + evas_object_show(sd->text_button); + + elm_layout_signal_emit(obj, "elm,state,genlist,inactive", "elm"); + evas_object_hide(sd->genlist); + } + else + elm_layout_signal_emit(obj, "elm,state,inactive", "elm"); + + sd->genlist_visible = EINA_FALSE; +} + +static void +_genlist_item_value_apply(Evas_Object *obj) +{ + ELM_SPINNER_DATA_GET(obj, sd); + Elm_Spinner_Item_Data* sp_item_data; + double val; + + sp_item_data = elm_object_item_data_get(sd->aligned_item); + if (!sp_item_data) return; + + val = sp_item_data->value; + if ((fabs(val - sd->val) < DBL_EPSILON)) return; + + _value_set(obj, val, 0.0); +} + +static void +_genlist_value_apply(Evas_Object *obj) +{ + ELM_SPINNER_DATA_GET(obj, sd); + Evas_Coord x, y, h, y_center; + + if (!sd->genlist_visible) return; + + eo_do(sd->genlist, eo_event_callback_del + (ELM_WIDGET_EVENT_UNFOCUSED, _genlist_unfocused_cb, obj)); + evas_object_smart_callback_del(sd->genlist, "realized", _genlist_realized_cb); + evas_object_smart_callback_del(sd->genlist, "scroll,anim,start", _genlist_scroll_anim_start_cb); + evas_object_smart_callback_del(sd->genlist, "scroll,anim,stop", _genlist_scroll_anim_stop_cb); + + _genlist_hide(obj); + + evas_object_geometry_get(sd->genlist, &x, &y, NULL, &h); + y_center = y + h / 2; + sd->aligned_item = elm_genlist_at_xy_item_get(sd->genlist, x, y_center, NULL); + + _genlist_item_value_apply(obj); + sd->scrolling = EINA_FALSE;//anim_stop_cb not comes when genlist is hidden while scrolling is in progress + _label_write(obj); +} +// + static int _decimal_points_get(const char *label) { @@ -679,6 +880,148 @@ _entry_show_cb(void *data, // } +//TIZEN_ONLY(20191226): List Spinner feature +static void +_set_genlist_item_state(Elm_Spinner_Data* sd) +{ + if (sd->aligned_item == elm_genlist_first_item_get(sd->genlist)) + sd->prev_item = elm_genlist_last_item_get(sd->genlist); + else + sd->prev_item = elm_genlist_item_prev_get(sd->aligned_item); + + if (sd->prev_item) + elm_object_item_signal_emit(sd->prev_item, "elm,state,up", "elm"); + + if (sd->aligned_item == elm_genlist_last_item_get(sd->genlist)) + sd->next_item = elm_genlist_first_item_get(sd->genlist); + else + sd->next_item = elm_genlist_item_next_get(sd->aligned_item); + + if (sd->next_item) + elm_object_item_signal_emit(sd->next_item, "elm,state,down", "elm"); +} + +static void +_genlist_item_default_cb(void *data EINA_UNUSED, + Evas_Object *obj, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + ELM_SPINNER_DATA_GET(obj, sd); + + if (sd->prev_item) elm_object_item_signal_emit(sd->prev_item, "elm,state,set_default", "elm"); + if (sd->next_item) elm_object_item_signal_emit(sd->next_item, "elm,state,set_default", "elm"); + sd->prev_item = NULL; + sd->next_item = NULL; +} + +static void +_genlist_show_cb(void *data, + Evas *e EINA_UNUSED, + Evas_Object *obj, + void *event_info EINA_UNUSED) +{ + ELM_SPINNER_DATA_GET(data, sd); + + evas_object_smart_callback_call(data, SIG_GENLIST_SHOW, NULL); + + elm_object_focus_set(obj, EINA_TRUE); + sd->genlist_visible = EINA_TRUE; + elm_layout_signal_emit(data, "elm,state,button,inactive,anim", "elm"); + evas_object_hide(sd->text_button); + + if (sd->aligned_item) + elm_genlist_item_show(sd->aligned_item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE); + else + elm_genlist_item_show(elm_genlist_first_item_get(obj), ELM_GENLIST_ITEM_SCROLLTO_MIDDLE); +} + +static void +_toggle_genlist(Evas_Object *obj) +{ + ELM_SPINNER_DATA_GET(obj, sd); + + if (sd->dragging) + { + sd->dragging = 0; + return; + } + if (elm_widget_disabled_get(obj)) return; + if (!sd->editable) return; + + if (sd->genlist_visible) + { + _genlist_value_apply(obj); + evas_object_smart_callback_call(obj, SIG_GENLIST_HIDE, NULL); + } + else + { + if (!sd->genlist) + { + sd->itc = elm_genlist_item_class_new(); + sd->itc->item_style = elm_widget_style_get(obj); + sd->itc->func.text_get = _genlist_item_text_get_cb; + sd->itc->func.del = _genlist_item_del_cb; + + sd->genlist = elm_genlist_add(obj); + elm_widget_style_set(sd->genlist, "spinner"); + elm_genlist_mode_set(sd->genlist, ELM_LIST_COMPRESS); + elm_genlist_homogeneous_set(sd->genlist, EINA_TRUE); + elm_scroller_policy_set(sd->genlist, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + elm_layout_signal_callback_add(obj, "elm,set,default", "", + _genlist_item_default_cb, NULL); + elm_layout_content_set(obj, "elm.swallow.genlist", sd->genlist); + + evas_object_event_callback_add + (sd->genlist, EVAS_CALLBACK_SHOW, _genlist_show_cb, obj); + + double i = sd->val_min; + for (;i <= sd->val_max; i += sd->step) + { + Elm_Spinner_Item_Data* sp_item_data = calloc(1, sizeof(Elm_Spinner_Item_Data)); + + sp_item_data->value = i; + sp_item_data->spinner_data = sd; + + Elm_Object_Item* item = elm_genlist_item_append(sd->genlist, sd->itc, sp_item_data, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); + sd->genlist_items = eina_list_append(sd->genlist_items, item); + + if ((fabs(i - sd->val) < DBL_EPSILON)) + sd->aligned_item = item; + } + + elm_scroller_loop_set(sd->genlist, EINA_FALSE, sd->wrap); + if (!sd->wrap) + { + Elm_Genlist_Item_Class *padding_itc = elm_genlist_item_class_new(); + padding_itc->item_style = "spinner/padding"; + + elm_genlist_item_prepend(sd->genlist, padding_itc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); + elm_genlist_item_append(sd->genlist, padding_itc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); + elm_genlist_item_class_free(padding_itc); + } + } + + _set_genlist_item_state(sd); + sd->scrolling = EINA_FALSE; + + evas_object_smart_callback_add + (sd->genlist, "scroll,anim,start", _genlist_scroll_anim_start_cb, sd); + evas_object_smart_callback_add + (sd->genlist, "scroll,anim,stop", _genlist_scroll_anim_stop_cb, sd); + evas_object_smart_callback_add + (sd->genlist, "realized", _genlist_realized_cb, sd); + eo_do(sd->genlist, eo_event_callback_add + (ELM_WIDGET_EVENT_UNFOCUSED, _genlist_unfocused_cb, obj)); + + sd->genlist_visible = EINA_TRUE; + elm_layout_signal_emit(obj, "elm,state,genlist,active", "elm"); + elm_layout_signal_emit(sd->text_button, "elm,state,text,default", "elm"); + evas_object_show(sd->genlist); + } +} +// + static void _toggle_entry(Evas_Object *obj) { @@ -716,7 +1059,7 @@ _toggle_entry(Evas_Object *obj) (sd->ent, EVAS_CALLBACK_SHOW, _entry_show_cb, obj); //TIZEN_ONLY(20160419): Spinner entry changed callback support for datetime UX. evas_object_smart_callback_add - (sd->ent, "changed,user", _entry_changed_user_cb, obj); + (sd->ent, "changed,user", _entry_changed_user_cb, obj); // } elm_entry_single_line_set(sd->ent, EINA_TRUE); @@ -754,6 +1097,17 @@ _entry_toggle_cb(void *data EINA_UNUSED, _toggle_entry(obj); } +//TIZEN_ONLY(20191226): List Spinner feature +static void +_genlist_toggle_cb(void *data EINA_UNUSED, + Evas_Object *obj, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + _toggle_genlist(obj); +} +// + static Eina_Bool _spin_value(void *data) { @@ -822,7 +1176,22 @@ _key_action_toggle(Evas_Object *obj, const char *params EINA_UNUSED) ELM_SPINNER_DATA_GET(obj, sd); if (sd->spin_timer) _spin_stop(obj); - else if (sd->entry_visible) _entry_toggle_cb(NULL, obj, NULL, NULL); + //TIZEN_ONLY(20191226): List Spinner feature + //else if (sd->entry_visible) _entry_toggle_cb(NULL, obj, NULL, NULL); + else + { + if (!sd->list_spinner) + { + if (sd->entry_visible) + _entry_toggle_cb(NULL, obj, NULL, NULL); + } + else + { + if (sd->genlist_visible) + _genlist_toggle_cb(NULL, obj, NULL, NULL); + } + } + // return EINA_FALSE; } @@ -834,6 +1203,9 @@ _button_inc_dec_start_cb(void *data, const char *source EINA_UNUSED) { ELM_SPINNER_DATA_GET(data, sd); + //TIZEN_ONLY(20191226): List Spinner feature + if (sd->list_spinner) return; + // sd->inc_btn_activated = !strcmp(emission, "elm,action,increment,start") ? EINA_TRUE : EINA_FALSE; @@ -867,6 +1239,9 @@ _button_inc_dec_stop_cb(void *data, const char *source EINA_UNUSED) { ELM_SPINNER_DATA_GET(data, sd); + //TIZEN_ONLY(20191226): List Spinner feature + if (sd->list_spinner) return; + // if (sd->longpress_timer) { @@ -1011,7 +1386,11 @@ _text_button_focused_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) { - _toggle_entry(data); + //TIZEN_ONLY(20191226): List Spinner feature + ELM_SPINNER_DATA_GET(data, sd); + if (!sd->list_spinner) + // + _toggle_entry(data); return EINA_TRUE; } @@ -1035,6 +1414,18 @@ _entry_unfocused_cb(void *data, return EINA_TRUE; } +//TIZEN_ONLY(20191226): List Spinner feature +static Eina_Bool +_genlist_unfocused_cb(void *data, + Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + _toggle_genlist(data); + + return EINA_TRUE; +} +// + static Eina_Bool _text_button_clicked_cb(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, @@ -1042,8 +1433,22 @@ _text_button_clicked_cb(void *data, { ELM_SPINNER_DATA_GET(data, sd); - if (sd->entry_visible) return EINA_TRUE; - _toggle_entry(data); + //TIZEN_ONLY(20191226): List Spinner feature + //if (sd->entry_visible) return EINA_TRUE; + // _toggle_entry(data); + if (!sd->list_spinner) + { + if (sd->entry_visible) + return EINA_TRUE; + _toggle_entry(data); + } + else + { + if (sd->genlist_visible) + return EINA_TRUE; + _toggle_genlist(data); + } + // return EINA_TRUE; } @@ -1097,7 +1502,11 @@ _elm_spinner_elm_widget_on_focus(Eo *obj, Elm_Spinner_Data *sd, Elm_Object_Item { if (sd->entry_reactivate) { - _toggle_entry(obj); + if (sd->list_spinner) + _toggle_genlist(obj); + else + _toggle_entry(obj); + sd->entry_reactivate = EINA_FALSE; } } @@ -1192,8 +1601,16 @@ _access_activate_spinner_cb(void *data, ELM_SPINNER_DATA_GET(data, sd); if (elm_widget_disabled_get(data)) return; - if (!sd->entry_visible) + + //TIZEN_ONLY(20191226): List Spinner feature + //if (!sd->entry_visible) + // _toggle_entry(data); + if (!sd->entry_visible && !sd->list_spinner) _toggle_entry(data); + + if (!sd->genlist_visible && sd->list_spinner) + _toggle_genlist(data); + // } static void @@ -1337,6 +1754,17 @@ _elm_spinner_evas_object_smart_add(Eo *obj, Elm_Spinner_Data *priv) priv->editable = EINA_TRUE; // + //TIZEN_ONLY(20191226): List Spinner feature + if (_elm_config->list_spinner) + priv->list_spinner = EINA_TRUE; + + if (priv->list_spinner) + { + priv->wrap = EINA_TRUE; + priv->aligned_item = NULL; + } + // + if (!elm_layout_theme_set(obj, "spinner", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); @@ -1428,8 +1856,14 @@ _elm_spinner_evas_object_smart_add(Eo *obj, Elm_Spinner_Data *priv) edje_object_part_drag_value_set (wd->resize_obj, "elm.dragable.slider", 0.0, 0.0); - elm_layout_signal_callback_add - (obj, "elm,action,entry,toggle", "*", _entry_toggle_cb, NULL); + //TIZEN_ONLY(20191226): List Spinner feature + if (priv->list_spinner) + elm_layout_signal_callback_add + (obj, "elm,action,genlist,toggle", "*", _genlist_toggle_cb, NULL); + else + // + elm_layout_signal_callback_add + (obj, "elm,action,entry,toggle", "*", _entry_toggle_cb, NULL); _label_write(obj); elm_widget_can_focus_set(obj, EINA_TRUE); @@ -1450,7 +1884,13 @@ _elm_spinner_evas_object_smart_del(Eo *obj, Elm_Spinner_Data *sd) ecore_timer_del(sd->delay_change_timer); ecore_timer_del(sd->spin_timer); ecore_timer_del(sd->longpress_timer); - + //TIZEN_ONLY(20191226): List Spinner feature + if (sd->list_spinner) + { + if (sd->itc) elm_genlist_item_class_free(sd->itc); + eina_list_free(sd->genlist_items); + } + // if (sd->special_values) { EINA_LIST_FREE(sd->special_values, sv) @@ -1591,6 +2031,62 @@ _access_object_get(const Evas_Object *obj, const char* part) return ao; } +//TIZEN_ONLY(20191226): List Spinner feature +static void +_update_genlist_items(Elm_Spinner_Data *sd) +{ + if (!sd->genlist) return; + + elm_genlist_clear(sd->genlist); + eina_list_free(sd->genlist_items); + sd->genlist_items = NULL; + evas_object_smart_callback_add + (sd->genlist, "realized", _genlist_realized_cb, sd); + + double i = sd->val_min; + for (;i <= sd->val_max; i += sd->step) + { + Elm_Spinner_Item_Data* sp_item_data = calloc(1, sizeof(Elm_Spinner_Item_Data)); + sp_item_data->value = i; + sp_item_data->spinner_data = sd; + + Elm_Object_Item* item = elm_genlist_item_append(sd->genlist, sd->itc, sp_item_data, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); + sd->genlist_items = eina_list_append(sd->genlist_items, item); + + if ((fabs(i - sd->val) < FLT_EPSILON)) + sd->aligned_item = item; + } + + _set_genlist_item_state(sd); +} + +static void +_update_genlist_aligned_item(Elm_Spinner_Data *sd) +{ + if (!sd->genlist || !sd->genlist_items) return; + + Eina_List *l; + Elm_Object_Item *item = NULL; + Elm_Spinner_Item_Data* sp_item_data = NULL; + + EINA_LIST_FOREACH(sd->genlist_items, l, item) + { + sp_item_data = elm_object_item_data_get(item); + if (sp_item_data && sp_item_data->value == sd->val) + { + sd->aligned_item = item; + break; + } + } + + if (sd->genlist_visible) + elm_genlist_item_show(sd->aligned_item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE); + + evas_object_smart_callback_add + (sd->genlist, "realized", _genlist_realized_cb, sd); +} +// + EOLIAN static Eina_Bool _elm_spinner_elm_widget_focus_next(Eo *obj, Elm_Spinner_Data *_pd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item) { @@ -1715,9 +2211,16 @@ _elm_spinner_min_max_set(Eo *obj, Elm_Spinner_Data *sd, double min, double max) evas_object_smart_callback_call(obj, SIG_CHANGED, NULL); } // + //TIZEN_ONLY(20160419): Added entry filter feature. _entry_accept_filter_add(obj); // + + //TIZEN_ONLY(20191226): List Spinner feature + if (sd->list_spinner) + _update_genlist_items(sd); + // + } EOLIAN static void @@ -1763,6 +2266,11 @@ _elm_spinner_value_set(Eo *obj, Elm_Spinner_Data *sd, double val) sd->val_updated = EINA_TRUE; } + //TIZEN_ONLY(20191226): List Spinner feature + if (sd->list_spinner) + _update_genlist_aligned_item(sd); + // + _val_set(obj); _label_write(obj); //TIZEN_ONLY(20160419): Changed smart callback call for value update. @@ -1773,13 +2281,62 @@ _elm_spinner_value_set(Eo *obj, Elm_Spinner_Data *sd, double val) EOLIAN static double _elm_spinner_value_get(Eo *obj EINA_UNUSED, Elm_Spinner_Data *sd) { + //TIZEN_ONLY(20191226): List Spinner feature + if (sd->list_spinner) + { + if (sd->genlist && sd->scrolling) + { + Evas_Coord x, y, h, y_center; + evas_object_geometry_get(sd->genlist, &x, &y, NULL, &h); + y_center = y + h / 2; + sd->aligned_item = elm_genlist_at_xy_item_get(sd->genlist, x, y_center, NULL); + + _genlist_item_value_apply(obj); + } + } + // return sd->val; } EOLIAN static void _elm_spinner_wrap_set(Eo *obj EINA_UNUSED, Elm_Spinner_Data *sd, Eina_Bool wrap) { + //TIZEN_ONLY(20191226): List Spinner feature + wrap = !!wrap; + if (sd->wrap == wrap) return; + // sd->wrap = wrap; + + //TIZEN_ONLY(20191226): List Spinner feature + if (sd->list_spinner) + { + if (sd->genlist) + { + elm_scroller_loop_set(sd->genlist, EINA_FALSE, sd->wrap); + if (sd->wrap) + { + Elm_Object_Item *it = elm_genlist_first_item_get(sd->genlist); + if (it) + { + const Elm_Genlist_Item_Class *itc = elm_genlist_item_item_class_get(it); + if (itc->item_style && !strncmp(itc->item_style, "spinner/padding", strlen("spinner/padding"))) + { + elm_object_item_del(it); + elm_object_item_del(elm_genlist_last_item_get(sd->genlist)); + } + } + } + else + { + Elm_Genlist_Item_Class *padding_itc = elm_genlist_item_class_new(); + padding_itc->item_style = "spinner/padding"; + elm_genlist_item_prepend(sd->genlist, padding_itc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); + elm_genlist_item_append(sd->genlist, padding_itc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); + elm_genlist_item_class_free(padding_itc); + } + } + } + // } EOLIAN static Eina_Bool diff --git a/src/lib/elm_widget_spinner.h b/src/lib/elm_widget_spinner.h index 46662c3..1732c28 100644 --- a/src/lib/elm_widget_spinner.h +++ b/src/lib/elm_widget_spinner.h @@ -41,6 +41,11 @@ struct _Elm_Spinner_Data double drag_prev_pos, drag_val_step; double spin_speed, interval, first_interval; Evas_Object *ent, *inc_button, *dec_button, *text_button; + //TIZEN_ONLY(20191226): List Spinner feature + Evas_Object *genlist, *g_rect; + Elm_Genlist_Item_Class *itc; + Elm_Object_Item *aligned_item, *next_item, *prev_item; + // const char *label; int round; int decimal_points; @@ -49,6 +54,9 @@ struct _Elm_Spinner_Data Ecore_Timer *longpress_timer; /**< a timer to detect long press. After lonpress timeout, start continuous change of values until mouse up */ Eina_List *special_values; + //TIZEN_ONLY(20191226): List Spinner feature + Eina_List *genlist_items; + // Elm_Spinner_Format_Type format_type; Eina_Bool entry_visible : 1; @@ -57,9 +65,14 @@ struct _Elm_Spinner_Data Eina_Bool dragging : 1; Eina_Bool editable : 1; Eina_Bool wrap : 1; + Eina_Bool list_spinner : 1; Eina_Bool val_updated : 1; Eina_Bool button_layout : 1; Eina_Bool inc_btn_activated: 1; + //TIZEN_ONLY(20191226): List Spinner feature + Eina_Bool scrolling: 1; + Eina_Bool genlist_visible : 1; + // }; typedef struct _Elm_Spinner_Special_Value Elm_Spinner_Special_Value; @@ -69,6 +82,15 @@ struct _Elm_Spinner_Special_Value const char *label; }; +//TIZEN_ONLY(20191226): List Spinner feature +typedef struct _Elm_Spinner_Item_Data Elm_Spinner_Item_Data; +struct _Elm_Spinner_Item_Data +{ + double value; + Elm_Spinner_Data *spinner_data; +}; +// + /** * @} */ -- 2.7.4