wearable/slider: add tap & drag features 45/196645/1
authorBowon Ryu <bowon.ryu@samsung.com>
Thu, 3 Jan 2019 06:42:55 +0000 (15:42 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Thu, 3 Jan 2019 06:58:50 +0000 (15:58 +0900)
Change-Id: I87217521bc9037c366af8cce370f8a3ea9b2fe1d
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
inc/wearable/circle/efl_extension_circle_private.h
src/wearable/circle/efl_extension_circle_object.c
src/wearable/circle/efl_extension_circle_object_item.c
src/wearable/circle/efl_extension_circle_object_slider.c

index fdb1e3876686360289b6ccf2b5c3f07ee68b5c58..f45c7c0b7da74efc76537f4f757f9874449335dc 100644 (file)
@@ -179,11 +179,26 @@ struct _Eext_Circle_Object_Progressbar_Data {
 typedef struct _Eext_Circle_Object_Slider_Data Eext_Circle_Object_Slider_Data;
 struct _Eext_Circle_Object_Slider_Data {
    double value_step;
-
+   Evas_Object *parent;
+   Evas_Object *hit_rect;
    Eext_Circle_Color color;
    Eext_Circle_Color bg_color;
    Eext_Circle_Color disabled_color;
    Eext_Circle_Color disabled_bg_color;
+   Eext_Circle_Color cue_color;
+   Eext_Circle_Color cue_press_color;
+   unsigned int rotary_event_time_stamp;
+   Evas_Point pressed_point;
+   double prev_angle;
+   struct {
+      Ecore_Animator *animator;
+      int             from_line_width;
+      Eina_Bool       showing : 1;
+   } cue_effect_transit;
+   Eina_Bool drag : 1;
+   Eina_Bool tap : 1;
+   Eina_Bool freeze : 1;
+   Eina_Bool rotary: 1;
 };
 
 /* Genlist widget data */
@@ -254,6 +269,8 @@ double _eext_circle_object_item_value_angle_get(const Eext_Circle_Object_Item *i
 
 double _eext_circle_object_item_angle_value_get(const Eext_Circle_Object_Item *item, double angle);
 
+double _eext_circle_object_item_angle_value_get_round(const Eext_Circle_Object_Item *item, double angle);
+
 const char *_eext_circle_text_font_get(const char *text, const char *font_family);
 
 void _eext_circle_object_item_name_set(Eext_Circle_Object_Item *item, const char *name);
@@ -280,6 +297,8 @@ int _eext_circle_object_item_line_width_get(const Eext_Circle_Object_Item *item)
 
 void _eext_circle_object_item_angle_set(Eext_Circle_Object_Item *item, double angle);
 
+void _eext_circle_object_item_angle_set_round(Eext_Circle_Object_Item *item, double angle);
+
 double _eext_circle_object_item_angle_get(const Eext_Circle_Object_Item *item);
 
 void _eext_circle_object_item_angle_offset_set(Eext_Circle_Object_Item *item, double angle_offset);
@@ -363,6 +382,8 @@ void _eext_circle_object_show(Eext_Circle_Object *obj);
 void _eext_circle_object_bg_file_path_set(Eext_Circle_Object *obj, const char *path);
 const char *_eext_circle_object_bg_file_path_get(Eext_Circle_Object *obj);
 
+void _eext_circle_object_angle_set_round(Evas_Object *obj, double angle);
+
 /**
  * @}
  */
index 18623b6d7523be23291ba1f43abed21eca4b10a9..d9f1c66acd5a289e8af95c0acee4657b6a115ff6 100644 (file)
@@ -309,6 +309,19 @@ _eext_circle_object_bg_file_path_get(Eext_Circle_Object *obj)
    return obj->bg_file_path;
 }
 
+void
+_eext_circle_object_angle_set_round(Evas_Object *obj, double angle)
+{
+   Eext_Circle_Object_Item *item = NULL;
+
+   EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return;
+
+   item = _eext_circle_object_item_get(circle_obj, "default");
+
+   if (item)
+     _eext_circle_object_item_angle_set_round(item, angle);
+}
+
 /////////////////////////////////////////////////
 // EAPI /////////////////////////////////////////
 /////////////////////////////////////////////////
index 5b6a2fe3453e6722f01b57d7492e494a936992cc..ca3fda26854b462de3dfb587729dee3c60a6fc75 100644 (file)
@@ -18,6 +18,8 @@
 #include "efl_extension_private.h"
 #include "wearable/circle/efl_extension_circle_private.h"
 
+static const char SIG_VALUE_CHANGED[] = "value,changed";
+static Eina_Bool _eext_circle_object_item_value_set_internal(Eext_Circle_Object_Item *item, double value, Eina_Bool angle_update);
 static void _eext_circle_object_item_color_transit_animator_del(Eext_Circle_Object_Item *item);
 static void _eext_circle_object_item_angle_transit_animator_del(Eext_Circle_Object_Item *item);
 
@@ -97,7 +99,7 @@ _eext_circle_object_item_angle_transit_animator_cb(void *data, double pos)
 static Eina_Bool
 _eext_circle_object_item_angle_set_internal(Eext_Circle_Object_Item *item, double angle)
 {
-   double temp_angle;
+   double temp_angle, value;
 
    if (item->angle == angle) return EINA_FALSE;
 
@@ -109,7 +111,29 @@ _eext_circle_object_item_angle_set_internal(Eext_Circle_Object_Item *item, doubl
    if (item->angle == temp_angle) return EINA_FALSE;
 
    item->angle = temp_angle;
-   item->value = _eext_circle_object_item_angle_value_get(item, item->angle);
+   value = _eext_circle_object_item_angle_value_get(item, item->angle);
+   _eext_circle_object_item_value_set_internal(item, value, EINA_TRUE);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_eext_circle_object_item_angle_set_round_internal(Eext_Circle_Object_Item *item, double angle)
+{
+   double temp_angle, value;
+
+   if (item->angle == angle) return EINA_FALSE;
+
+   temp_angle = angle;
+
+   if (angle < item->min_angle) temp_angle = item->min_angle;
+   if (angle > item->max_angle) temp_angle = item->max_angle;
+
+   if (item->angle == temp_angle) return EINA_FALSE;
+
+   item->angle = temp_angle;
+   value = _eext_circle_object_item_angle_value_get_round(item, item->angle);
+   _eext_circle_object_item_value_set_internal(item, value, EINA_FALSE);
 
    return EINA_TRUE;
 }
@@ -125,8 +149,9 @@ _eext_circle_object_item_angle_offset_set_internal(Eext_Circle_Object_Item *item
 }
 
 static Eina_Bool
-_eext_circle_object_item_value_set_internal(Eext_Circle_Object_Item *item, double value)
+_eext_circle_object_item_value_set_internal(Eext_Circle_Object_Item *item, double value, Eina_Bool angle_update)
 {
+   Eext_Circle_Object *obj = item->obj;
    double angle;
 
    if (item->value == value) return EINA_FALSE;
@@ -136,6 +161,11 @@ _eext_circle_object_item_value_set_internal(Eext_Circle_Object_Item *item, doubl
    if (item->value < item->min_value) item->value = item->min_value;
    if (item->value > item->max_value) item->value = item->max_value;
 
+   if (obj)
+     evas_object_smart_callback_call(obj->main_obj, SIG_VALUE_CHANGED, NULL);
+
+   if (!angle_update) return EINA_TRUE;
+
    angle = _eext_circle_object_item_value_angle_get(item, item->value);
 
    if (item->angle == angle) return EINA_FALSE;
@@ -282,6 +312,24 @@ _eext_circle_object_item_angle_value_get(const Eext_Circle_Object_Item *item, do
    return value;
 }
 
+double
+_eext_circle_object_item_angle_value_get_round(const Eext_Circle_Object_Item *item, double angle)
+{
+   double value;
+
+   value = item->min_value;
+   if (item->max_angle != item->min_angle)
+     value += (angle - item->min_angle) * (item->max_value - item->min_value) / (item->max_angle - item->min_angle);
+
+   value += 0.5;
+   value = (int)value;
+
+   if (value < item->min_value) value = item->min_value;
+   if (value > item->max_value) value = item->max_value;
+
+   return value;
+}
+
 const char *
 _eext_circle_text_font_get(const char *text, const char *font_family)
 {
@@ -571,6 +619,25 @@ _eext_circle_object_item_angle_set(Eext_Circle_Object_Item *item, double angle)
      }
 }
 
+void
+_eext_circle_object_item_angle_set_round(Eext_Circle_Object_Item *item, double angle)
+{
+   if (!item) return;
+
+   if (item->angle_transit.animator_cb)
+     {
+        _eext_circle_object_item_angle_transit_animator_del(item);
+        item->draw.angle = item->angle;
+        _eext_circle_object_changed(item->obj);
+     }
+
+   if (_eext_circle_object_item_angle_set_round_internal(item, angle))
+     {
+        item->draw.angle = item->angle;
+        _eext_circle_object_changed(item->obj);
+     }
+}
+
 double
 _eext_circle_object_item_angle_get(const Eext_Circle_Object_Item *item)
 {
@@ -602,7 +669,7 @@ _eext_circle_object_item_angle_offset_get(const Eext_Circle_Object_Item *item)
 void
 _eext_circle_object_item_angle_min_max_set(Eext_Circle_Object_Item *item, double min_angle, double max_angle)
 {
-   double angle = 0.0;
+   double angle = 0.0, value;
 
    if (!item) return;
 
@@ -624,7 +691,8 @@ _eext_circle_object_item_angle_min_max_set(Eext_Circle_Object_Item *item, double
    if (item->angle == angle) return;
 
    item->angle = angle;
-   item->value = _eext_circle_object_item_angle_value_get(item, item->angle);
+   value = _eext_circle_object_item_angle_value_get(item, item->angle);
+   _eext_circle_object_item_value_set_internal(item, value, EINA_TRUE);
    item->draw.angle = item->angle;
 
    _eext_circle_object_changed(item->obj);
@@ -664,8 +732,10 @@ _eext_circle_object_item_value_min_max_set(Eext_Circle_Object_Item *item, double
    item->min_value = min_value;
    item->max_value = max_value;
 
-   if (item->value < item->min_value) item->value = item->min_value;
-   if (item->value > item->max_value) item->value = item->max_value;
+   if (item->value < item->min_value)
+     _eext_circle_object_item_value_set_internal(item, item->min_value, EINA_TRUE);
+   if (item->value > item->max_value)
+     _eext_circle_object_item_value_set_internal(item, item->max_value, EINA_TRUE);
 
    angle = _eext_circle_object_item_value_angle_get(item, item->value);
 
@@ -704,7 +774,7 @@ _eext_circle_object_item_value_set(Eext_Circle_Object_Item *item, double value)
         _eext_circle_object_changed(item->obj);
      }
 
-   if (_eext_circle_object_item_value_set_internal(item, value))
+   if (_eext_circle_object_item_value_set_internal(item, value, EINA_TRUE))
      {
         item->draw.angle = item->angle;
         _eext_circle_object_changed(item->obj);
@@ -921,6 +991,7 @@ _eext_circle_object_item_angle_transit_set(Eext_Circle_Object_Item *item, double
                                            double cubic_bezier_p2_x, double cubic_bezier_p2_y)
 {
    Eina_Bool ret;
+   double value;
 
    if (!item) return;
 
@@ -931,7 +1002,10 @@ _eext_circle_object_item_angle_transit_set(Eext_Circle_Object_Item *item, double
                                                              cubic_bezier_p2_x, cubic_bezier_p2_y);
 
    if (ret)
-     item->value = _eext_circle_object_item_angle_value_get(item, item->angle);
+     {
+        value = _eext_circle_object_item_angle_value_get(item, item->angle);
+        _eext_circle_object_item_value_set_internal(item, value, EINA_TRUE);
+     }
 }
 
 void
@@ -956,7 +1030,7 @@ _eext_circle_object_item_value_transit_set(Eext_Circle_Object_Item *item, double
                                                              cubic_bezier_p2_x, cubic_bezier_p2_y);
 
    if (ret)
-     item->value = to_value;
+     _eext_circle_object_item_value_set_internal(item, to_value, EINA_TRUE);
 }
 
 void
index 4d5467545789e7ab97330d03a6db6229784506d3..c4a8d8ad71366a8b2111928c2a914ab76f0d9f5e 100644 (file)
 #include "efl_extension.h"
 #include "efl_extension_private.h"
 #include "wearable/circle/efl_extension_circle_private.h"
+#include "math.h"
 
 #define EEXT_CIRCLE_OBJECT_SLIDER_TYPE "Eext_Circle_Object_Slider"
 
-#define SLIDER_TRANSIT_TIME 0.3
+#define SLIDER_ROTARY_EVENT_TIME_STAMP_THRESHOLD 500
+#define SLIDER_ROTARY_EVENT_ACCELERATION_TIME_DIFF 100
+#define SLIDER_ROTARY_EVENT_VALUE_MULTIPLYER 1
+
+#define SLIDER_TRANSIT_TIME 0.2
+#define SLIDER_TOUCH_AREA_SIZE 50
+#define SLIDER_WIDTH_SIZE 6
+#define SLIDER_RADIUS_SIZE 174
+#define SLIDER_CENTER_POINT 180
+#define SLIDER_CUE_SIZE 0.1
+#define SLIDER_CUE_OFFSET 0.05
+#define SLIDER_CUE_SHOWN_WIDTH 56
+#define SLIDER_CUE_HIDDEN_WIDTH 14
 
 #define EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, data) \
       Eext_Circle_Object_Slider_Data *data = NULL; \
@@ -31,6 +44,8 @@
 
 #define SLIDER_ITEM_NAME "default"
 #define SLIDER_BG_ITEM_NAME "bg"
+#define SLIDER_CUE_ITEM_NAME "cue"
+#define SLIDER_CUE_EFFECT_ITEM_NAME "effect"
 
 #define SLIDER_COLOR_R 77
 #define SLIDER_COLOR_G 207
 #define SLIDER_BG_COLOR_DISABLED_B 64
 #define SLIDER_BG_COLOR_DISABLED_A 255
 
-#define SLIDER_WIDTH_SIZE 8
-#define SLIDER_RADIUS_SIZE 176
+#define SLIDER_CUE_COLOR_R 77
+#define SLIDER_CUE_COLOR_G 207
+#define SLIDER_CUE_COLOR_B 255
+#define SLIDER_CUE_COLOR_A 255
+
+#define SLIDER_CUE_EFFECT_COLOR_R 77
+#define SLIDER_CUE_EFFECT_COLOR_G 207
+#define SLIDER_CUE_EFFECT_COLOR_B 255
+#define SLIDER_CUE_EFFECT_COLOR_A 128
 
 static const char SIG_VALUE_CHANGED[] = "value,changed";
+static const double durations[4] = {0.3, 0.4, 0.5, 0.6};
+
+static Eina_Bool _eext_circle_object_slider_value_transit_set_internal(Evas_Object *obj, double value);
+
+static double
+_angle_calculate(Evas_Object *obj, Evas_Coord mouse_x, Evas_Coord mouse_y)
+{
+   const double radian_value = 180.0/M_PI; // 1 radian
+   Evas_Coord_Point center = {0,0};
+   center.x = SLIDER_CENTER_POINT;
+   center.y = SLIDER_CENTER_POINT;
+
+   double default_angle = 0.0;
+   Evas_Coord dx = abs(center.x - mouse_x);
+   Evas_Coord dy = abs(center.y - mouse_y);
+   double radian = 0.0;
+
+   if (center.x <= mouse_x && center.y > mouse_y)
+     {
+       // 1 quadrant
+       radian = atan2(dx, dy);
+     }
+   else if (center.x < mouse_x && center.y <= mouse_y)
+     {
+       // 2 quadrant
+       default_angle = 90.0;
+       radian = atan2(dy, dx);
+     }
+   else if (center.x >= mouse_x && center.y < mouse_y)
+     {
+       // 3 quadrant
+       default_angle = 180.0;
+       radian = atan2(dx, dy);
+     }
+   else if (center.x > mouse_x && center.y >= mouse_y)
+     {
+       // 4 quadrant
+       default_angle = 270.0;
+       radian = atan2(dy, dx);
+     }
+
+   return default_angle + (radian_value * radian);
+}
+
+static void
+_angle_drag_set(Evas_Object *obj, double new_angle)
+{
+   EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   Eext_Circle_Object_Item *cue_item, *effect_item;
+   cue_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_ITEM_NAME);
+   effect_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_EFFECT_ITEM_NAME);
+   double current_angle = eext_circle_object_angle_get(obj);
+   double current_value = eext_circle_object_value_get(obj);
+
+   Eina_Bool pass_top = abs(new_angle - widget_data->prev_angle) > 180.0 ? EINA_TRUE : EINA_FALSE;
+   if (widget_data->freeze)
+     {
+       if (pass_top &&
+           ((current_angle == 360.0 && new_angle > widget_data->prev_angle)
+            || (current_angle == 0.0 && new_angle < widget_data->prev_angle)))
+         {
+            widget_data->freeze = EINA_FALSE;
+            _eext_circle_object_angle_set_round(obj, new_angle);
+            _eext_circle_object_item_angle_offset_set(effect_item, new_angle - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(effect_item, SLIDER_CUE_SIZE);
+            _eext_circle_object_item_angle_offset_set(cue_item, new_angle - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(cue_item, SLIDER_CUE_SIZE);
+         }
+     }
+   else
+     {
+       if (widget_data->prev_angle == -1.0 || !pass_top)
+         {
+            _eext_circle_object_angle_set_round(obj, new_angle);
+            _eext_circle_object_item_angle_offset_set(effect_item, new_angle - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(effect_item, SLIDER_CUE_SIZE);
+            _eext_circle_object_item_angle_offset_set(cue_item, new_angle - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(cue_item, SLIDER_CUE_SIZE);
+         }
+       else if (current_angle > 180.0)
+         {
+            _eext_circle_object_angle_set_round(obj, 360.0);
+            _eext_circle_object_item_angle_offset_set(effect_item, 360.0 - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(effect_item, SLIDER_CUE_SIZE);
+            _eext_circle_object_item_angle_offset_set(cue_item, 360.0 - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(cue_item, SLIDER_CUE_SIZE);
+            widget_data->freeze = EINA_TRUE;
+         }
+       else
+         {
+            _eext_circle_object_angle_set_round(obj, 0.0);
+            _eext_circle_object_item_angle_offset_set(effect_item, 0.0 - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(effect_item, SLIDER_CUE_SIZE);
+            _eext_circle_object_item_angle_offset_set(cue_item, 0.0 - SLIDER_CUE_OFFSET);
+            _eext_circle_object_item_angle_set(cue_item, SLIDER_CUE_SIZE);
+            widget_data->freeze = EINA_TRUE;
+         }
+     }
+
+   double new_value = eext_circle_object_value_get(obj);
+   widget_data->prev_angle = new_angle;
+}
+
+static void
+_angle_tap_set(Evas_Object *obj, double new_angle)
+{
+   EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return;
+
+   double min = 0.0, max = 0.0;
+   eext_circle_object_value_min_max_get(obj, &min, &max);
+
+   double current_value = eext_circle_object_value_get(obj);
+   double new_value = min + (new_angle * (max - min))/360.0;
+
+   if (floor(new_value + 0.5) != floor(current_value + 0.5))
+     _eext_circle_object_slider_value_transit_set_internal(obj, floor(new_value + 0.5));
+}
+
+static Eina_Bool _cue_effect_animator_cb(void *data, double pos)
+{
+   Evas_Object *obj = (Evas_Object *)data;
+
+   EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return ECORE_CALLBACK_CANCEL;
+
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return ECORE_CALLBACK_CANCEL;
+
+   Eext_Circle_Object_Item *item = NULL;
+   item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_EFFECT_ITEM_NAME);
+
+   if (!item)
+     {
+        ecore_animator_del(widget_data->cue_effect_transit.animator);
+        widget_data->cue_effect_transit.animator = NULL;
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   int to_width = SLIDER_CUE_HIDDEN_WIDTH;
+   if (widget_data->cue_effect_transit.showing)
+     to_width = SLIDER_CUE_SHOWN_WIDTH;
+
+   int diff = widget_data->cue_effect_transit.from_line_width - to_width;
+   int line_width = widget_data->cue_effect_transit.from_line_width - pos * diff;
+   _eext_circle_object_item_line_width_set(item, line_width);
+
+   if (pos >= 1.0)
+     {
+        ecore_animator_del(widget_data->cue_effect_transit.animator);
+        widget_data->cue_effect_transit.animator = NULL;
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void _show_cue_effect(Evas_Object *obj)
+{
+   EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   Eext_Circle_Object_Item *item = NULL;
+   item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_EFFECT_ITEM_NAME);
+
+   if (!item)
+     return;
+
+   if (widget_data->cue_effect_transit.animator)
+     {
+        ecore_animator_del(widget_data->cue_effect_transit.animator);
+        widget_data->cue_effect_transit.animator = NULL;
+     }
+
+   widget_data->cue_effect_transit.from_line_width = _eext_circle_object_item_line_width_get(item);
+   widget_data->cue_effect_transit.showing = EINA_TRUE;
+
+   widget_data->cue_effect_transit.animator = ecore_animator_timeline_add(SLIDER_TRANSIT_TIME, _cue_effect_animator_cb, obj);
+}
+
+static void _hide_cue_effect(Evas_Object *obj)
+{
+   EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   Eext_Circle_Object_Item *item = NULL;
+   item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_EFFECT_ITEM_NAME);
+
+   if (!item)
+     return;
+
+   if (widget_data->cue_effect_transit.animator)
+     {
+        ecore_animator_del(widget_data->cue_effect_transit.animator);
+        widget_data->cue_effect_transit.animator = NULL;
+     }
+
+   widget_data->cue_effect_transit.from_line_width = _eext_circle_object_item_line_width_get(item);
+   widget_data->cue_effect_transit.showing = EINA_FALSE;
+
+   widget_data->cue_effect_transit.animator = ecore_animator_timeline_add(SLIDER_TRANSIT_TIME, _cue_effect_animator_cb, obj);
+}
+
+static void
+_mouse_down_cb(void *data,
+               Evas *evas,
+               Evas_Object *obj,
+               void *event_info)
+{
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Object *img_obj = data;
+
+   EEXT_CIRCLE_OBJECT_GET(img_obj, circle_obj) return;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   if (circle_obj->disabled) return;
+
+   int radius = eext_circle_object_radius_get(img_obj);
+   Evas_Coord_Point center = {0,0};
+   center.x = SLIDER_CENTER_POINT;
+   center.y = SLIDER_CENTER_POINT;
+
+   int point = sqrt(pow(center.x - ev->canvas.x, 2) + pow(center.y - ev->canvas.y, 2));
+
+   if ((point <= radius) && (point >= (radius - SLIDER_TOUCH_AREA_SIZE)))
+     {
+        double new_angle = _angle_calculate(img_obj, ev->canvas.x, ev->canvas.y);
+        double current_angle = eext_circle_object_angle_get(img_obj);
+
+        double angle_difference = fabs(new_angle - current_angle);
+        if (angle_difference <= 18.0)
+          {
+             _show_cue_effect(img_obj);
+
+             widget_data->freeze = EINA_FALSE;
+             widget_data->prev_angle = -1.0;
+             _angle_drag_set(img_obj, new_angle);
+             widget_data->drag = EINA_TRUE;
+          }
+        else
+          {
+             widget_data->pressed_point.x = ev->canvas.x;
+             widget_data->pressed_point.y = ev->canvas.y;
+
+             widget_data->tap = EINA_TRUE;
+          }
+     }
+}
+
+static void
+_mouse_move_cb(void *data,
+               Evas *evas,
+               Evas_Object *obj,
+               void *event_info)
+{
+   Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Object *img_obj = data;
+
+   EEXT_CIRCLE_OBJECT_GET(img_obj, circle_obj) return;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   if (circle_obj->disabled) return;
+
+   if(widget_data->tap)
+     {
+        int gap = sqrt(pow(widget_data->pressed_point.x - ev->cur.canvas.x, 2) + pow(widget_data->pressed_point.y - ev->cur.canvas.y, 2));
+        if (gap > elm_config_scroll_thumbscroll_threshold_get())
+          {
+             _show_cue_effect(img_obj);
+
+             widget_data->freeze = EINA_FALSE;
+             widget_data->prev_angle = -1.0;
+
+             widget_data->tap = EINA_FALSE;
+             widget_data->drag = EINA_TRUE;
+          }
+     }
+
+   if (widget_data->drag)
+     {
+        int radius = eext_circle_object_radius_get(img_obj);
+        Evas_Coord_Point center = {0,0};
+        center.x = SLIDER_CENTER_POINT;
+        center.y = SLIDER_CENTER_POINT;
+
+        int point = sqrt(pow(center.x - ev->cur.canvas.x, 2) + pow(center.y - ev->cur.canvas.y, 2));
+
+        if ((point <= radius) && (point >= (radius - SLIDER_TOUCH_AREA_SIZE)))
+          _angle_drag_set(img_obj, _angle_calculate(img_obj, ev->cur.canvas.x, ev->cur.canvas.y));
+     }
+}
+
+static void
+_mouse_up_cb(void *data,
+               Evas *evas,
+               Evas_Object *obj,
+               void *event_info)
+{
+   Evas_Event_Mouse_Up *ev = event_info;
+   Evas_Object *img_obj = data;
+
+   EEXT_CIRCLE_OBJECT_GET(img_obj, circle_obj) return;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   if (circle_obj->disabled) return;
+
+   if (widget_data->drag)
+     {
+        _eext_circle_object_slider_value_transit_set_internal(img_obj, eext_circle_object_value_get(img_obj));
+
+        _hide_cue_effect(img_obj);
+
+        widget_data->drag = EINA_FALSE;
+     }
+   else if (widget_data->tap)
+     {
+        int gap = sqrt(pow(widget_data->pressed_point.x - ev->canvas.x, 2) + pow(widget_data->pressed_point.y - ev->canvas.y, 2));
+        if (gap < elm_config_scroll_thumbscroll_threshold_get())
+          _angle_tap_set(img_obj, _angle_calculate(img_obj, ev->canvas.x, ev->canvas.y));
+
+        widget_data->tap = EINA_FALSE;
+     }
+
+   widget_data->pressed_point.x = -1;
+   widget_data->pressed_point.y = -1;
+}
+
+static void
+_mouse_out_cb(void *data,
+               Evas *evas,
+               Evas_Object *obj,
+               void *event_info)
+{
+   Evas_Object *img_obj = data;
+
+   EEXT_CIRCLE_OBJECT_GET(img_obj, circle_obj) return;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   if (circle_obj->disabled) return;
+
+   widget_data->drag = EINA_FALSE;
+   widget_data->tap = EINA_FALSE;
+
+   widget_data->pressed_point.x = -1;
+   widget_data->pressed_point.y = -1;
+}
+
+static void
+_value_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   Eext_Circle_Object *circle_obj = data;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return;
+
+   if (widget_data->drag) return;
+   if (widget_data->tap) return;
+   if (widget_data->rotary) return;
+
+   Eext_Circle_Object_Item *item = NULL, *cue_item = NULL, *effect_item = NULL;
+   item = _eext_circle_object_item_get(circle_obj, SLIDER_ITEM_NAME);
+   cue_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_ITEM_NAME);
+   effect_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_EFFECT_ITEM_NAME);
+   if (!item || !cue_item || !effect_item) return;
+
+   double value = item->value;
+   double angle = _eext_circle_object_item_value_angle_get(item, value);
+
+   _eext_circle_object_item_angle_offset_set(effect_item, angle - SLIDER_CUE_OFFSET);
+   _eext_circle_object_item_angle_set(effect_item, SLIDER_CUE_SIZE);
+   _eext_circle_object_item_angle_offset_set(cue_item, angle - SLIDER_CUE_OFFSET);
+   _eext_circle_object_item_angle_set(cue_item, SLIDER_CUE_SIZE);
+}
 
 static void
 _eext_circle_object_slider_del_cb(Eext_Circle_Object *obj)
 {
    if (obj->widget_data)
      {
+        Eext_Circle_Object_Slider_Data *slider_data = (Eext_Circle_Object_Slider_Data *)obj->widget_data;
+        if (slider_data)
+          {
+             evas_object_event_callback_del(slider_data->hit_rect, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb);
+             evas_object_event_callback_del(slider_data->hit_rect, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb);
+             evas_object_event_callback_del(slider_data->hit_rect, EVAS_CALLBACK_MOUSE_OUT, _mouse_out_cb);
+             evas_object_event_callback_del(slider_data->hit_rect, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb);
+          }
+
+        evas_object_smart_callback_del(obj->main_obj, SIG_VALUE_CHANGED, _value_changed_cb);
+
+        if (slider_data->cue_effect_transit.animator)
+          ecore_animator_del(slider_data->cue_effect_transit.animator);
         free(obj->widget_data);
         obj->widget_data = NULL;
      }
@@ -71,34 +476,72 @@ static Eina_Bool
 _rotary_changed_cb(void *data, Evas_Object *obj, Eext_Rotary_Event_Info *info)
 {
    Evas_Object *slider = obj;
+   int time_stamp_diff, multiplier;
    double current_value;
    double next_value;
    double min, max;
+   double value_count, digit, threshold;
+   double angle;
 
    EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return EINA_FALSE;
    EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return EINA_FALSE;
 
-   Eext_Circle_Object_Item *item = NULL;
+   Eext_Circle_Object_Item *item = NULL, *cue_item = NULL, *effect_item = NULL;
    item = _eext_circle_object_item_get(circle_obj, SLIDER_ITEM_NAME);
+   cue_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_ITEM_NAME);
+   effect_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_EFFECT_ITEM_NAME);
+   if (!item || !cue_item || !effect_item) return EINA_FALSE;
 
    current_value = _eext_circle_object_item_value_get(item);
+   _eext_circle_object_item_value_min_max_get(item, &min, &max);
 
-   if (info->direction == EEXT_ROTARY_DIRECTION_CLOCKWISE)
-     next_value = current_value + widget_data->value_step;
-   else
-     next_value = current_value - widget_data->value_step;
+   multiplier = SLIDER_ROTARY_EVENT_VALUE_MULTIPLYER;
+
+   time_stamp_diff = info->time_stamp - widget_data->rotary_event_time_stamp;
+   if (time_stamp_diff > SLIDER_ROTARY_EVENT_TIME_STAMP_THRESHOLD)
+     {
+        widget_data->rotary_event_time_stamp = info->time_stamp;
+     }
 
    _eext_circle_object_item_value_min_max_get(item, &min, &max);
+   value_count = (max - min) / widget_data->value_step;
+
+   digit = log10(value_count);
+
+   threshold = SLIDER_ROTARY_EVENT_ACCELERATION_TIME_DIFF + (digit * 10);
+   if (time_stamp_diff < threshold)
+     {
+        multiplier  = value_count / (digit + 1) * pow(((threshold - time_stamp_diff) / threshold), digit + 1);
+
+        if (multiplier < SLIDER_ROTARY_EVENT_VALUE_MULTIPLYER)
+          multiplier = SLIDER_ROTARY_EVENT_VALUE_MULTIPLYER;
+     }
+
+   if (info->direction == EEXT_ROTARY_DIRECTION_CLOCKWISE)
+     next_value = current_value + widget_data->value_step * multiplier;
+   else
+     next_value = current_value - widget_data->value_step * multiplier;
 
    if (next_value < min) next_value = min;
    else if (next_value > max) next_value = max;
 
+   angle = _eext_circle_object_item_value_angle_get(item, next_value);
+
+   widget_data->rotary = EINA_TRUE;
+   _eext_circle_object_item_angle_transit_set(effect_item, SLIDER_TRANSIT_TIME,
+                                              SLIDER_CUE_SIZE, angle - SLIDER_CUE_OFFSET, EINA_TRUE,
+                                              0.25, 0.46, 0.45, 1.0);
+
+   _eext_circle_object_item_angle_transit_set(cue_item, SLIDER_TRANSIT_TIME,
+                                              SLIDER_CUE_SIZE, angle - SLIDER_CUE_OFFSET, EINA_TRUE,
+                                              0.25, 0.46, 0.45, 1.0);
+
    _eext_circle_object_item_value_transit_set(item, SLIDER_TRANSIT_TIME,
                                               next_value,
                                               EINA_TRUE,
                                               0.25, 0.46, 0.45, 1.0);
 
-   evas_object_smart_callback_call(slider, SIG_VALUE_CHANGED, NULL);
+   widget_data->rotary = EINA_FALSE;
 
    /* Accessibility */
    if (elm_atspi_bridge_utils_is_screen_reader_enabled())
@@ -193,7 +636,7 @@ _eext_circle_object_slider_disabled_cb(Eext_Circle_Object *obj)
 }
 
 static void
-_eext_circle_object_slider_init(Eext_Circle_Object *obj)
+_eext_circle_object_slider_init(Evas_Object *parent, Eext_Circle_Object *obj)
 {
    Eext_Circle_Object_Slider_Data *data;
    Eext_Circle_Object_Item *item;
@@ -205,7 +648,12 @@ _eext_circle_object_slider_init(Eext_Circle_Object *obj)
    obj->color_changed_func = _eext_circle_object_slider_color_changed_cb;
 
    data = (Eext_Circle_Object_Slider_Data *)calloc(1, sizeof(Eext_Circle_Object_Slider_Data));
+   data->parent = parent;
    data->value_step = 1.0;
+   data->rotary_event_time_stamp = 0.0;
+   data->tap = EINA_FALSE;
+   data->drag = EINA_FALSE;
+
    data->color.r = SLIDER_COLOR_R;
    data->color.g = SLIDER_COLOR_G;
    data->color.b = SLIDER_COLOR_B;
@@ -222,8 +670,30 @@ _eext_circle_object_slider_init(Eext_Circle_Object *obj)
    data->disabled_bg_color.g = SLIDER_BG_COLOR_DISABLED_G;
    data->disabled_bg_color.b = SLIDER_BG_COLOR_DISABLED_B;
    data->disabled_bg_color.a = SLIDER_BG_COLOR_DISABLED_A;
+   data->cue_color.r = SLIDER_CUE_COLOR_R;
+   data->cue_color.g = SLIDER_CUE_COLOR_G;
+   data->cue_color.b = SLIDER_CUE_COLOR_B;
+   data->cue_color.a = SLIDER_CUE_COLOR_A;
+   data->cue_press_color.r = SLIDER_CUE_EFFECT_COLOR_R;
+   data->cue_press_color.g = SLIDER_CUE_EFFECT_COLOR_G;
+   data->cue_press_color.b = SLIDER_CUE_EFFECT_COLOR_B;
+   data->cue_press_color.a = SLIDER_CUE_EFFECT_COLOR_A;
+
+   data->hit_rect = evas_object_rectangle_add(evas_object_evas_get(parent));
+   evas_object_smart_member_add(data->hit_rect, parent);
+   evas_object_color_set(data->hit_rect, 0, 0, 0, 0);
+   evas_object_resize(data->hit_rect, 360, 360);
+   evas_object_show(data->hit_rect);
+   evas_object_repeat_events_set(data->hit_rect, EINA_TRUE);
+
+   evas_object_event_callback_add(data->hit_rect, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj->main_obj);
+   evas_object_event_callback_add(data->hit_rect, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj->main_obj);
+   evas_object_event_callback_add(data->hit_rect, EVAS_CALLBACK_MOUSE_OUT, _mouse_out_cb, obj->main_obj);
+   evas_object_event_callback_add(data->hit_rect, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, obj->main_obj);
+
    obj->widget_data = data;
 
+   //BG
    item = _eext_circle_object_item_new();
    _eext_circle_object_item_name_set(item, SLIDER_BG_ITEM_NAME);
    _eext_circle_object_item_color_set(item, data->bg_color.r, data->bg_color.g, data->bg_color.b, data->bg_color.a);
@@ -232,6 +702,26 @@ _eext_circle_object_slider_init(Eext_Circle_Object *obj)
    _eext_circle_object_item_angle_set(item, 360);
    _eext_circle_object_item_append(obj, item);
 
+   item = _eext_circle_object_item_new();
+   _eext_circle_object_item_name_set(item, SLIDER_CUE_EFFECT_ITEM_NAME);
+   _eext_circle_object_item_color_set(item, data->cue_press_color.r, data->cue_press_color.g, data->cue_press_color.b, data->cue_press_color.a);
+   _eext_circle_object_item_line_width_set(item, 14);
+   _eext_circle_object_item_radius_set(item, SLIDER_RADIUS_SIZE);
+   _eext_circle_object_item_round_cap_enable_set(item, EINA_TRUE);
+   _eext_circle_object_item_angle_offset_set(item, item->angle_offset - SLIDER_CUE_OFFSET);
+   _eext_circle_object_item_angle_set(item, SLIDER_CUE_SIZE);
+   _eext_circle_object_item_append(obj, item);
+
+   item = _eext_circle_object_item_new();
+   _eext_circle_object_item_name_set(item, SLIDER_CUE_ITEM_NAME);
+   _eext_circle_object_item_color_set(item, data->cue_color.r, data->cue_color.g, data->cue_color.b, data->cue_color.a);
+   _eext_circle_object_item_line_width_set(item, 14);
+   _eext_circle_object_item_radius_set(item, SLIDER_RADIUS_SIZE);
+   _eext_circle_object_item_round_cap_enable_set(item, EINA_TRUE);
+   _eext_circle_object_item_angle_offset_set(item, item->angle_offset - SLIDER_CUE_OFFSET);
+   _eext_circle_object_item_angle_set(item, SLIDER_CUE_SIZE);
+   _eext_circle_object_item_append(obj, item);
+
    item = _eext_circle_object_item_new();
    _eext_circle_object_item_name_set(item, SLIDER_ITEM_NAME);
    _eext_circle_object_item_color_set(item, data->color.r, data->color.g, data->color.b, data->color.a);
@@ -241,6 +731,7 @@ _eext_circle_object_slider_init(Eext_Circle_Object *obj)
    _eext_circle_object_item_value_set(item, 0);
    _eext_circle_object_item_append(obj, item);
 
+   evas_object_smart_callback_add(obj->main_obj, SIG_VALUE_CHANGED, _value_changed_cb, obj);
    eext_rotary_object_event_callback_add(obj->main_obj, _rotary_changed_cb, NULL);
 }
 
@@ -284,7 +775,7 @@ eext_circle_object_slider_add(Evas_Object *parent, Eext_Circle_Surface *surface)
 
    EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return NULL;
 
-   _eext_circle_object_slider_init(circle_obj);
+   _eext_circle_object_slider_init(parent, circle_obj);
 
    /* TODO: Reading information should be changed with UX team */
    /* ELM_ATSPI_ROLE_PUSH_BUTTON to make layout grab highlight */
@@ -315,3 +806,46 @@ eext_circle_object_slider_step_get(const Evas_Object *obj)
    return widget_data->value_step;
 }
 
+static Eina_Bool
+_eext_circle_object_slider_value_transit_set_internal(Evas_Object *obj, double value)
+{
+   EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return EINA_FALSE;
+   EEXT_CIRCLE_OBJECT_SLIDER_DATA_GET(circle_obj, widget_data) return EINA_FALSE;
+
+   Eext_Circle_Object_Item *item = NULL, *cue_item = NULL, *effect_item = NULL;
+   item = _eext_circle_object_item_get(circle_obj, SLIDER_ITEM_NAME);
+   cue_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_ITEM_NAME);
+   effect_item = _eext_circle_object_item_get(circle_obj, SLIDER_CUE_EFFECT_ITEM_NAME);
+   if (!item || !cue_item || !effect_item) return EINA_FALSE;
+
+
+   double current_angle = eext_circle_object_angle_get(obj);
+   double new_angle = _eext_circle_object_item_value_angle_get(item, value);
+
+   double angle_difference = fabs(new_angle - current_angle);
+
+   double duration = durations[0];
+   if (angle_difference > 270.0)
+     duration = durations[3];
+   else if (angle_difference > 180.0)
+     duration = durations[2];
+   else if (angle_difference > 90.0)
+     duration = durations[1];
+
+
+   double angle = _eext_circle_object_item_value_angle_get(item, value);
+
+   _eext_circle_object_item_angle_transit_set(effect_item, duration,
+                                              SLIDER_CUE_SIZE, angle - SLIDER_CUE_OFFSET, EINA_TRUE,
+                                              0.25, 0.46, 0.45, 1.0);
+
+   _eext_circle_object_item_angle_transit_set(cue_item, duration,
+                                              SLIDER_CUE_SIZE, angle - SLIDER_CUE_OFFSET, EINA_TRUE,
+                                              0.25, 0.46, 0.45, 1.0);
+
+   _eext_circle_object_item_value_transit_set(item, duration,
+                                              value, EINA_TRUE,
+                                              0.25, 0.46, 0.45, 1.0);
+
+   return EINA_TRUE;
+}
\ No newline at end of file