--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "efl_extension.h"
+#include "efl_extension_private.h"
+#include "wearable/circle/efl_extension_circle_private.h"
+#define EEXT_CIRCLE_OBJECT_GENGRID_TYPE "Eext_Circle_Object_Gengrid"
+
+#define VERTICAL_BAR_ANGLE_START 60.0
+#define VERTICAL_BAR_ANGLE_RANGE 60.0
+#define VERTICAL_BAR_ANGLE_MAX_SIZE 60.0
+#define VERTICAL_BAR_ANGLE_MIN_SIZE 6.0
+#define VERTICAL_BAR_TRANSIT_TIME 0.2
+#define VERTICAL_BAR_HIDE_WAITTING_TIME 0.2
+#define VERTICAL_BAR_HIDE_WAITTING_TIME_ON_INITIALIZING 1.0
+#define VERTICAL_BAR_WIDTH_SIZE 10
+#define VERTICAL_BAR_RADIUS_SIZE 174 // (180 - 6)
+
+#define HORIZONTAL_BAR_ANGLE_START -30.0
+#define HORIZONTAL_BAR_ANGLE_RANGE 60.0
+#define HORIZONTAL_BAR_ANGLE_MAX_SIZE 60.0
+#define HORIZONTAL_BAR_ANGLE_MIN_SIZE 6.0
+#define HORIZONTAL_BAR_TRANSIT_TIME 0.2
+#define HORIZONTAL_BAR_HIDE_WAITTING_TIME 0.2
+#define HORIZONTAL_BAR_HIDE_WAITTING_TIME_ON_INITIALIZING 1.0
+#define HORIZONTAL_BAR_WIDTH_SIZE 10
+#define HORIZONTAL_BAR_RADIUS_SIZE 174 // (180 - 6)
+
+#define DETENT_SCROLL_DISTANCE_RATE 0.4
+#define ROTARY_EVENT_TIME_STAMP_THRESHOLD 500
+
+#define ROTARY_PHASE_N1 0.1
+#define ROTARY_PHASE_N2 3
+#define ROTARY_PHASE_N3 1.5
+#define ROTARY_PHASE_N4 4
+
+static const char SIGNAL_LOADED[] = "loaded";
+static const char SIGNAL_ACTIVATED[] = "rotary,activated";
+static const char SIGNAL_DEACTIVATED[] = "rotary,deactivated";
+static const char SIGNAL_SCROLL[] = "scroll";
+static const char SIGNAL_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
+static const char SIGNAL_EDGE_TOP_ROTARY_DETENTED[] = "elm,edge,top,rotary,detented";
+static const char SIGNAL_EDGE_BOTTOM_ROTARY_DETENTED[] = "elm,edge,bottom,rotary,detented";
+static const char SIGNAL_EDGE_LEFT_ROTARY_DETENTED[] = "elm,edge,left,rotary,detented";
+static const char SIGNAL_EDGE_RIGHT_ROTARY_DETENTED[] = "elm,edge,right,rotary,detented";
+static const char SIGNAL_ITEM_DELETED[] = "item,deleted";
+static const char SIG_BRING_IN_ITEM_ADJUSTED[] = "bring_in,item,adjusted";
+
+#define EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, data) \
+ Eext_Circle_Object_Gengrid_Data *data = NULL; \
+ if (circle_obj && circle_obj->widget_data && \
+ circle_obj->widget_type && !strcmp(circle_obj->widget_type, EEXT_CIRCLE_OBJECT_GENGRID_TYPE)) \
+ data = (Eext_Circle_Object_Gengrid_Data *)circle_obj->widget_data; \
+ if (!data)
+
+#define GENGRID_ITEM_NAME "default"
+#define GENGRID_BG_ITEM_NAME "scroll,bg"
+
+static void
+_eext_circle_object_gengrid_region_show(Eext_Circle_Object *circle_obj,
+ Eina_Bool clockwise)
+{
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ Evas_Coord x = 0, y = 0, w = 0, h = 0, x_pos = 0, y_pos = 0;
+ Evas_Coord ch = 0, scroll_y = 0, cw = 0, scroll_x = 0;
+
+ elm_scroller_child_size_get(circle_obj->widget_object, &cw, &ch);
+ elm_scroller_region_get(circle_obj->widget_object, &x, &y, &w, &h);
+ Eina_Bool horizontal = elm_gengrid_horizontal_get(circle_obj->widget_object);
+
+ if (!elm_object_scroll_item_align_enabled_get(circle_obj->widget_object))
+ {
+ if (!horizontal && widget_data->policy_v != ELM_SCROLLER_POLICY_OFF && !widget_data->scrollbar_first_shown) return;
+ else if (horizontal && widget_data->policy_h != ELM_SCROLLER_POLICY_OFF && !widget_data->scrollbar_first_shown) return;
+
+ if (clockwise)
+ {
+ if (horizontal)
+ {
+ if (x < widget_data->dest_x)
+ scroll_x = x + (widget_data->dest_x - x) + (w * DETENT_SCROLL_DISTANCE_RATE);
+ else
+ scroll_x = x + w * DETENT_SCROLL_DISTANCE_RATE;
+
+ if (scroll_x > cw - w)
+ scroll_x = cw - w;
+ if (scroll_x == x)
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_RIGHT_ROTARY_DETENTED, "elm");
+ }
+ else
+ {
+ if (y < widget_data->dest_y)
+ scroll_y = y + (widget_data->dest_y - y) + (h * DETENT_SCROLL_DISTANCE_RATE);
+ else
+ scroll_y = y + h * DETENT_SCROLL_DISTANCE_RATE;
+
+ if (scroll_y > ch - h)
+ scroll_y = ch - h;
+ if (scroll_y == y)
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_BOTTOM_ROTARY_DETENTED, "elm");
+ }
+ }
+ else
+ {
+ if (horizontal && (x > 0))
+ {
+ if (x > widget_data->dest_x)
+ scroll_x = x - (x - widget_data->dest_x) - (w * DETENT_SCROLL_DISTANCE_RATE);
+ else
+ scroll_x = x - w * DETENT_SCROLL_DISTANCE_RATE;
+
+ if (scroll_x < 0)
+ scroll_x = 0;
+ }
+ else if (horizontal)
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_LEFT_ROTARY_DETENTED, "elm");
+
+ if (!horizontal && y > 0)
+ {
+ if (y > widget_data->dest_y)
+ scroll_y = y - (y - widget_data->dest_y) - (h * DETENT_SCROLL_DISTANCE_RATE);
+ else
+ scroll_y = y - h * DETENT_SCROLL_DISTANCE_RATE;
+
+ if (scroll_y < 0)
+ scroll_y = 0;
+ }
+ else if (!horizontal)
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_TOP_ROTARY_DETENTED, "elm");
+ }
+
+ if (horizontal)
+ {
+ widget_data->dest_x = scroll_x;
+ elm_scroller_region_bring_in(circle_obj->widget_object, scroll_x, y, w, h);
+ }
+ else
+ {
+ widget_data->dest_y = scroll_y;
+ elm_scroller_region_bring_in(circle_obj->widget_object, x, scroll_y, w, h);
+ }
+ return;
+ }
+
+ if (horizontal && (cw < w + elm_config_finger_size_get())) return;
+ if (!horizontal && (ch < h + elm_config_finger_size_get())) return;
+
+ if (clockwise)
+ {
+ Evas_Coord item_w, item_h, pos_delta;
+
+ if (horizontal && (x >= (cw - w)))
+ {
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_RIGHT_ROTARY_DETENTED, "elm");
+ return;
+ }
+ else if (!horizontal && (y >= (ch - h)))
+ {
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_BOTTOM_ROTARY_DETENTED, "elm");
+ return;
+ }
+
+ elm_gengrid_item_size_get(circle_obj->widget_object, &item_w, &item_h);
+ if (horizontal)
+ {
+ x_pos = x + item_w;
+ pos_delta = x_pos % item_w;
+ if (pos_delta != 0) x_pos += (item_w - pos_delta);
+ }
+ else
+ {
+ y_pos = y + item_h;
+ pos_delta = y_pos % item_h;
+ if (pos_delta != 0) y_pos += (item_h - pos_delta);
+ }
+ }
+ else
+ {
+ if (horizontal)
+ {
+ if (x > (elm_config_finger_size_get() * -1) && x < elm_config_finger_size_get())
+ {
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_LEFT_ROTARY_DETENTED, "elm");
+ return;
+ }
+ else
+ {
+ Evas_Coord item_w, pos_delta;
+ elm_gengrid_item_size_get(circle_obj->widget_object, &item_w, NULL);
+ x_pos = x - item_w;
+ pos_delta = x_pos % item_w;
+ if (pos_delta != 0) x_pos -= pos_delta;
+ }
+ }
+ else
+ {
+ if (y > (elm_config_finger_size_get() * -1) && y < elm_config_finger_size_get())
+ {
+ edje_object_signal_emit(elm_layout_edje_get(circle_obj->widget_object), SIGNAL_EDGE_TOP_ROTARY_DETENTED, "elm");
+ return;
+ }
+ else
+ {
+ Evas_Coord item_h, pos_delta;
+ elm_gengrid_item_size_get(circle_obj->widget_object, NULL, &item_h);
+ y_pos = y - item_h;
+ pos_delta = y_pos % item_h;
+ if (pos_delta != 0) y_pos -= pos_delta;
+ }
+ }
+ }
+
+ if (horizontal)
+ elm_scroller_region_bring_in(circle_obj->widget_object, x_pos, y, w, h);
+ else
+ elm_scroller_region_bring_in(circle_obj->widget_object, x, y_pos, w, h);
+}
+
+static Eext_Circle_Object_Gengrid_Rotary_Time *
+_eext_circle_object_gengrid_rotary_time_new(double time)
+{
+ Eext_Circle_Object_Gengrid_Rotary_Time *rotary_time = calloc(1, sizeof(Eext_Circle_Object_Gengrid_Rotary_Time));
+
+ if (rotary_time)
+ rotary_time->time = time;
+
+ return rotary_time;
+}
+
+static Eina_Bool
+_rotary_changed_cb(void *data,
+ Evas_Object *obj,
+ Eext_Rotary_Event_Info *info)
+{
+ Eina_Bool clockwise;
+ unsigned int time_stamp_diff;
+
+ Eext_Circle_Object *circle_obj = data;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return EINA_TRUE;
+
+ if (circle_obj->is_propagated)
+ {
+ circle_obj->is_propagated = EINA_FALSE;
+
+ return EINA_TRUE;
+ }
+
+ if (obj == circle_obj->main_obj)
+ {
+ circle_obj->is_propagated = EINA_TRUE;
+ }
+
+ time_stamp_diff = info->time_stamp - widget_data->latest_time_stamp;
+ if (time_stamp_diff > ROTARY_EVENT_TIME_STAMP_THRESHOLD || !widget_data->current_item)
+ {
+ Evas_Coord ox, oy, ow, oh;
+ evas_object_geometry_get(circle_obj->widget_object, &ox, &oy, &ow, &oh);
+ widget_data->current_item = elm_gengrid_at_xy_item_get(circle_obj->widget_object, ox + ow/2, oy + oh/2, NULL, NULL);
+ }
+ widget_data->latest_time_stamp = info->time_stamp;
+
+ if (info->direction == EEXT_ROTARY_DIRECTION_CLOCKWISE)
+ clockwise = EINA_TRUE;
+ else
+ clockwise = EINA_FALSE;
+
+ if (widget_data->current_phase == 0)
+ {
+ _eext_circle_object_gengrid_region_show(circle_obj, clockwise);
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_eext_circle_object_gengrid_bg_color_set(Eext_Circle_Object *circle_obj)
+{
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ edje_object_color_class_get(elm_layout_edje_get(circle_obj->widget_object),
+ widget_data->scrollbar_bg_color_class,
+ &widget_data->bg_color.r,
+ &widget_data->bg_color.g,
+ &widget_data->bg_color.b,
+ &widget_data->bg_color.a,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ _eext_circle_object_item_color_set(widget_data->bg_item,
+ widget_data->bg_color.r,
+ widget_data->bg_color.g,
+ widget_data->bg_color.b,
+ widget_data->bg_color.a);
+}
+
+static void
+_eext_circle_object_gengrid_line_color_set(Eext_Circle_Object *circle_obj)
+{
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ edje_object_color_class_get(elm_layout_edje_get(circle_obj->widget_object),
+ widget_data->scrollbar_color_class,
+ &widget_data->color.r,
+ &widget_data->color.g,
+ &widget_data->color.b,
+ &widget_data->color.a,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ _eext_circle_object_item_color_set(widget_data->item,
+ widget_data->color.r,
+ widget_data->color.g,
+ widget_data->color.b,
+ widget_data->color.a);
+}
+
+static void
+_eext_circle_object_gengrid_change_color_signal_cb(void *data,
+ Evas_Object *widget_obj,
+ const char *emission,
+ const char *source)
+{
+ Eext_Circle_Object *circle_obj = data;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ if(!strcmp(source, widget_data->scrollbar_bg_color_class))
+ _eext_circle_object_gengrid_bg_color_set(circle_obj);
+ else if (!strcmp(source, widget_data->scrollbar_color_class))
+ _eext_circle_object_gengrid_line_color_set(circle_obj);
+}
+
+static void
+_eext_circle_object_gengrid_scrollbar_update(Eext_Circle_Object *circle_obj)
+{
+ Evas_Coord ch = 0, cw = 0, px = 0, py = 0, vh = 0, vw = 0; /* content h postion y, viewport h */
+ double ratio = 0.0;
+ double bar_pos_y = VERTICAL_BAR_ANGLE_START;
+ double bar_pos_x = HORIZONTAL_BAR_ANGLE_START;
+ double vertical_bar_angle_range = VERTICAL_BAR_ANGLE_RANGE;
+ double horizontal_bar_angle_range = HORIZONTAL_BAR_ANGLE_RANGE;
+
+ if (!circle_obj) return;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+ Eina_Bool horizontal = elm_gengrid_horizontal_get(circle_obj->widget_object);
+
+ elm_scroller_child_size_get(circle_obj->widget_object, &cw, &ch);
+ elm_scroller_region_get(circle_obj->widget_object, &px, &py, &vw, &vh);
+
+ if (elm_object_scroll_item_align_enabled_get(circle_obj->widget_object) &&
+ ((horizontal && cw < vw + elm_config_finger_size_get()) ||
+ (!horizontal && ch < vh + elm_config_finger_size_get())))
+ {
+ widget_data->bar_size_x = 0;
+ widget_data->bar_size_y = 0;
+ _eext_circle_object_item_color_set(widget_data->item, 0, 0, 0, 0);
+ _eext_circle_object_item_color_set(widget_data->bg_item, 0, 0, 0, 0);
+ _eext_circle_object_changed(circle_obj);
+ return;
+ }
+ if (horizontal)
+ ratio = (double)cw / (double)vw;
+ else
+ ratio = (double)ch / (double)vh;
+
+ if (horizontal && cw > vw)
+ {
+ widget_data->bar_size_x = horizontal_bar_angle_range / ratio;
+
+ if (widget_data->bar_size_x > HORIZONTAL_BAR_ANGLE_MAX_SIZE)
+ widget_data->bar_size_x = HORIZONTAL_BAR_ANGLE_MAX_SIZE;
+ if (widget_data->bar_size_x < HORIZONTAL_BAR_ANGLE_MIN_SIZE)
+ widget_data->bar_size_x = HORIZONTAL_BAR_ANGLE_MIN_SIZE;
+
+ bar_pos_x += (HORIZONTAL_BAR_ANGLE_MAX_SIZE - widget_data->bar_size_x) * px / (cw - vw);
+ _eext_circle_object_item_angle_set(widget_data->item, widget_data->bar_size_x);
+ _eext_circle_object_item_angle_offset_set(widget_data->item, bar_pos_x);
+ }
+ else if (!horizontal && ch > vh)
+ {
+ widget_data->bar_size_y = vertical_bar_angle_range / ratio;
+
+ if (widget_data->bar_size_y > VERTICAL_BAR_ANGLE_MAX_SIZE)
+ widget_data->bar_size_y = VERTICAL_BAR_ANGLE_MAX_SIZE;
+ if (widget_data->bar_size_y < VERTICAL_BAR_ANGLE_MIN_SIZE)
+ widget_data->bar_size_y = VERTICAL_BAR_ANGLE_MIN_SIZE;
+
+ bar_pos_y += (VERTICAL_BAR_ANGLE_MAX_SIZE - widget_data->bar_size_y) * py / (ch - vh);
+ _eext_circle_object_item_angle_set(widget_data->item, widget_data->bar_size_y);
+ _eext_circle_object_item_angle_offset_set(widget_data->item, bar_pos_y);
+ }
+
+}
+
+static void
+_eext_circle_object_gengrid_color_changed_cb(Eext_Circle_Object *circle_obj,
+ const char *item_name)
+{
+ Eext_Circle_Object_Item *item = NULL;
+ int r = 0, g = 0, b = 0, a = 0;
+
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ item = _eext_circle_object_item_get(circle_obj, item_name);
+ if (!item) return;
+
+ _eext_circle_object_item_color_get(item, &r, &g, &b, &a);
+
+ if (!strcmp(item_name, GENGRID_ITEM_NAME))
+ {
+ widget_data->color.r = r;
+ widget_data->color.g = g;
+ widget_data->color.b = b;
+ widget_data->color.a = a;
+
+ return;
+ }
+
+ if (!strcmp(item_name, GENGRID_BG_ITEM_NAME))
+ {
+ widget_data->bg_color.r = r;
+ widget_data->bg_color.g = g;
+ widget_data->bg_color.b = b;
+ widget_data->bg_color.a = a;
+
+ return;
+ }
+}
+
+static Eina_Bool
+_eext_circle_object_gengrid_scrollbar_policy_hide_cb(void *data)
+{
+ Eext_Circle_Object *circle_obj = (Eext_Circle_Object *)data;
+ Eext_Circle_Object_Item *item = NULL;
+ Eina_List *l = NULL;
+
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return ECORE_CALLBACK_CANCEL;
+ Eina_Bool horizontal = elm_gengrid_horizontal_get(circle_obj->widget_object);
+
+ if (!widget_data->scrollbar_initializing)
+ {
+ EINA_LIST_FOREACH(circle_obj->items, l, item)
+ {
+ if (!horizontal && widget_data->bar_size_y > 0.0)
+ _eext_circle_object_item_color_transit_set(item,
+ VERTICAL_BAR_TRANSIT_TIME,
+ 0, 0, 0, 0,
+ EINA_TRUE,
+ 0.25, 0.46, 0.45, 1.0);
+ else if (horizontal && widget_data->bar_size_x > 0.0)
+ _eext_circle_object_item_color_transit_set(item,
+ HORIZONTAL_BAR_TRANSIT_TIME,
+ 0, 0, 0, 0,
+ EINA_TRUE,
+ 0.25, 0.46, 0.45, 1.0);
+ }
+ }
+
+ if (widget_data->bar_hide_timer)
+ {
+ ecore_timer_del(widget_data->bar_hide_timer);
+ widget_data->bar_hide_timer = NULL;
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_eext_circle_object_gengrid_scrollbar_showing(Eext_Circle_Object *circle_obj,
+ double hide_waiting_time)
+{
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ Eina_Bool horizontal = elm_gengrid_horizontal_get(circle_obj->widget_object);
+ if ((horizontal && (widget_data->bar_size_x <= 0)) ||
+ (!horizontal && (widget_data->bar_size_y <= 0))) return;
+
+ _eext_circle_object_item_color_set(widget_data->item,
+ widget_data->color.r,
+ widget_data->color.g,
+ widget_data->color.b,
+ widget_data->color.a);
+ _eext_circle_object_item_color_set(widget_data->bg_item,
+ widget_data->bg_color.r,
+ widget_data->bg_color.g,
+ widget_data->bg_color.b,
+ widget_data->bg_color.a);
+
+ if (widget_data->bar_hide_timer)
+ {
+ ecore_timer_del(widget_data->bar_hide_timer);
+ widget_data->bar_hide_timer = NULL;
+ }
+
+ if (horizontal && widget_data->policy_h == ELM_SCROLLER_POLICY_AUTO)
+ {
+ widget_data->bar_hide_timer = ecore_timer_add(hide_waiting_time,
+ _eext_circle_object_gengrid_scrollbar_policy_hide_cb,
+ circle_obj);
+ }
+ else if (!horizontal && widget_data->policy_v == ELM_SCROLLER_POLICY_AUTO)
+ {
+ widget_data->bar_hide_timer = ecore_timer_add(hide_waiting_time,
+ _eext_circle_object_gengrid_scrollbar_policy_hide_cb,
+ circle_obj);
+ }
+}
+
+static Eina_Bool
+_eext_circle_object_gengrid_scrollbar_first_show_cb(void *data)
+{
+ Eext_Circle_Object *circle_obj = (Eext_Circle_Object *)data;
+ Evas_Coord x = 0, y = 0, w = 0, h = 0;
+
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return EINA_FALSE;
+
+ if (widget_data->bar_first_show_timer)
+ {
+ ecore_timer_del(widget_data->bar_first_show_timer);
+ widget_data->bar_first_show_timer = NULL;
+ }
+
+ _eext_circle_object_gengrid_scrollbar_update(circle_obj);
+ _eext_circle_object_gengrid_scrollbar_showing(circle_obj, VERTICAL_BAR_HIDE_WAITTING_TIME_ON_INITIALIZING);
+
+ if (!elm_object_scroll_item_align_enabled_get(circle_obj->widget_object))
+ {
+ elm_scroller_region_get(circle_obj->widget_object, &x, &y, &w, &h);
+ widget_data->dest_x = x;
+ widget_data->dest_y = y;
+ }
+
+ widget_data->scrollbar_first_shown = EINA_TRUE;
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_eext_circle_object_gengrid_change_flag_cb(void *data)
+{
+ Eext_Circle_Object *circle_obj = (Eext_Circle_Object *)data;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return EINA_FALSE;
+
+ widget_data->scrollbar_initializing = EINA_FALSE;
+ Eina_Bool horizontal = elm_gengrid_horizontal_get(circle_obj->widget_object);
+
+ if (widget_data->change_flag_timer)
+ {
+ ecore_timer_del(widget_data->change_flag_timer);
+ widget_data->change_flag_timer = NULL;
+ }
+
+ if ((!horizontal && widget_data->policy_v == ELM_SCROLLER_POLICY_AUTO) ||
+ (horizontal && widget_data->policy_h == ELM_SCROLLER_POLICY_AUTO))
+ {
+ if (widget_data->bar_hide_timer)
+ {
+ ecore_timer_del(widget_data->bar_hide_timer);
+ widget_data->bar_hide_timer = NULL;
+ }
+
+ widget_data->bar_hide_timer = ecore_timer_add(0.5,
+ _eext_circle_object_gengrid_scrollbar_policy_hide_cb,
+ circle_obj);
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_eext_circle_object_gengrid_scrollbar_show(Eext_Circle_Object *circle_obj,
+ Eina_Bool first_show)
+{
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ if (first_show)
+ {
+ widget_data->scrollbar_initializing = EINA_TRUE;
+ widget_data->scrollbar_first_shown = EINA_FALSE;
+
+ if (!widget_data->change_flag_timer)
+ widget_data->change_flag_timer = ecore_timer_add(1.5, _eext_circle_object_gengrid_change_flag_cb, circle_obj);
+ if (!widget_data->bar_first_show_timer)
+ widget_data->bar_first_show_timer = ecore_timer_add(0.5, _eext_circle_object_gengrid_scrollbar_first_show_cb, circle_obj);
+ }
+ else if (widget_data->scrollbar_first_shown)
+ {
+ _eext_circle_object_gengrid_scrollbar_update(circle_obj);
+ _eext_circle_object_gengrid_scrollbar_showing(circle_obj, VERTICAL_BAR_HIDE_WAITTING_TIME);
+ }
+}
+
+void
+_eext_circle_object_gengrid_init_scroller_info(Eext_Circle_Object *circle_obj)
+{
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ if (widget_data->bar_first_show_timer)
+ {
+ ecore_timer_del(widget_data->bar_first_show_timer);
+ widget_data->bar_first_show_timer = NULL;
+ }
+ if (widget_data->change_flag_timer)
+ {
+ ecore_timer_del(widget_data->change_flag_timer);
+ widget_data->change_flag_timer = NULL;
+ }
+ if (widget_data->bar_hide_timer)
+ {
+ ecore_timer_del(widget_data->bar_hide_timer);
+ widget_data->bar_hide_timer = NULL;
+ }
+ widget_data->scrollbar_initializing = EINA_FALSE;
+
+ _eext_circle_object_item_color_set(widget_data->item, 0, 0, 0, 0);
+ _eext_circle_object_item_color_set(widget_data->bg_item, 0, 0, 0, 0);
+
+ _eext_circle_object_changed(circle_obj);
+}
+
+static void
+_eext_circle_object_gengrid_activated_cb(void *data,
+ Evas_Object *obj,
+ void *event_info)
+{
+ Eext_Circle_Object *circle_obj = (Eext_Circle_Object *)data;
+
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ if (widget_data->scrollbar_initializing) return;
+
+ _eext_circle_object_gengrid_init_scroller_info(circle_obj);
+
+ if (widget_data->policy_v == ELM_SCROLLER_POLICY_OFF) return;
+
+ _eext_circle_object_gengrid_scrollbar_show(circle_obj, EINA_TRUE);
+}
+
+static void
+_eext_circle_object_gengrid_deactivated_cb(void *data,
+ Evas_Object *obj,
+ void *event_info)
+{
+ Eext_Circle_Object *circle_obj = (Eext_Circle_Object *)data;
+ _eext_circle_object_gengrid_init_scroller_info(circle_obj);
+}
+
+static void
+_eext_circle_object_gengrid_scroll_cb(void *data,
+ Evas_Object *obj,
+ void *event_info)
+{
+ Eext_Circle_Object *circle_obj = (Eext_Circle_Object *)data;
+
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ if (widget_data->policy_v == ELM_SCROLLER_POLICY_OFF) return;
+
+ _eext_circle_object_gengrid_scrollbar_show(circle_obj, EINA_FALSE);
+}
+
+static void
+_eext_circle_object_gengrid_scroll_anim_stop_cb(void *data,
+ Evas_Object *obj,
+ void *event_info)
+{
+ Eext_Circle_Object *circle_obj = (Eext_Circle_Object *)data;
+ Evas_Coord x = 0, y = 0, w = 0, h = 0;
+
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ if (widget_data->policy_v == ELM_SCROLLER_POLICY_OFF) return;
+
+ if (!elm_object_scroll_item_align_enabled_get(circle_obj->widget_object))
+ {
+ elm_scroller_region_get(circle_obj->widget_object, &x, &y, &w, &h);
+ widget_data->dest_x = x;
+ }
+}
+
+static void
+_eext_circle_object_gengrid_loaded_cb(void *data,
+ Evas_Object *widget_obj,
+ void *event_info)
+{
+ Eext_Circle_Object *circle_obj = data;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+ if (widget_data->policy_h == ELM_SCROLLER_POLICY_OFF ||
+ widget_data->policy_v == ELM_SCROLLER_POLICY_OFF)
+ {
+ if (widget_data->bar_hide_timer)
+ {
+ ecore_timer_del(widget_data->bar_hide_timer);
+ widget_data->bar_hide_timer = NULL;
+ }
+ _eext_circle_object_gengrid_scrollbar_policy_hide_cb(circle_obj);
+ }
+ else if (widget_data->policy_h == ELM_SCROLLER_POLICY_ON ||
+ widget_data->policy_v == ELM_SCROLLER_POLICY_ON)
+ {
+ _eext_circle_object_gengrid_scrollbar_update(circle_obj);
+ _eext_circle_object_gengrid_scrollbar_show(circle_obj, EINA_FALSE);
+ }
+}
+
+static void
+_eext_circle_object_gengrid_item_deleted_cb(void *data,
+ Evas_Object *widget_obj,
+ void *event_info)
+{
+ Eext_Circle_Object *circle_obj = data;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ Elm_Object_Item* delted_item = (Elm_Object_Item*)event_info;
+
+ if(widget_data->current_item == delted_item)
+ {
+ widget_data->current_item = NULL;
+ }
+}
+
+static void
+_eext_circle_object_gengrid_bring_in_item_adjusted_cb(void *data,
+ Evas_Object *widget_obj,
+ void *event_info)
+{
+ Eext_Circle_Object *circle_obj = data;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+
+ widget_data->current_item = (Elm_Object_Item*)event_info;
+}
+
+static void
+_eext_circle_object_gengrid_del_cb(Eext_Circle_Object *circle_obj)
+{
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data) return;
+ Eext_Circle_Object_Gengrid_Rotary_Time *rotary_time;
+
+ evas_object_smart_callback_del_full(circle_obj->widget_object, SIGNAL_ACTIVATED, _eext_circle_object_gengrid_activated_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->main_obj, SIGNAL_ACTIVATED, _eext_circle_object_gengrid_activated_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->widget_object, SIGNAL_DEACTIVATED, _eext_circle_object_gengrid_deactivated_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->main_obj, SIGNAL_DEACTIVATED, _eext_circle_object_gengrid_deactivated_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->widget_object, SIGNAL_SCROLL, _eext_circle_object_gengrid_scroll_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->widget_object, SIGNAL_SCROLL_ANIM_STOP, _eext_circle_object_gengrid_scroll_anim_stop_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->widget_object, SIGNAL_LOADED, _eext_circle_object_gengrid_loaded_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->widget_object, SIGNAL_ITEM_DELETED, _eext_circle_object_gengrid_item_deleted_cb, circle_obj);
+ evas_object_smart_callback_del_full(circle_obj->widget_object, SIG_BRING_IN_ITEM_ADJUSTED, _eext_circle_object_gengrid_bring_in_item_adjusted_cb, circle_obj);
+ edje_object_signal_callback_del(elm_layout_edje_get(circle_obj->widget_object), "color_class,set", widget_data->scrollbar_color_class, _eext_circle_object_gengrid_change_color_signal_cb);
+ edje_object_signal_callback_del(elm_layout_edje_get(circle_obj->widget_object), "color_class,set", widget_data->scrollbar_bg_color_class, _eext_circle_object_gengrid_change_color_signal_cb);
+
+ if (widget_data->bar_hide_timer)
+ {
+ ecore_timer_del(widget_data->bar_hide_timer);
+ widget_data->bar_hide_timer = NULL;
+ }
+
+ if (widget_data->bar_first_show_timer)
+ {
+ ecore_timer_del(widget_data->bar_first_show_timer);
+ widget_data->bar_first_show_timer = NULL;
+ }
+ if (widget_data->change_flag_timer)
+ {
+ ecore_timer_del(widget_data->change_flag_timer);
+ widget_data->change_flag_timer = NULL;
+ }
+
+
+ EINA_LIST_FREE(widget_data->rotary_times, rotary_time)
+ free(rotary_time);
+
+ free(circle_obj->widget_data);
+ circle_obj->widget_data = NULL;
+
+ eext_rotary_object_event_callback_del(circle_obj->widget_object, _rotary_changed_cb);
+}
+
+static void
+_eext_circle_object_gengrid_init(Eext_Circle_Object *circle_obj,
+ Evas_Object *gengrid)
+{
+ Eext_Circle_Object_Gengrid_Data *widget_data = NULL;
+
+ circle_obj->widget_type = EEXT_CIRCLE_OBJECT_GENGRID_TYPE;
+ circle_obj->del_func = _eext_circle_object_gengrid_del_cb;
+ circle_obj->color_changed_func = _eext_circle_object_gengrid_color_changed_cb;
+ circle_obj->mirrored_state = EEXT_CIRCLE_MIRRORED_CONFIG;
+
+ widget_data = (Eext_Circle_Object_Gengrid_Data *)calloc(1, sizeof(Eext_Circle_Object_Gengrid_Data));
+ widget_data->policy_v = ELM_SCROLLER_POLICY_AUTO;
+ widget_data->scrollbar_initializing = EINA_FALSE;
+ widget_data->scrollbar_color_class = edje_object_data_get(elm_layout_edje_get(gengrid), "bar_color_class");
+ widget_data->scrollbar_bg_color_class = edje_object_data_get(elm_layout_edje_get(gengrid), "bar_bg_color_class");
+
+ widget_data->bg_item = _eext_circle_object_item_new();
+ edje_object_color_class_get(elm_layout_edje_get(circle_obj->widget_object),
+ widget_data->scrollbar_bg_color_class,
+ &widget_data->bg_color.r,
+ &widget_data->bg_color.g,
+ &widget_data->bg_color.b,
+ &widget_data->bg_color.a,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ _eext_circle_object_item_name_set(widget_data->bg_item, GENGRID_BG_ITEM_NAME);
+ _eext_circle_object_item_color_set(widget_data->bg_item, 0, 0, 0, 0);
+ if (elm_gengrid_horizontal_get(gengrid))
+ {
+ _eext_circle_object_item_angle_set(widget_data->bg_item, HORIZONTAL_BAR_ANGLE_MAX_SIZE);
+ _eext_circle_object_item_line_width_set(widget_data->bg_item, HORIZONTAL_BAR_WIDTH_SIZE);
+ _eext_circle_object_item_radius_set(widget_data->bg_item, HORIZONTAL_BAR_RADIUS_SIZE);
+ _eext_circle_object_item_angle_offset_set(widget_data->bg_item, HORIZONTAL_BAR_ANGLE_START);
+ }
+ else
+ {
+ _eext_circle_object_item_angle_set(widget_data->bg_item, VERTICAL_BAR_ANGLE_MAX_SIZE);
+ _eext_circle_object_item_line_width_set(widget_data->bg_item, VERTICAL_BAR_WIDTH_SIZE);
+ _eext_circle_object_item_radius_set(widget_data->bg_item, VERTICAL_BAR_RADIUS_SIZE);
+ _eext_circle_object_item_angle_offset_set(widget_data->bg_item, VERTICAL_BAR_ANGLE_START);
+ }
+ _eext_circle_object_item_append(circle_obj, widget_data->bg_item);
+
+ widget_data->item = _eext_circle_object_item_new();
+ edje_object_color_class_get(elm_layout_edje_get(circle_obj->widget_object),
+ widget_data->scrollbar_color_class,
+ &widget_data->color.r,
+ &widget_data->color.g,
+ &widget_data->color.b,
+ &widget_data->color.a,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ _eext_circle_object_item_name_set(widget_data->item, GENGRID_ITEM_NAME);
+ _eext_circle_object_item_color_set(widget_data->item, 0, 0, 0, 0);
+ if (elm_gengrid_horizontal_get(gengrid))
+ {
+ _eext_circle_object_item_angle_set(widget_data->item, HORIZONTAL_BAR_ANGLE_MAX_SIZE);
+ _eext_circle_object_item_line_width_set(widget_data->item, HORIZONTAL_BAR_WIDTH_SIZE);
+ _eext_circle_object_item_radius_set(widget_data->item, HORIZONTAL_BAR_RADIUS_SIZE);
+ _eext_circle_object_item_angle_offset_set(widget_data->item, HORIZONTAL_BAR_ANGLE_START);
+ }
+ else
+ {
+ _eext_circle_object_item_angle_set(widget_data->item, VERTICAL_BAR_ANGLE_MAX_SIZE);
+ _eext_circle_object_item_line_width_set(widget_data->item, VERTICAL_BAR_WIDTH_SIZE);
+ _eext_circle_object_item_radius_set(widget_data->item, VERTICAL_BAR_RADIUS_SIZE);
+ _eext_circle_object_item_angle_offset_set(widget_data->item, VERTICAL_BAR_ANGLE_START);
+ }
+ _eext_circle_object_item_append(circle_obj, widget_data->item);
+
+ circle_obj->widget_data = (void *)widget_data;
+
+ elm_scroller_policy_set(circle_obj->widget_object, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+
+ evas_object_smart_callback_add(circle_obj->widget_object, SIGNAL_ACTIVATED, _eext_circle_object_gengrid_activated_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->main_obj, SIGNAL_ACTIVATED, _eext_circle_object_gengrid_activated_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->widget_object, SIGNAL_DEACTIVATED, _eext_circle_object_gengrid_deactivated_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->main_obj, SIGNAL_DEACTIVATED, _eext_circle_object_gengrid_deactivated_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->widget_object, SIGNAL_SCROLL, _eext_circle_object_gengrid_scroll_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->widget_object, SIGNAL_SCROLL_ANIM_STOP, _eext_circle_object_gengrid_scroll_anim_stop_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->widget_object, SIGNAL_LOADED, _eext_circle_object_gengrid_loaded_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->widget_object, SIGNAL_ITEM_DELETED, _eext_circle_object_gengrid_item_deleted_cb, circle_obj);
+ evas_object_smart_callback_add(circle_obj->widget_object, SIG_BRING_IN_ITEM_ADJUSTED, _eext_circle_object_gengrid_bring_in_item_adjusted_cb, circle_obj);
+ edje_object_signal_callback_add(elm_layout_edje_get(circle_obj->widget_object), "color_class,set", widget_data->scrollbar_color_class, _eext_circle_object_gengrid_change_color_signal_cb, circle_obj);
+ edje_object_signal_callback_add(elm_layout_edje_get(circle_obj->widget_object), "color_class,set", widget_data->scrollbar_bg_color_class, _eext_circle_object_gengrid_change_color_signal_cb, circle_obj);
+
+ eext_rotary_object_event_callback_add(circle_obj->widget_object, _rotary_changed_cb, circle_obj);
+}
+
+EAPI Evas_Object *
+eext_circle_object_gengrid_add(Evas_Object *gengrid,
+ Eext_Circle_Surface *surface)
+{
+ if (!gengrid) return NULL;
+
+ Evas_Object *obj = _eext_circle_object_add(gengrid, gengrid, surface);
+
+ EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return NULL;
+
+ _eext_circle_object_gengrid_init(circle_obj, gengrid);
+
+ return obj;
+}
+
+EAPI void
+eext_circle_object_gengrid_scroller_policy_set(Evas_Object *obj,
+ Elm_Scroller_Policy policy_h,
+ Elm_Scroller_Policy policy_v)
+{
+ EEXT_CIRCLE_OBJECT_GET(obj, circle_obj) return;
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data)
+ {
+ ERR("Eext_Circle_Object type mismatch: expected type [%s], given type [%s]",
+ EEXT_CIRCLE_OBJECT_GENGRID_TYPE, circle_obj->widget_type);
+ return;
+ }
+
+ if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
+ (policy_v >= ELM_SCROLLER_POLICY_LAST))
+ return;
+
+ widget_data->policy_h = policy_h;
+ widget_data->policy_v = policy_v;
+
+ if (widget_data->policy_v == ELM_SCROLLER_POLICY_ON)
+ {
+ _eext_circle_object_gengrid_scrollbar_show(circle_obj, EINA_FALSE);
+ }
+ else
+ {
+ if (widget_data->bar_hide_timer)
+ {
+ ecore_timer_del(widget_data->bar_hide_timer);
+ widget_data->bar_hide_timer = NULL;
+ }
+ _eext_circle_object_gengrid_scrollbar_policy_hide_cb(circle_obj);
+ }
+}
+
+EAPI void
+eext_circle_object_gengrid_scroller_policy_get(const Evas_Object *obj,
+ Elm_Scroller_Policy *policy_h,
+ Elm_Scroller_Policy *policy_v)
+{
+ EEXT_CIRCLE_OBJECT_GET(obj, circle_obj)
+ {
+ if (policy_h) *policy_h = ELM_SCROLLER_POLICY_AUTO;
+ if (policy_v) *policy_v = ELM_SCROLLER_POLICY_AUTO;
+ return;
+ }
+
+ EEXT_CIRCLE_OBJECT_GENGRID_DATA_GET(circle_obj, widget_data)
+ {
+ ERR("Eext_Circle_Object type mismatch: expected type [%s], given type [%s]",
+ EEXT_CIRCLE_OBJECT_GENGRID_TYPE, circle_obj->widget_type);
+ if (policy_h) *policy_h = ELM_SCROLLER_POLICY_AUTO;
+ if (policy_v) *policy_v = ELM_SCROLLER_POLICY_AUTO;
+ return;
+ }
+
+ if (policy_h) *policy_h = widget_data->policy_h;
+ if (policy_v) *policy_v = widget_data->policy_v;
+}