[spinner] Made changes for bezel less(pulse) spinner UX 54/196254/19 accepted/tizen/4.0/unified/20190214.144637 submit/tizen_4.0/20190214.082212
authorPrasoon Singh <prasoon.16@samsung.com>
Wed, 26 Dec 2018 14:35:53 +0000 (20:05 +0530)
committerWoochanlee <wc0917.lee@samsung.com>
Mon, 11 Feb 2019 06:54:14 +0000 (15:54 +0900)
Change-Id: I5abd2800491cda022f2fa42dde76f5fc66b1cd16
Signed-off-by: Prasoon Singh <prasoon.16@samsung.com>
Signed-off-by: Anuj Asher <anuj.asher@samsung.com>
Signed-off-by: Godly T.Alias <godlytalias@yahoo.co.in>
config/default/base.src.in
config/mobile/base.src.in
config/standard/base.src.in
src/lib/elm_config.c
src/lib/elm_datetime.c
src/lib/elm_gesture_layer.c
src/lib/elm_priv.h
src/lib/elm_spinner.c
src/lib/elm_widget_spinner.h

index 8bf5d89..7213250 100644 (file)
@@ -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";
index df06a0b..d8d90c4 100644 (file)
@@ -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";
index dbde6c9..c4131de 100644 (file)
@@ -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";
index 4eda6f9..ddd75e0 100644 (file)
@@ -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;
index e04da89..6325040 100644 (file)
@@ -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 */
index 568371a..eac7c43 100644 (file)
@@ -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;
index ec1ca3e..fe240cc 100644 (file)
@@ -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;
    //
index a163867..f814c39 100644 (file)
@@ -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
index 46662c3..1732c28 100644 (file)
@@ -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;
+};
+//
+
 /**
  * @}
  */