[Scroller] Fix the region_show/region_bring_in don't have a limit at a paging movement.
[framework/uifw/elementary.git] / src / lib / elm_interface_scrollable.c
index 0365eed..acf5ffa 100644 (file)
@@ -382,6 +382,11 @@ static const char SCROLL_SMART_NAME[] = "elm_scroll";
 static void _elm_scroll_scroll_bar_size_adjust(
   Elm_Scrollable_Smart_Interface_Data *);
 static void _elm_scroll_wanted_region_set(Evas_Object *);
+static Eina_Bool _paging_is_enabled(Elm_Scrollable_Smart_Interface_Data *sid);
+static Evas_Coord _elm_scroll_page_x_get(
+   Elm_Scrollable_Smart_Interface_Data *sid, int offset, Eina_Bool limit);
+static Evas_Coord _elm_scroll_page_y_get(
+   Elm_Scrollable_Smart_Interface_Data *sid, int offset, Eina_Bool limit);
 static void _elm_scroll_content_pos_get(const Evas_Object *,
                                         Evas_Coord *,
                                         Evas_Coord *);
@@ -1342,6 +1347,40 @@ _elm_scroll_content_pos_set(Evas_Object *obj,
         if (y - miny > my) y = my + miny;
      }
 
+   if (((!_elm_config->thumbscroll_bounce_enable) ||
+        (!sid->bounce_horiz)) && (sid->scrollto.x.animator) &&
+       ((px != x) && ((x == minx) || (x == (mx + minx)))))
+     {
+        ecore_animator_del(sid->scrollto.x.animator);
+        sid->scrollto.x.animator = NULL;
+     }
+
+   if (((!_elm_config->thumbscroll_bounce_enable) ||
+        (!sid->bounce_vert)) && (sid->scrollto.y.animator) &&
+       ((py != y) && ((y == miny) || (y == (my + miny)))))
+     {
+        ecore_animator_del(sid->scrollto.y.animator);
+        sid->scrollto.y.animator = NULL;
+     }
+
+   if (((!_elm_config->thumbscroll_bounce_enable) ||
+        ((!sid->bounce_horiz) && (!sid->bounce_vert))) &&
+       (sid->down.momentum_animator) &&
+       ((((px != x) && ((x == minx) || (x == (mx + minx)))) && (py == y)) ||
+       (((py != y) && ((y == miny) || (y == (my + miny)))) && (px == x))))
+     {
+        ecore_animator_del(sid->down.momentum_animator);
+        sid->down.momentum_animator = NULL;
+        sid->down.bounce_x_hold = EINA_FALSE;
+        sid->down.bounce_y_hold = EINA_FALSE;
+        sid->down.ax = 0;
+        sid->down.ay = 0;
+        sid->down.pdx = 0;
+        sid->down.pdy = 0;
+        if (sid->content_info.resized)
+          _elm_scroll_wanted_region_set(sid->obj);
+     }
+
    psd->api->pos_set(sid->pan_obj, x, y);
    psd->api->pos_get(sid->pan_obj, &spx, &spy);
 
@@ -1364,8 +1403,6 @@ _elm_scroll_content_pos_set(Evas_Object *obj,
    edje_object_part_drag_value_set
      (sid->edje_obj, "elm.dragable.hbar", vx, 0.0);
 
-   if (sig && ((px != x) || (py != y)))
-     edje_object_signal_emit(sid->edje_obj, "elm,action,scroll", "elm");
    if (!sid->down.bounce_x_animator)
      {
         if (((x < minx) && (0 <= sid->down.dx)) ||
@@ -1389,13 +1426,38 @@ _elm_scroll_content_pos_set(Evas_Object *obj,
           sid->bouncemey = EINA_FALSE;
      }
 
-   if ((x != px) || (y != py))
-     {
-        if (sid->cb_func.scroll)
-          sid->cb_func.scroll(obj, NULL);
-     }
    if (sig)
      {
+        if ((x != px) || (y != py))
+          {
+             if (sid->cb_func.scroll)
+               sid->cb_func.scroll(obj, NULL);
+             edje_object_signal_emit(sid->edje_obj, "elm,action,scroll", "elm");
+             if (x < px)
+               {
+                  if (sid->cb_func.scroll_left)
+                    sid->cb_func.scroll_left(obj, NULL);
+                  edje_object_signal_emit(sid->edje_obj, "elm,action,scroll,left", "elm");
+               }
+             if (x > px)
+               {
+                  if (sid->cb_func.scroll_right)
+                    sid->cb_func.scroll_right(obj, NULL);
+                  edje_object_signal_emit(sid->edje_obj, "elm,action,scroll,right", "elm");
+               }
+             if (y < py)
+               {
+                  if (sid->cb_func.scroll_up)
+                    sid->cb_func.scroll_up(obj, NULL);
+                  edje_object_signal_emit(sid->edje_obj, "elm,action,scroll,up", "elm");
+               }
+             if (y > py)
+               {
+                  if (sid->cb_func.scroll_down)
+                    sid->cb_func.scroll_down(obj, NULL);
+                  edje_object_signal_emit(sid->edje_obj, "elm,action,scroll,down", "elm");
+               }
+          }
         if (x != px)
           {
              if (x == minx)
@@ -1543,10 +1605,18 @@ _elm_scroll_content_region_show_internal(Evas_Object *obj,
           _elm_scroll_wanted_region_set(sid->obj);
      }
 
-   x = nx;
+   if (_paging_is_enabled(sid))
+     {
+        x = _elm_scroll_page_x_get(sid, nx - px, EINA_FALSE);
+        y = _elm_scroll_page_y_get(sid, ny - py, EINA_FALSE);
+     }
+   else
+     {
+        x = nx;
+        y = ny;
+     }
    if ((x + pw) > cw) x = cw - pw;
    if (x < minx) x = minx;
-   y = ny;
    if ((y + ph) > ch) y = ch - ph;
    if (y < miny) y = miny;
 
@@ -1822,9 +1892,9 @@ _elm_scroll_momentum_animator(void *data)
 
 static Evas_Coord
 _elm_scroll_page_x_get(Elm_Scrollable_Smart_Interface_Data *sid,
-                       int offset)
+                       int offset, Eina_Bool limit)
 {
-   Evas_Coord x, y, w, h, cw, ch, minx = 0;
+   Evas_Coord x, y, w, h, dx, cw, ch, minx = 0;
 
    if (!sid->pan_obj) return 0;
 
@@ -1835,10 +1905,21 @@ _elm_scroll_page_x_get(Elm_Scrollable_Smart_Interface_Data *sid,
    psd->api->content_size_get(sid->pan_obj, &cw, &ch);
    psd->api->pos_min_get(sid->pan_obj, &minx, NULL);
 
-   x += offset;
-
    if (sid->pagerel_h > 0.0)
      sid->pagesize_h = w * sid->pagerel_h;
+
+   if (!limit)
+     x += offset;
+   else
+     {
+        dx = (sid->pagesize_h * ((double)sid->page_limit_h - 0.5));
+
+        if (offset > 0)
+          x += (abs(offset) < dx ? offset : dx);
+        else
+          x += (abs(offset) < dx ? offset : -dx);
+     }
+
    if (sid->pagesize_h > 0)
      {
         x = x + (sid->pagesize_h * 0.5);
@@ -1853,9 +1934,9 @@ _elm_scroll_page_x_get(Elm_Scrollable_Smart_Interface_Data *sid,
 
 static Evas_Coord
 _elm_scroll_page_y_get(Elm_Scrollable_Smart_Interface_Data *sid,
-                       int offset)
+                       int offset, Eina_Bool limit)
 {
-   Evas_Coord x, y, w, h, cw, ch, miny = 0;
+   Evas_Coord x, y, w, h, dy, cw, ch, miny = 0;
 
    if (!sid->pan_obj) return 0;
 
@@ -1866,10 +1947,21 @@ _elm_scroll_page_y_get(Elm_Scrollable_Smart_Interface_Data *sid,
    psd->api->content_size_get(sid->pan_obj, &cw, &ch);
    psd->api->pos_min_get(sid->pan_obj, NULL, &miny);
 
-   y += offset;
-
    if (sid->pagerel_v > 0.0)
      sid->pagesize_v = h * sid->pagerel_v;
+
+   if (!limit)
+     y += offset;
+   else
+     {
+        dy = (sid->pagesize_v * ((double)sid->page_limit_v - 0.5));
+
+        if (offset > 0)
+          y += (abs(offset) < dy ? offset : dy);
+        else
+          y += (abs(offset) < dy ? offset : -dy);
+     }
+
    if (sid->pagesize_v > 0)
      {
         y = y + (sid->pagesize_v * 0.5);
@@ -2173,7 +2265,7 @@ _elm_scroll_mouse_up_event_cb(void *data,
                       (!elm_widget_drag_child_locked_x_get
                          (sid->obj)))
                     {
-                       pgx = _elm_scroll_page_x_get(sid, ox);
+                       pgx = _elm_scroll_page_x_get(sid, ox, EINA_TRUE);
                        if (pgx != x)
                          {
                             ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
@@ -2185,7 +2277,7 @@ _elm_scroll_mouse_up_event_cb(void *data,
                       (!elm_widget_drag_child_locked_y_get
                          (sid->obj)))
                     {
-                       pgy = _elm_scroll_page_y_get(sid, oy);
+                       pgy = _elm_scroll_page_y_get(sid, oy, EINA_TRUE);
                        if (pgy != y)
                          {
                             ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
@@ -2208,7 +2300,7 @@ _elm_scroll_mouse_up_event_cb(void *data,
                       (!elm_widget_drag_child_locked_x_get
                          (sid->obj)))
                     {
-                       pgx = _elm_scroll_page_x_get(sid, ox);
+                       pgx = _elm_scroll_page_x_get(sid, ox, EINA_TRUE);
                        if (pgx != x)
                          _elm_scroll_scroll_to_x
                            (sid, _elm_config->page_scroll_friction, pgx);
@@ -2217,7 +2309,7 @@ _elm_scroll_mouse_up_event_cb(void *data,
                       (!elm_widget_drag_child_locked_y_get
                          (sid->obj)))
                     {
-                       pgy = _elm_scroll_page_y_get(sid, oy);
+                       pgy = _elm_scroll_page_y_get(sid, oy, EINA_TRUE);
                        if (pgy != y)
                          _elm_scroll_scroll_to_y
                            (sid, _elm_config->page_scroll_friction, pgy);
@@ -2871,8 +2963,8 @@ _elm_scroll_page_adjust(Elm_Scrollable_Smart_Interface_Data *sid)
 
    _elm_scroll_content_viewport_size_get(sid->obj, &w, &h);
 
-   x = _elm_scroll_page_x_get(sid, 0);
-   y = _elm_scroll_page_y_get(sid, 0);
+   x = _elm_scroll_page_x_get(sid, 0, EINA_TRUE);
+   y = _elm_scroll_page_y_get(sid, 0, EINA_TRUE);
 
    _elm_scroll_content_region_set(sid->obj, x, y, w, h);
 }
@@ -3343,6 +3435,46 @@ _elm_scroll_scroll_cb_set(Evas_Object *obj,
 }
 
 static void
+_elm_scroll_scroll_left_cb_set(Evas_Object *obj,
+                          void (*scroll_left_cb)(Evas_Object *obj,
+                                            void *data))
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN(obj, sid);
+
+   sid->cb_func.scroll_left = scroll_left_cb;
+}
+
+static void
+_elm_scroll_scroll_right_cb_set(Evas_Object *obj,
+                          void (*scroll_right_cb)(Evas_Object *obj,
+                                            void *data))
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN(obj, sid);
+
+   sid->cb_func.scroll_right = scroll_right_cb;
+}
+
+static void
+_elm_scroll_scroll_up_cb_set(Evas_Object *obj,
+                          void (*scroll_up_cb)(Evas_Object *obj,
+                                            void *data))
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN(obj, sid);
+
+   sid->cb_func.scroll_up = scroll_up_cb;
+}
+
+static void
+_elm_scroll_scroll_down_cb_set(Evas_Object *obj,
+                          void (*scroll_down_cb)(Evas_Object *obj,
+                                            void *data))
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN(obj, sid);
+
+   sid->cb_func.scroll_down = scroll_down_cb;
+}
+
+static void
 _elm_scroll_edge_left_cb_set(Evas_Object *obj,
                              void (*edge_left_cb)(Evas_Object *obj,
                                                   void *data))
@@ -3655,6 +3787,23 @@ _elm_scroll_single_direction_get(const Evas_Object *obj)
 }
 
 static void
+_elm_scroll_repeat_events_set(Evas_Object *obj,
+                                 Eina_Bool repeat_events)
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN(obj, sid);
+
+   evas_object_repeat_events_set(sid->event_rect, repeat_events);
+}
+
+static Eina_Bool
+_elm_scroll_repeat_events_get(Evas_Object *obj)
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN_VAL(obj, sid, EINA_FALSE);
+
+   return evas_object_repeat_events_get(sid->event_rect);
+}
+
+static void
 _elm_scroll_hold_set(Evas_Object *obj,
                      Eina_Bool hold)
 {
@@ -3739,6 +3888,28 @@ _elm_scroll_paging_get(const Evas_Object *obj,
 }
 
 static void
+_elm_scroll_page_scroll_limit_set(const Evas_Object *obj,
+                                  int page_limit_h,
+                                  int page_limit_v)
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN(obj, sid);
+
+   sid->page_limit_h = page_limit_h;
+   sid->page_limit_v = page_limit_v;
+}
+
+static void
+_elm_scroll_page_scroll_limit_get(const Evas_Object *obj,
+                                  int *page_limit_h,
+                                  int *page_limit_v)
+{
+   ELM_SCROLL_IFACE_DATA_GET_OR_RETURN(obj, sid);
+
+   if (page_limit_h) *page_limit_h = sid->page_limit_h;
+   if (page_limit_v) *page_limit_v = sid->page_limit_v;
+}
+
+static void
 _elm_scroll_current_page_get(const Evas_Object *obj,
                              int *pagenumber_h,
                              int *pagenumber_v)
@@ -3894,6 +4065,8 @@ _elm_scroll_interface_add(Evas_Object *obj)
    sid->step.y = 32;
    sid->page.x = -50;
    sid->page.y = -50;
+   sid->page_limit_h = 9999;
+   sid->page_limit_v = 9999;
    sid->hbar_flags = ELM_SCROLLER_POLICY_AUTO;
    sid->vbar_flags = ELM_SCROLLER_POLICY_AUTO;
    sid->hbar_visible = EINA_TRUE;
@@ -3952,6 +4125,10 @@ EAPI const Elm_Scrollable_Smart_Interface ELM_SCROLLABLE_IFACE =
    _elm_scroll_animate_start_cb_set,
    _elm_scroll_animate_stop_cb_set,
    _elm_scroll_scroll_cb_set,
+   _elm_scroll_scroll_left_cb_set,
+   _elm_scroll_scroll_right_cb_set,
+   _elm_scroll_scroll_up_cb_set,
+   _elm_scroll_scroll_down_cb_set,
    _elm_scroll_edge_left_cb_set,
    _elm_scroll_edge_right_cb_set,
    _elm_scroll_edge_top_cb_set,
@@ -3978,6 +4155,8 @@ EAPI const Elm_Scrollable_Smart_Interface ELM_SCROLLABLE_IFACE =
    _elm_scroll_policy_get,
    _elm_scroll_single_direction_set,
    _elm_scroll_single_direction_get,
+   _elm_scroll_repeat_events_set,
+   _elm_scroll_repeat_events_get,
    _elm_scroll_mirrored_set,
    _elm_scroll_hold_set,
    _elm_scroll_freeze_set,
@@ -3985,6 +4164,8 @@ EAPI const Elm_Scrollable_Smart_Interface ELM_SCROLLABLE_IFACE =
    _elm_scroll_bounce_allow_get,
    _elm_scroll_paging_set,
    _elm_scroll_paging_get,
+   _elm_scroll_page_scroll_limit_set,
+   _elm_scroll_page_scroll_limit_get,
    _elm_scroll_current_page_get,
    _elm_scroll_last_page_get,
    _elm_scroll_page_show,