Add scrollable-like functions to at-spi component object
[platform/upstream/elementary.git] / src / lib / elm_interface_scrollable.c
index fac6349..3f71c9c 100644 (file)
@@ -1671,6 +1671,206 @@ _elm_scroll_bounce_eval(Elm_Scrollable_Smart_Interface_Data *sid)
      }
 }
 
+//TIZEN_ONLY(20171102): add scroll functions for Universal-Switch scroll's functionality
+typedef struct scroll_timer_data {
+  Ecore_Timer *timer;
+  Eo *obj;
+  int step, start_pos, vertical;
+  double step_calc_time;
+  double end_time;
+} scroll_timer_data;
+static scroll_timer_data scroll_info;
+
+static double _scroll_timer_data_calculate(int *pos, int start_pos, int step, int size, int view,
+        double now, double step_calc_time)
+{
+   *pos = start_pos + step * (now - step_calc_time);
+
+   double timeToFinish = 0;
+
+   if (step > 0)
+     {
+       if (*pos + view > size)
+         {
+           *pos = size - view;
+           if (*pos < 0) *pos = 0;
+         }
+       else
+         {
+           timeToFinish = ((double)size - (*pos + view)) / step;
+         }
+     }
+   else if (step < 0)
+     {
+       if (*pos < 0)
+         {
+           *pos = 0;
+         }
+       else
+         {
+           timeToFinish = ((double)*pos) / -step;
+         }
+     }
+
+   if (timeToFinish < 0) timeToFinish = 0;
+
+   return timeToFinish;
+}
+
+static double _scroll_timer_data_update(double now, Eina_Bool force_reset)
+{
+   if (!scroll_info.obj) {
+     return 0;
+   }
+   int size_w, size_h, view_w, view_h, pos_x, pos_y;
+   eo_do(scroll_info.obj,
+      elm_interface_scrollable_content_pos_get(&pos_x, &pos_y),
+      elm_interface_scrollable_content_size_get(&size_w, &size_h),
+      elm_interface_scrollable_content_viewport_geometry_get(NULL, NULL, &view_w, &view_h));
+
+   double timeToFinish = 0;
+   if (scroll_info.vertical)
+     {
+       timeToFinish = _scroll_timer_data_calculate(&pos_y, scroll_info.start_pos, scroll_info.step,
+            size_h, view_h, now, scroll_info.step_calc_time);
+       if (force_reset) scroll_info.start_pos = pos_y;
+     }
+   else
+     {
+       timeToFinish = _scroll_timer_data_calculate(&pos_x, scroll_info.start_pos, scroll_info.step,
+            size_w, view_w, now, scroll_info.step_calc_time);
+       if (force_reset) scroll_info.start_pos = pos_x;
+     }
+   if (force_reset) scroll_info.step_calc_time = now;
+   eo_do(scroll_info.obj, elm_interface_scrollable_content_pos_set(pos_x, pos_y, EINA_TRUE));
+   return timeToFinish;
+}
+
+static Eina_Bool scroll_timer_cb(void *data)
+{
+   double now = ecore_time_get();
+   if (now >= scroll_info.end_time || _scroll_timer_data_update(now, EINA_FALSE) == 0)
+     {
+       scroll_info.timer = NULL;
+       return ECORE_CALLBACK_CANCEL;
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+EOLIAN static double
+_elm_interface_scrollable_content_scroll_auto(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Elm_Scroll_Direction direction, unsigned int ustep)
+{
+   double remainingTime = 0;
+
+   int step = (int)ustep;
+   if (step == 0)
+     {
+       remainingTime = 0;
+       if (scroll_info.timer)
+       {
+         ecore_timer_del(scroll_info.timer);
+         scroll_info.timer = NULL;
+       }
+     }
+   else
+     {
+       double now = ecore_time_get();
+       scroll_info.end_time = now + 1.0f;
+       scroll_info.vertical = direction == ELM_SCROLL_DIRECTION_UP || direction == ELM_SCROLL_DIRECTION_DOWN;
+
+       if (direction == ELM_SCROLL_DIRECTION_UP || direction == ELM_SCROLL_DIRECTION_LEFT) step = -step;
+
+       if (!scroll_info.timer || scroll_info.obj != obj)
+         {
+           scroll_info.obj = obj;
+           scroll_info.step_calc_time = now;
+           scroll_info.step = step;
+
+           if (scroll_info.vertical)
+             eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &scroll_info.start_pos));
+           else
+             eo_do(obj, elm_interface_scrollable_content_pos_get(&scroll_info.start_pos, NULL));
+           remainingTime = _scroll_timer_data_update(now, EINA_FALSE);
+         }
+       else
+         {
+           remainingTime = _scroll_timer_data_update(now, EINA_TRUE);
+           scroll_info.step = step;
+         }
+       // TODO: remove move by timer and some sort of animator object to animate scrolling
+       if (!scroll_info.timer) scroll_info.timer = ecore_timer_add(0.04f, scroll_timer_cb, NULL);
+     }
+   return remainingTime;
+}
+
+static void _scroll_page_calculate(int *pos, int size, int view, int positive_direction)
+{
+   if (positive_direction)
+     {
+       *pos += view;
+       if (*pos + view > size)
+         {
+           *pos = size - view;
+           if (*pos < 0) *pos = 0;
+         }
+     }
+   else
+     {
+       *pos -= view;
+       if (*pos < 0) *pos = 0;
+     }
+}
+
+EOLIAN static void
+_elm_interface_scrollable_content_scroll_page(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Elm_Scroll_Direction direction)
+{
+   int size_w, size_h, view_w, view_h, pos_x, pos_y;
+   eo_do(obj,
+     elm_interface_scrollable_content_pos_get(&pos_x, &pos_y),
+     elm_interface_scrollable_content_size_get(&size_w, &size_h),
+     elm_interface_scrollable_content_viewport_geometry_get(NULL, NULL, &view_w, &view_h));
+
+   if (direction == ELM_SCROLL_DIRECTION_DOWN || direction == ELM_SCROLL_DIRECTION_UP)
+     _scroll_page_calculate(&pos_y, size_h, view_h, direction == ELM_SCROLL_DIRECTION_DOWN);
+   else
+     _scroll_page_calculate(&pos_x, size_w, view_w, direction == ELM_SCROLL_DIRECTION_RIGHT);
+
+   eo_do(obj, elm_interface_scrollable_region_bring_in(pos_x, pos_y, size_w, size_h));
+}
+
+EOLIAN static void
+_elm_interface_scrollable_content_scroll_to_end(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Elm_Scroll_Direction direction)
+{
+   int size_w, size_h, view_w, view_h, pos_x, pos_y;
+   eo_do(obj,
+     elm_interface_scrollable_content_pos_get(&pos_x, &pos_y),
+     elm_interface_scrollable_content_size_get(&size_w, &size_h),
+     elm_interface_scrollable_content_viewport_geometry_get(NULL, NULL, &view_w, &view_h));
+
+   if (direction == ELM_SCROLL_DIRECTION_DOWN)
+     {
+       pos_y = size_h - view_h;
+       if (pos_y < 0) pos_y = 0;
+     }
+   else if (direction == ELM_SCROLL_DIRECTION_RIGHT)
+     {
+       pos_x = size_w - view_w;
+       if (pos_x < 0) pos_x = 0;
+     }
+   else if (direction == ELM_SCROLL_DIRECTION_LEFT)
+     {
+       pos_x = 0;
+     }
+   else if (direction == ELM_SCROLL_DIRECTION_UP)
+     {
+       pos_y = 0;
+     }
+
+   eo_do(obj, elm_interface_scrollable_region_bring_in(pos_x, pos_y, size_w, size_h));
+}
+//
+
 EOLIAN static void
 _elm_interface_scrollable_content_pos_get(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Evas_Coord *x, Evas_Coord *y)
 {