scroller: add loop feature. 12/40412/2
authorJaehwan Kim <jae.hwan.kim@samsung.com>
Sat, 24 Jan 2015 03:01:03 +0000 (12:01 +0900)
committerJaehwan Kim <jae.hwan.kim@samsung.com>
Wed, 3 Jun 2015 11:31:37 +0000 (04:31 -0700)
This feature works the infinite loop horizontally or vertically.
If the content is set, it will be shown repeatedly.
@feature

Conflicts:
src/lib/elm_scroller.c
src/lib/elm_scroller_legacy.h

Change-Id: I1f20b794ae44bc8e5d120901222c7cccadca96b7
origin: upstream

data/themes/edc/elm/scroller.edc
src/bin/test_scroller.c
src/lib/elm_interface_scrollable.c
src/lib/elm_interface_scrollable.eo
src/lib/elm_interface_scrollable.h
src/lib/elm_scroller.c
src/lib/elm_scroller_legacy.h
src/lib/elm_widget_scroller.h

index a2c397e..d70be40 100644 (file)
@@ -1252,3 +1252,55 @@ group { name: "elm/scroller/base/noclip";
       }
    }
 }
+
+group { name: "elm/scroller/contents/default";
+   parts {
+      part { name: "elm.swallow.content";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+         }
+      }
+      part { name: "elm.swallow.content_r";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            fixed: 1 1;
+            rel1 {
+                relative: 1.0 0.0;
+                to: "elm.swallow.content";
+            }
+            rel2 {
+                relative: 2.0 1.0;
+                to: "elm.swallow.content";
+            }
+         }
+      }
+      part { name: "elm.swallow.content_b";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            fixed: 1 1;
+            rel1 {
+                relative: 0.0 1.0;
+                to: "elm.swallow.content";
+            }
+            rel2 {
+                relative: 1.0 2.0;
+                to: "elm.swallow.content";
+            }
+         }
+      }
+      part { name: "elm.swallow.content_rb";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            fixed: 1 1;
+            rel1 {
+                relative: 1.0 1.0;
+                to: "elm.swallow.content";
+            }
+            rel2 {
+                relative: 2.0 2.0;
+                to: "elm.swallow.content";
+            }
+         }
+      }
+   }
+}
index 8628ca2..8457e92 100644 (file)
@@ -113,6 +113,28 @@ my_bt_block_movements_y_axis(void *data, Evas_Object *obj,
 }
 
 void
+my_bt_loop_x_axis(void *data, Evas_Object *obj EINA_UNUSED,
+                  void *event_info EINA_UNUSED)
+{
+   Eina_Bool loop_h, loop_v;
+   Evas_Object *scroller = (Evas_Object *)data;
+
+   elm_scroller_loop_get(scroller, &loop_h, &loop_v);
+   elm_scroller_loop_set(scroller, !loop_h, loop_v);
+}
+
+void
+my_bt_loop_y_axis(void *data, Evas_Object *obj EINA_UNUSED,
+                  void *event_info EINA_UNUSED)
+{
+   Eina_Bool loop_h, loop_v;
+   Evas_Object *scroller = (Evas_Object *)data;
+
+   elm_scroller_loop_get(scroller, &loop_h, &loop_v);
+   elm_scroller_loop_set(scroller, loop_h, !loop_v);
+}
+
+void
 page_change_cb(void *data EINA_UNUSED,
                Evas_Object *obj,
                void *event_info EINA_UNUSED)
@@ -152,7 +174,7 @@ void
 test_scroller(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Evas_Object *win, *bg2, *tb, *tb2, *sc, *bt, *ck1, *ck2, *bx, *bx2, *fr,
-       *ck3, *ck4, *ck5;
+       *ck3, *ck4, *ck5, *ck6, *ck7;
    int i, j, n;
    char buf[PATH_MAX];
    Evas_Coord x = 0, y = 0, w = 0, h = 0;
@@ -214,6 +236,16 @@ test_scroller(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_
    elm_box_pack_end(bx2, ck5);
    evas_object_show(ck5);
 
+   ck6 = elm_check_add(win);
+   elm_object_text_set(ck6, "Loop in X axis");
+   elm_box_pack_end(bx2, ck6);
+   evas_object_show(ck6);
+
+   ck7 = elm_check_add(win);
+   elm_object_text_set(ck7, "Loop in Y axis");
+   elm_box_pack_end(bx2, ck7);
+   evas_object_show(ck7);
+
    sc = elm_scroller_add(win);
    evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL);
@@ -256,6 +288,8 @@ test_scroller(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_
    evas_object_smart_callback_add(ck4, "changed", my_bt_block_movements_y_axis,
                                   sc);
    evas_object_smart_callback_add(ck5, "changed", my_bt_snap_to_pages, sc);
+   evas_object_smart_callback_add(ck6, "changed", my_bt_loop_x_axis, sc);
+   evas_object_smart_callback_add(ck7, "changed", my_bt_loop_y_axis, sc);
 
    bt = elm_spinner_add(win);
    elm_spinner_min_max_set(bt, 0, 500);
index d1b818a..1a99016 100644 (file)
@@ -1209,14 +1209,24 @@ _elm_scroll_wanted_coordinates_update(Elm_Scrollable_Smart_Interface_Data *sid,
    eo_do(sid->obj, elm_interface_scrollable_content_viewport_geometry_get
          (NULL, NULL, &sid->ww, &sid->wh));
 
-   if (x < minx) sid->wx = minx;
-   else if (x > mx) sid->wx = mx;
+   if (x < minx)
+     {
+        if (!sid->loop_h) sid->wx = minx;
+        else sid->wx = mx;
+     }
+   else if (!sid->loop_h && (x > mx)) sid->wx = mx;
+   else if (sid->loop_h && x >= (sid->ww + mx)) sid->wx = 0;
    else if (sid->is_mirrored)
      sid->wx = _elm_scroll_x_mirrored_get(sid->obj, x);
    else sid->wx = x;
 
-   if (y < miny) sid->wy = miny;
-   else if (y > my) sid->wy = my;
+   if (y < miny)
+     {
+        if (!sid->loop_v) sid->wy = miny;
+        else sid->wy = my;
+     }
+   else if (!sid->loop_v && (y > my)) sid->wy = my;
+   else if (sid->loop_v && y >= (sid->wh + my)) sid->wy = 0;
    else sid->wy = y;
 }
 
@@ -1446,6 +1456,7 @@ EOLIAN static void
 _elm_interface_scrollable_content_pos_set(Eo *obj, Elm_Scrollable_Smart_Interface_Data *sid, Evas_Coord x, Evas_Coord y, Eina_Bool sig)
 {
    Evas_Coord mx = 0, my = 0, px = 0, py = 0, spx = 0, spy = 0, minx = 0, miny = 0;
+   Evas_Coord cw = 0, ch = 0, pw = 0, ph = 0;
    double vx, vy;
 
 
@@ -1454,7 +1465,9 @@ _elm_interface_scrollable_content_pos_set(Eo *obj, Elm_Scrollable_Smart_Interfac
    // FIXME: allow for bounce outside of range
    eo_do(sid->pan_obj, elm_obj_pan_pos_max_get(&mx, &my));
    eo_do(sid->pan_obj, elm_obj_pan_pos_min_get(&minx, &miny));
+   eo_do(sid->pan_obj, elm_obj_pan_content_size_get(&cw, &ch));
    eo_do(sid->pan_obj, elm_obj_pan_pos_get(&px, &py));
+   evas_object_geometry_get(sid->pan_obj, NULL, NULL, &pw, &ph);
 
    if (_paging_is_enabled(sid))
      {
@@ -1478,24 +1491,35 @@ _elm_interface_scrollable_content_pos_set(Eo *obj, Elm_Scrollable_Smart_Interfac
           }
      }
 
+   if (sid->loop_h && cw > 0)
+     {
+        if (x < 0) x = cw + (x % cw);
+        else if (x >= cw) x = (x % cw);
+     }
+   if (sid->loop_v && ch > 0)
+     {
+        if (y < 0) y = ch + (y % ch);
+        else if (y >= ch) y = (y % ch);
+     }
+
    if (!_elm_config->thumbscroll_bounce_enable)
      {
 
         if (x < minx) x = minx;
-        if ((x - minx) > mx) x = mx + minx;
+        if (!sid->loop_h && (x - minx) > mx) x = mx + minx;
         if (y < miny) y = miny;
-        if ((y - miny) > my) y = my + miny;
+        if (!sid->loop_v && (y - miny) > my) y = my + miny;
      }
 
    if (!sid->bounce_horiz)
      {
         if (x < minx) x = minx;
-        if ((x - minx) > mx) x = mx + minx;
+        if (!sid->loop_h && (x - minx) > mx) x = mx + minx;
      }
    if (!sid->bounce_vert)
      {
         if (y < miny) y = miny;
-        if (y - miny > my) y = my + miny;
+        if (!sid->loop_v && (y - miny) > my) y = my + miny;
      }
 
    eo_do(sid->pan_obj, elm_obj_pan_pos_set(x, y));
@@ -1520,7 +1544,7 @@ _elm_interface_scrollable_content_pos_set(Eo *obj, Elm_Scrollable_Smart_Interfac
    edje_object_part_drag_value_set
      (sid->edje_obj, "elm.dragable.hbar", vx, 0.0);
 
-   if (!sid->down.bounce_x_animator)
+   if (!sid->loop_h && !sid->down.bounce_x_animator)
      {
         if (((x < minx) && (0 <= sid->down.dx)) ||
             ((x > (mx + minx)) && (0 >= sid->down.dx)))
@@ -1531,7 +1555,7 @@ _elm_interface_scrollable_content_pos_set(Eo *obj, Elm_Scrollable_Smart_Interfac
         else
           sid->bouncemex = EINA_FALSE;
      }
-   if (!sid->down.bounce_y_animator)
+   if (!sid->loop_v && !sid->down.bounce_y_animator)
      {
         if (((y < miny) && (0 <= sid->down.dy)) ||
             ((y > (my + miny)) && (0 >= sid->down.dy)))
@@ -1717,10 +1741,16 @@ _elm_scroll_content_region_show_internal(Evas_Object *obj,
         x = nx;
         y = ny;
      }
-   if ((x + pw) > cw) x = cw - pw;
-   if (x < minx) x = minx;
-   if ((y + ph) > ch) y = ch - ph;
-   if (y < miny) y = miny;
+   if (!sid->loop_h)
+     {
+        if ((x + pw) > cw) x = cw - pw;
+        if (x < minx) x = minx;
+     }
+   if (!sid->loop_v)
+     {
+        if ((y + ph) > ch) y = ch - ph;
+        if (y < miny) y = miny;
+     }
 
    if ((x == px) && (y == py)) return EINA_FALSE;
    *_x = x;
@@ -1992,12 +2022,12 @@ _elm_scroll_momentum_animator(void *data)
         if (!_elm_config->thumbscroll_bounce_enable || !sid->bounce_horiz)
           {
              if (x <= minx) no_bounce_x_end = EINA_TRUE;
-             if ((x - minx) >= maxx) no_bounce_x_end = EINA_TRUE;
+             if (!sid->loop_h && (x - minx) >= maxx) no_bounce_x_end = EINA_TRUE;
           }
         if (!_elm_config->thumbscroll_bounce_enable || !sid->bounce_vert)
           {
              if (y <= miny) no_bounce_y_end = EINA_TRUE;
-             if ((y - miny) >= maxy) no_bounce_y_end = EINA_TRUE;
+             if (sid->loop_v && (y - miny) >= maxy) no_bounce_y_end = EINA_TRUE;
           }
         if ((dt >= 1.0) ||
             ((sid->down.bounce_x_hold) && (sid->down.bounce_y_hold)) ||
@@ -2057,8 +2087,11 @@ _elm_scroll_page_x_get(Elm_Scrollable_Smart_Interface_Data *sid,
         x = x / (sid->pagesize_h);
         x = x * (sid->pagesize_h);
      }
-   if ((x + w) > cw) x = cw - w;
-   if (x < minx) x = minx;
+   if (!sid->loop_h)
+     {
+        if ((x + w) > cw) x = cw - w;
+        if (x < minx) x = minx;
+     }
 
    return x;
 }
@@ -2098,8 +2131,11 @@ _elm_scroll_page_y_get(Elm_Scrollable_Smart_Interface_Data *sid,
         y = y / (sid->pagesize_v);
         y = y * (sid->pagesize_v);
      }
-   if ((y + h) > ch) y = ch - h;
-   if (y < miny) y = miny;
+   if (!sid->loop_v)
+     {
+        if ((y + h) > ch) y = ch - h;
+        if (y < miny) y = miny;
+     }
 
    return y;
 }
@@ -2788,19 +2824,19 @@ _elm_scroll_down_coord_eval(Elm_Scrollable_Smart_Interface_Data *sid,
 
    eo_do(sid->pan_obj, elm_obj_pan_pos_min_get(&minx, &miny));
 
-   if (*x < minx)
+   if (!sid->loop_h && *x < minx)
      *x += (minx - *x) * _elm_config->thumbscroll_border_friction;
-   else if (sid->content_info.w <= sid->w)
+   else if (!sid->loop_h && sid->content_info.w <= sid->w)
      *x += (sid->down.sx - *x) * _elm_config->thumbscroll_border_friction;
-   else if ((sid->content_info.w - sid->w + minx) < *x)
+   else if (!sid->loop_h && (sid->content_info.w - sid->w + minx) < *x)
      *x += (sid->content_info.w - sid->w + minx - *x) *
        _elm_config->thumbscroll_border_friction;
 
-   if (*y < miny)
+   if (!sid->loop_v && *y < miny)
      *y += (miny - *y) * _elm_config->thumbscroll_border_friction;
-   else if (sid->content_info.h <= sid->h)
+   else if (!sid->loop_v && sid->content_info.h <= sid->h)
      *y += (sid->down.sy - *y) * _elm_config->thumbscroll_border_friction;
-   else if ((sid->content_info.h - sid->h + miny) < *y)
+   else if (!sid->loop_v && (sid->content_info.h - sid->h + miny) < *y)
      *y += (sid->content_info.h - sid->h + miny - *y) *
        _elm_config->thumbscroll_border_friction;
 }
@@ -3207,22 +3243,22 @@ _elm_scroll_mouse_move_event_cb(void *data,
 
                 eo_do(sid->pan_obj, elm_obj_pan_pos_min_get(&minx, &miny));
                 eo_do(sid->pan_obj, elm_obj_pan_pos_max_get(&mx, &my));
-                if (y < miny)
+                if (!sid->loop_v && y < miny)
                   y += (miny - y) *
                     _elm_config->thumbscroll_border_friction;
-                else if (my <= 0)
+                else if (!sid->loop_v && my <= 0)
                   y += (sid->down.sy - y) *
                     _elm_config->thumbscroll_border_friction;
-                else if ((my + miny) < y)
+                else if (!sid->loop_v && (my + miny) < y)
                   y += (my + miny - y) *
                     _elm_config->thumbscroll_border_friction;
-                if (x < minx)
+                if (!sid->loop_h && x < minx)
                   x += (minx - x) *
                     _elm_config->thumbscroll_border_friction;
-                else if (mx <= 0)
+                else if (!sid->loop_h && mx <= 0)
                   x += (sid->down.sx - x) *
                     _elm_config->thumbscroll_border_friction;
-                else if ((mx + minx) < x)
+                else if (!sid->loop_h && (mx + minx) < x)
                   x += (mx + minx - x) *
                     _elm_config->thumbscroll_border_friction;
              }
@@ -4290,6 +4326,22 @@ _elm_interface_scrollable_movement_block_get(Eo *obj EINA_UNUSED, Elm_Scrollable
 }
 
 EOLIAN static void
+_elm_interface_scrollable_loop_set(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Eina_Bool loop_h, Eina_Bool loop_v)
+{
+   if (sid->loop_h == loop_h && sid->loop_v == loop_v) return;
+
+   sid->loop_h = loop_h;
+   sid->loop_v = loop_v;
+}
+
+EOLIAN static void
+_elm_interface_scrollable_loop_get(Eo *obj EINA_UNUSED, Elm_Scrollable_Smart_Interface_Data *sid, Eina_Bool *loop_h, Eina_Bool *loop_v)
+{
+   *loop_h = sid->loop_h;
+   *loop_v = sid->loop_v;
+}
+
+EOLIAN static void
 _elm_interface_scrollable_evas_object_smart_add(Eo *obj, Elm_Scrollable_Smart_Interface_Data *sid)
 {
    memset(sid, 0, sizeof(*sid));
@@ -4310,6 +4362,8 @@ _elm_interface_scrollable_evas_object_smart_add(Eo *obj, Elm_Scrollable_Smart_In
    sid->vbar_flags = ELM_SCROLLER_POLICY_AUTO;
    sid->hbar_visible = EINA_TRUE;
    sid->vbar_visible = EINA_TRUE;
+   sid->loop_h = EINA_FALSE;
+   sid->loop_v = EINA_FALSE;
 
    sid->bounce_horiz = EINA_TRUE;
    sid->bounce_vert = EINA_TRUE;
index 320651c..6b6e1ba 100644 (file)
@@ -297,6 +297,32 @@ mixin Elm_Interface_Scrollable(Evas.Scrollable_Interface, Evas.Object_Smart)
             Evas_Coord y;
          }
       }
+      loop {
+         set {
+            /*@ Sets an infinite loop for a scroller.
+
+             This sets an infinite loop for a scroller.
+
+             @since 1.14
+
+             @ingroup Widget
+             */
+         }
+         get {
+            /*@ Gets an infinite loop for a scroller.
+
+             This gets an infinite loop for a scroller.
+
+             @since 1.14
+
+             @ingroup Widget
+             */
+         }
+         values {
+            Eina_Bool loop_h; /*@ The scrolling horizontal loop */
+            Eina_Bool loop_v; /*@ The scrolling vertical loop */
+         }
+      }
       scroll_up_cb {
          set {
             /*@ Set the callback to run when the content has been moved up.
index 25f50a1..c69feaf 100644 (file)
@@ -210,6 +210,8 @@ struct _Elm_Scrollable_Smart_Interface_Data
    Eina_Bool  go_right : 1;
    Eina_Bool  go_up : 1;
    Eina_Bool  go_down : 1;
+   Eina_Bool  loop_h : 1;
+   Eina_Bool  loop_v : 1;
 };
 
 #define ELM_SCROLLABLE_CHECK(obj, ...)                                       \
index b48bb08..f9825a1 100644 (file)
@@ -56,6 +56,28 @@ static const Elm_Action key_actions[] = {
    {NULL, NULL}
 };
 
+static void
+_elm_scroller_proxy_set(Evas_Object *obj, Elm_Scroller_Data *sd, Evas_Object *proxy)
+{
+   Evas_Coord h_pagesize, v_pagesize;
+   Evas_Coord cw, ch;
+   Evas_Object *content = sd->content;
+
+   if (!content) return;
+
+   eo_do(obj, elm_interface_scrollable_paging_get(NULL, NULL, &h_pagesize, &v_pagesize));
+   eo_do(obj, elm_interface_scrollable_content_size_get(&cw, &ch));
+   /* Since Proxy has the texture size limitation problem, we set a key value
+      for evas works in some hackish way to avoid this problem. This hackish
+      code should be removed once evas supports a mechanism like a virtual
+      texture. */
+   evas_object_image_fill_set(proxy, 0, 0, cw, ch);
+   evas_object_size_hint_min_set(proxy, h_pagesize, v_pagesize);
+   evas_object_image_source_clip_set(proxy, EINA_FALSE);
+   evas_object_image_source_set(proxy, content);
+   evas_object_show(proxy);
+}
+
 static Eina_Bool
 _key_action_move(Evas_Object *obj, const char *params)
 {
@@ -289,7 +311,9 @@ _elm_scroller_elm_layout_sizing_eval(Eo *obj, Elm_Scroller_Data *sd)
 {
    Evas_Coord vw = 0, vh = 0, minw = 0, minh = 0, maxw = 0, maxh = 0, w, h,
               vmw, vmh;
+   Evas_Coord h_pagesize, v_pagesize;
    double xw = 0.0, yw = 0.0;
+   int i;
 
    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
 
@@ -323,6 +347,16 @@ _elm_scroller_elm_layout_sizing_eval(Eo *obj, Elm_Scroller_Data *sd)
      vh = minh;
 
    if (sd->content) evas_object_resize(sd->content, vw, vh);
+   if (sd->contents) evas_object_resize(sd->contents, vw, vh);
+
+   for (i = 0 ; i < 3 ; i++)
+     {
+        if (!sd->proxy_content[i]) continue;
+        eo_do((Eo *)obj, elm_interface_scrollable_paging_get(NULL, NULL, &h_pagesize, &v_pagesize));
+        evas_object_image_fill_set(sd->proxy_content[i], 0, 0, vw, vh);
+        evas_object_size_hint_min_set(sd->proxy_content[i],
+                                      h_pagesize, v_pagesize);
+     }
 
    w = -1;
    h = -1;
@@ -595,6 +629,54 @@ _page_change_cb(Evas_Object *obj,
    evas_object_smart_callback_call(obj, SIG_SCROLL_PAGE_CHANGE, NULL);
 }
 
+static void
+_loop_content_set(Evas_Object *obj, Elm_Scroller_Data *sd, Evas_Object *content)
+{
+   if (!sd->contents)
+     {
+        sd->contents = elm_layout_add(obj);
+        evas_object_smart_member_add(sd->contents, obj);
+        elm_layout_theme_set(sd->contents, "scroller", "contents", elm_widget_style_get(obj));
+        evas_object_size_hint_weight_set(sd->contents, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(sd->contents, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+        elm_widget_sub_object_add(obj, sd->contents);
+        elm_widget_on_show_region_hook_set(sd->contents, _show_region_hook, obj);
+     }
+   elm_object_part_content_set(sd->contents, "elm.swallow.content", content);
+   sd->content = content;
+
+   if (sd->loop_h)
+     {
+       if (!sd->proxy_content[0])
+          sd->proxy_content[0] =
+             evas_object_image_add(evas_object_evas_get(sd->contents));
+        _elm_scroller_proxy_set(obj, sd, sd->proxy_content[0]);
+        elm_object_part_content_set(sd->contents, "elm.swallow.content_r",
+                                    sd->proxy_content[0]);
+     }
+
+   if (sd->loop_v)
+     {
+        if (!sd->proxy_content[1])
+          sd->proxy_content[1] =
+             evas_object_image_add(evas_object_evas_get(sd->contents));
+        _elm_scroller_proxy_set(obj, sd, sd->proxy_content[1]);
+        elm_object_part_content_set(sd->contents, "elm.swallow.content_b",
+                                    sd->proxy_content[1]);
+     }
+
+   if (sd->loop_h && sd->loop_v)
+     {
+        if (!sd->proxy_content[2])
+          sd->proxy_content[2] =
+             evas_object_image_add(evas_object_evas_get(sd->contents));
+        _elm_scroller_proxy_set(obj, sd, sd->proxy_content[2]);
+        elm_object_part_content_set(sd->contents, "elm.swallow.content_rb",
+                                    sd->proxy_content[2]);
+     }
+}
+
 EOLIAN static Eina_Bool
 _elm_scroller_elm_container_content_set(Eo *obj, Elm_Scroller_Data *sd, const char *part, Evas_Object *content)
 {
@@ -616,8 +698,24 @@ _elm_scroller_elm_container_content_set(Eo *obj, Elm_Scroller_Data *sd, const ch
           elm_widget_on_show_region_hook_set(content, _show_region_hook, obj);
         elm_widget_sub_object_add(obj, content);
 
+        if (sd->loop_h || sd->loop_v)
+          {
+             _loop_content_set(obj, sd, content);
+             if(sd->contents)
+               content = sd->contents;
+          }
         eo_do(obj, elm_interface_scrollable_content_set(content));
      }
+   else
+     {
+        int i;
+        for (i = 0; i < 3; i ++)
+          {
+             if (!sd->proxy_content[i]) continue;
+             evas_object_del(sd->proxy_content[i]);
+             sd->proxy_content[i] = NULL;
+          }
+     }
 
    elm_layout_sizing_eval(obj);
 
@@ -650,7 +748,10 @@ _elm_scroller_elm_container_content_unset(Eo *obj, Elm_Scroller_Data *sd, const
    if (!sd->content) return NULL;
 
    ret = sd->content;
-   elm_widget_sub_object_del(obj, sd->content);
+   if (sd->loop_h || sd->loop_v)
+     elm_widget_sub_object_del(obj, sd->contents);
+   else
+     elm_widget_sub_object_del(obj, sd->content);
    eo_do(obj, elm_interface_scrollable_content_set(NULL));
    sd->content = NULL;
 
@@ -1125,6 +1226,62 @@ elm_scroller_step_size_get(const Evas_Object *obj,
    eo_do((Eo *) obj, elm_interface_scrollable_step_size_get(x, y));
 }
 
+EAPI void
+elm_scroller_loop_set(Evas_Object *obj,
+                      Eina_Bool loop_h,
+                      Eina_Bool loop_v)
+{
+   ELM_SCROLLABLE_CHECK(obj);
+   ELM_SCROLLER_DATA_GET(obj, sd);
+
+   int i;
+
+   if (sd->loop_h == loop_h && sd->loop_v == loop_v) return;
+
+   sd->loop_h = loop_h;
+   sd->loop_v = loop_v;
+
+   eo_do(obj, elm_interface_scrollable_loop_set(loop_h, loop_v));
+
+   if (sd->content)
+     {
+        if (sd->loop_h || sd->loop_v)
+          {
+             eo_do(obj, elm_interface_scrollable_content_set(NULL));
+             _loop_content_set(obj, sd, sd->content);
+
+             if (sd->contents)
+               {
+                  eo_do(obj, elm_interface_scrollable_content_set(sd->contents));
+                  elm_widget_sub_object_add(obj, sd->contents);
+                  elm_widget_on_show_region_hook_set(sd->contents, _show_region_hook, obj);
+               }
+          }
+        else
+          {
+             for (i = 0 ; i < 3 ; i++)
+               {
+                  if (sd->proxy_content[i])
+                    {
+                       evas_object_del(sd->proxy_content[i]);
+                       sd->proxy_content[i]= NULL;
+                    }
+               }
+          }
+     }
+   elm_layout_sizing_eval(obj);
+}
+
+EAPI void
+elm_scroller_loop_get(const Evas_Object *obj,
+                      Eina_Bool *loop_h,
+                      Eina_Bool *loop_v)
+{
+   ELM_SCROLLABLE_CHECK(obj);
+
+   eo_do(obj, elm_interface_scrollable_loop_get(loop_h, loop_v));
+}
+
 EOLIAN static void
 _elm_scroller_propagate_events_set(Eo *obj, Elm_Scroller_Data *_pd EINA_UNUSED, Eina_Bool propagation)
 {
index b0d87b6..8d49b74 100644 (file)
@@ -494,4 +494,35 @@ EAPI void                          elm_scroller_step_size_set(Evas_Object *obj,
  */
 EAPI void                          elm_scroller_step_size_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
 
+/**
+ * @brief Set an infinite loop_ for a scroller
+ *
+ * @param obj The scroller object
+ * @param loop_h The scrolling horizontal loop
+ * @param loop_v The scrolling vertical loop
+ *
+ * This function sets the infinite loop horizontally or vertically.
+ * If the content is set, it will be shown repeatedly.
+ *
+ * @since 1.14
+ *
+ * @ingroup Scroller
+ */
+EAPI void                          elm_scroller_loop_set(Evas_Object *obj, Eina_Bool loop_h, Eina_Bool loop_v);
+
+/**
+ * @brief Get an infinite loop_ for a scroller
+ *
+ * @param obj The scroller object
+ * @param loop_h The scrolling horizontal loop
+ * @param loop_v The scrolling vertical loop
+ *
+ * @since 1.14
+ *
+ * @see elm_scroller_loop_set() for more details
+ *
+ * @ingroup Scroller
+ */
+EAPI void                          elm_scroller_loop_get(const Evas_Object *obj, Eina_Bool *loop_h, Eina_Bool *loop_v);
+
 #include "elm_scroller.eo.legacy.h"
index 3f264b3..6e6875d 100644 (file)
@@ -30,9 +30,13 @@ struct _Elm_Scroller_Data
    Evas_Object                          *g_layer;
 
    Evas_Object                          *content;
+   Evas_Object                          *contents;
+   Evas_Object                          *proxy_content[3];
 
    Eina_Bool                             min_w : 1;
    Eina_Bool                             min_h : 1;
+   Eina_Bool                             loop_h : 1;
+   Eina_Bool                             loop_v : 1;
 };
 
 /**