This feature works the infinite loop horizontally or vertically.
If the content is set, it will be shown repeatedly.
@feature
Change-Id: I1f20b794ae44bc8e5d120901222c7cccadca96b7
Conflicts:
src/lib/elm_scroller.c
src/lib/elm_scroller_legacy.h
}
}
}
+
+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";
+ }
+ }
+ }
+ }
+}
}
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)
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;
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);
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);
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;
}
_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;
// 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))
{
}
}
+ 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));
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)))
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)))
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;
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)) ||
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;
}
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;
}
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;
}
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;
}
}
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));
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;
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.
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, ...) \
{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)
{
{
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);
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;
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)
{
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);
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;
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)
{
*/
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"
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;
};
/**