#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);
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;
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;
}
}
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;
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;
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)
{
}
}
+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)
{
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;
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);
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);
_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);
double cubic_bezier_p2_x, double cubic_bezier_p2_y)
{
Eina_Bool ret;
+ double value;
if (!item) return;
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
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
#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; \
#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;
}
_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())
}
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;
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;
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);
_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);
_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);
}
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 */
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