summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaeun Choi <jaeun12.choi@samsung.com>2017-10-26 16:41:38 +0900
committerJaeun Choi <jaeun12.choi@samsung.com>2018-04-23 16:28:41 +0900
commit0c8b01f47501cf0ecd2b41d76ef907aa24bcd6e7 (patch)
tree082d3d9bcd94cfae6bbbb88976dcca98c61f1dc5
parent9cbba2d0b452934b485706de5f8956c984556e29 (diff)
downloadefl-0c8b01f47501cf0ecd2b41d76ef907aa24bcd6e7.tar.gz
efl_ui_pager: add a new class
-rw-r--r--src/Makefile_Elementary.am9
-rw-r--r--src/lib/elementary/Elementary.h3
-rw-r--r--src/lib/elementary/efl_page_transition.c47
-rw-r--r--src/lib/elementary/efl_page_transition.eo24
-rw-r--r--src/lib/elementary/efl_page_transition.h13
-rw-r--r--src/lib/elementary/efl_page_transition_scroll.c315
-rw-r--r--src/lib/elementary/efl_page_transition_scroll.eo10
-rw-r--r--src/lib/elementary/efl_page_transition_scroll.h12
-rw-r--r--src/lib/elementary/efl_ui_pager.c718
-rw-r--r--src/lib/elementary/efl_ui_pager.eo60
-rw-r--r--src/lib/elementary/efl_ui_widget_pager.h92
11 files changed, 1303 insertions, 0 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index 35f9d0ea5f..7a600a21c7 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -105,6 +105,9 @@ elm_public_eolian_files = \
lib/elementary/efl_ui_dnd.eo \
lib/elementary/efl_ui_dnd_container.eo \
lib/elementary/efl_ui_focus_manager_window_root.eo \
+ lib/elementary/efl_ui_pager.eo \
+ lib/elementary/efl_page_transition.eo \
+ lib/elementary/efl_page_transition_scroll.eo \
$(NULL)
# More public files -- FIXME
@@ -401,6 +404,9 @@ includesunstable_HEADERS = \
lib/elementary/efl_ui_widget_pan.h \
lib/elementary/efl_ui_nstate_private.h \
lib/elementary/Efl_Ui.h
+ lib/elementary/efl_ui_widget_pager.h \
+ lib/elementary/efl_page_transition.h \
+ lib/elementary/efl_page_transition_scroll.h
includesunstabledir = $(includedir)/elementary-@VMAJ@
nodist_includesunstable_HEADERS = \
@@ -805,6 +811,9 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_ui_dnd.c \
static_libs/buildsystem/buildsystem.h \
static_libs/buildsystem/buildsystem_autotools.c \
+ lib/elementary/efl_ui_pager.c \
+ lib/elementary/efl_page_transition.c \
+ lib/elementary/efl_page_transition_scroll.c \
$(NULL)
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 76b9b0a39c..e0c5069a0d 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -341,6 +341,9 @@ typedef Eo Efl_Ui_Focus_Manager;
# include <efl_ui_navigation_bar_part_back_button.eo.h>
# include <efl_ui_navigation_layout.eo.h>
# include <efl_ui_stack.eo.h>
+# include <efl_page_transition.eo.h>
+# include <efl_page_transition_scroll.eo.h>
+# include <efl_ui_pager.eo.h>
#endif
/* include deprecated calls last of all */
diff --git a/src/lib/elementary/efl_page_transition.c b/src/lib/elementary/efl_page_transition.c
new file mode 100644
index 0000000000..40023b366a
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition.c
@@ -0,0 +1,47 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#include "efl_page_transition.h"
+
+#define MY_CLASS EFL_PAGE_TRANSITION_CLASS
+
+
+EOLIAN static void
+_efl_page_transition_bind(Eo *obj EINA_UNUSED,
+ Efl_Page_Transition_Data *_pd EINA_UNUSED,
+ Eo *pager EINA_UNUSED)
+{
+}
+
+EOLIAN static void
+_efl_page_transition_init(Eo *obj EINA_UNUSED,
+ Efl_Page_Transition_Data *_pd EINA_UNUSED)
+{
+}
+
+EOLIAN static void
+_efl_page_transition_update(Eo *obj EINA_UNUSED,
+ Efl_Page_Transition_Data *_pd EINA_UNUSED)
+{
+}
+
+EOLIAN static void
+_efl_page_transition_finish(Eo *obj EINA_UNUSED,
+ Efl_Page_Transition_Data *_pd EINA_UNUSED)
+{
+}
+
+EOLIAN static Eo *
+_efl_page_transition_efl_object_constructor(Eo *obj,
+ Efl_Page_Transition_Data *sd EINA_UNUSED)
+{
+ obj = efl_constructor(efl_super(obj, MY_CLASS));
+
+ return obj;
+}
+
+#include "efl_page_transition.eo.c"
diff --git a/src/lib/elementary/efl_page_transition.eo b/src/lib/elementary/efl_page_transition.eo
new file mode 100644
index 0000000000..8f3e6279b7
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition.eo
@@ -0,0 +1,24 @@
+class Efl.Page.Transition (Efl.Object)
+{
+ [[Efl ui pagescroller transition effect class]]
+ methods {
+ bind {
+ [[set object]]
+ params {
+ @in pager: Efl.Object; [[pager object]]
+ }
+ }
+ init {
+ [[set up initial variables]]
+ }
+ update {
+ [[transition effect update]]
+ }
+ finish {
+ [[After page moving is done]]
+ }
+ }
+ implements {
+ Efl.Object.constructor;
+ }
+}
diff --git a/src/lib/elementary/efl_page_transition.h b/src/lib/elementary/efl_page_transition.h
new file mode 100644
index 0000000000..26413d1762
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition.h
@@ -0,0 +1,13 @@
+#ifndef EFL_PAGE_TRANSITION_H
+#define EFL_PAGE_TRANSITION_H
+
+
+
+typedef struct _Efl_Page_Transition_Data Efl_Page_Transition_Data;
+
+struct _Efl_Page_Transition_Data
+{
+ Efl_Canvas_Object *target;
+};
+
+#endif
diff --git a/src/lib/elementary/efl_page_transition_scroll.c b/src/lib/elementary/efl_page_transition_scroll.c
new file mode 100644
index 0000000000..55008ee384
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition_scroll.c
@@ -0,0 +1,315 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#include "efl_page_transition_scroll.h"
+#include "efl_ui_widget_pager.h"
+
+//FIXME use ELM_RECTS_INTERSECT
+#define INTERSECT(x1, w1, x2, w2) \
+ (!(((x1) + (w1) <= (x2)) || ((x2) + (w2) <= (x1))))
+#define RECT_INTERSECT(x1, y1, w1, h1, x2, y2, w2, h2) \
+ ((INTERSECT(x1, w1, x2, w2)) && (INTERSECT(y1, h1, y2, h2)))
+
+#define DEBUG 0
+
+EOLIAN static void
+_efl_page_transition_scroll_efl_page_transition_bind(Eo *obj EINA_UNUSED,
+ Efl_Page_Transition_Scroll_Data *_pd,
+ Eo *pager)
+{
+ _pd->pager = pager;
+}
+
+EOLIAN static void
+_efl_page_transition_scroll_efl_page_transition_init(Eo *obj,
+ Efl_Page_Transition_Scroll_Data *_pd)
+{
+ EFL_UI_PAGER_DATA_GET(_pd->pager, pd);
+ Eina_List *list;
+ Page_Info *pi;
+ int content_w;
+
+#if 0
+ double d;
+ int n;
+
+ d = (double) pd->w / ((double) pd->page_spec.w + (double) pd->page_spec.padding);
+ n = (int) d;
+ d -= n;
+
+ if ((n % 2) == 0)
+ {
+ n -= 1;
+ d += 1.0;
+ }
+ if (d > 0) n += 2;
+
+ pd->page_info_num = n;
+#endif
+
+ EINA_LIST_FOREACH(pd->page_infos, list, pi)
+ {
+ pi->x = pd->x + (pd->w / 2)
+ + pi->pos * (pd->page_spec.w + pd->page_spec.padding)
+ - (pd->page_spec.w / 2);
+ pi->y = pd->y + (pd->h / 2) - (pd->page_spec.h / 2);
+ pi->w = pd->page_spec.w;
+ pi->h = pd->page_spec.h;
+
+ if (RECT_INTERSECT(pd->x, pd->y, pd->w, pd->h,
+ pi->x, pi->y, pi->w, pi->h) &&
+ (pi->id != 0) && (pi->id != (pd->page_info_num - 1)))
+ {
+ pi->vis_page = EINA_TRUE;
+ pi->visible = EINA_TRUE;
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.foreclip);
+ }
+ else
+ {
+ pi->vis_page = EINA_FALSE;
+ pi->visible = EINA_FALSE;
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.backclip);
+ }
+ }
+
+ content_w = pd->page_spec.w
+ + ((pd->page_spec.w + pd->page_spec.padding) * pd->side_page_num * 2);
+
+ if (content_w < pd->w)
+ {
+ pd->viewport.x = pd->x + ((pd->w - content_w) / 2);
+ pd->viewport.y = pd->y;
+ pd->viewport.w = content_w;
+ pd->viewport.h = pd->h;
+ }
+ else
+ {
+ pd->viewport.x = pd->x;
+ pd->viewport.y = pd->y;
+ pd->viewport.w = pd->w;
+ pd->viewport.h = pd->h;
+ }
+
+ efl_gfx_position_set(pd->viewport.foreclip,
+ EINA_POSITION2D(pd->viewport.x, pd->viewport.y));
+ efl_gfx_size_set(pd->viewport.foreclip,
+ EINA_SIZE2D(pd->viewport.w, pd->viewport.h));
+
+ //FIXME need to call update function?
+ // or can we substitute the code with size_set and position_set
+ // and do something more for dynamic viewport size change?
+ efl_page_transition_update(obj);
+}
+
+EOLIAN static void
+_efl_page_transition_scroll_efl_page_transition_update(Eo *obj EINA_UNUSED,
+ Efl_Page_Transition_Scroll_Data *_pd EINA_UNUSED)
+{
+ Evas_Object *pager = _pd->pager;
+
+ if (!pager) return;
+
+ EFL_UI_PAGER_DATA_GET(pager, pd);
+
+ int tmp_id;
+ Eo *tmp;
+ Eina_List *list;
+ Page_Info *pi, *tpi;
+
+ double t = pd->move;
+ if (t < 0) t *= (-1);
+
+ EINA_LIST_FOREACH(pd->page_infos, list, pi)
+ {
+ if (pd->move == 0.0)
+ {
+ if (!pi->vis_page && !!pi->content)
+ {
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.backclip);
+ efl_pack_unpack(pi->obj, pi->content);
+ efl_canvas_object_clip_set(pi->content, pd->viewport.backclip);
+
+ pi->content_num = -1;
+ pi->content = NULL;
+ pi->visible = EINA_FALSE;
+ }
+ else if (pi->vis_page && !pi->content)
+ {
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.foreclip);
+ tmp_id = (pd->current_page + pi->pos + pd->cnt) % pd->cnt;
+ tmp = eina_list_nth(pd->content_list, tmp_id);
+
+ efl_pack(pi->obj, tmp);
+ efl_canvas_object_clip_set(tmp, pd->viewport.foreclip);
+
+ pi->content_num = tmp_id;
+ pi->content = tmp;
+ pi->visible = EINA_TRUE;
+ }
+
+ efl_gfx_position_set(pi->obj, EINA_POSITION2D(pi->x, pi->y));
+ efl_gfx_size_set(pi->obj, EINA_SIZE2D(pi->w, pi->h));
+ }
+ else
+ {
+ if (pd->move < 0)
+ tpi = pi->next;
+ else
+ tpi = pi->prev;
+
+ pi->tx = tpi->x * t + pi->x * (1 - t);
+ pi->ty = tpi->y * t + pi->y * (1 - t);
+ pi->tw = tpi->w * t + pi->w * (1 - t);
+ pi->th = tpi->h * t + pi->h * (1 - t);
+
+ efl_gfx_position_set(pi->obj, EINA_POSITION2D(pi->tx, pi->ty));
+ efl_gfx_size_set(pi->obj, EINA_SIZE2D(pi->tw, pi->th));
+
+ if ((!pi->vis_page && tpi->vis_page) || (pi->vis_page && !tpi->vis_page))
+ {
+ if (!RECT_INTERSECT(pi->tx, pi->ty, pi->tw, pi->th,
+ pd->viewport.x, pd->viewport.y,
+ pd->viewport.w, pd->viewport.h))
+ {
+ if (pi->visible)
+ {
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.backclip);
+
+ if (!!pi->content) efl_pack_unpack(pi->obj, pi->content);
+ efl_canvas_object_clip_set(pi->content, pd->viewport.backclip);
+
+ pi->content_num = -1;
+ pi->content = NULL;
+ pi->visible = EINA_FALSE;
+ }
+ }
+ else
+ {
+ if (!pi->visible)
+ {
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.foreclip);
+
+ if (!!pi->content) efl_pack_unpack(pi->obj, pi->content);
+ efl_canvas_object_clip_set(pi->content, pd->viewport.backclip);
+
+ tmp_id = (pd->current_page + pi->pos + pd->cnt) % pd->cnt;
+ tmp = eina_list_nth(pd->content_list, tmp_id);
+
+ efl_pack(pi->obj, tmp);
+ efl_canvas_object_clip_set(tmp, pd->viewport.foreclip);
+
+ pi->content_num = tmp_id;
+ pi->content = tmp;
+ pi->visible = EINA_TRUE;
+ }
+ }
+ }
+ }
+ }
+
+#if DEBUG
+ EINA_LIST_FOREACH(pd->page_infos, list, pi)
+ {
+ ERR("[id: %d] vis_page %d visible %d content %d",
+ pi->id, pi->vis_page, pi->visible, pi->content_num);
+ }
+ printf("\n");
+#endif
+
+}
+
+EOLIAN static void
+_efl_page_transition_scroll_efl_page_transition_finish(Eo *obj EINA_UNUSED,
+ Efl_Page_Transition_Scroll_Data *_pd EINA_UNUSED)
+{
+ Evas_Object *pager = _pd->pager;
+
+ if (!pager) return;
+
+ EFL_UI_PAGER_DATA_GET(pager, pd);
+
+ Eina_List *list;
+ Page_Info *pi;
+
+ if (pd->move == 1.0)
+ {
+ EINA_LIST_FOREACH(pd->page_infos, list, pi)
+ {
+ pi->id = (pi->id - 1 + pd->page_info_num) % pd->page_info_num;
+ pi->pos = pi->id - (pd->side_page_num + 1);
+
+ pi->x = pi->tx;
+ pi->y = pi->ty;
+ pi->w = pi->tw;
+ pi->h = pi->th;
+
+ if (RECT_INTERSECT(pi->x, pi->y, pi->w, pi->h,
+ pd->viewport.x, pd->viewport.y,
+ pd->viewport.w, pd->viewport.h) &&
+ (pi->id != 0) && (pi->id != (pd->page_info_num - 1)))
+ {
+ pi->vis_page = EINA_TRUE;
+ pi->visible = EINA_TRUE;
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.foreclip);
+ }
+ else
+ {
+ pi->vis_page = EINA_FALSE;
+ pi->visible = EINA_FALSE;
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.backclip);
+ }
+ }
+ pd->current_page = (pd->current_page + 1) % pd->cnt;
+ pd->head = pd->head->next;
+ pd->tail = pd->tail->next;
+ }
+ else if (pd->move == -1.0)
+ {
+ EINA_LIST_FOREACH(pd->page_infos, list, pi)
+ {
+ pi->id = (pi->id + 1) % pd->page_info_num;
+ pi->pos = pi->id - (pd->side_page_num + 1);
+
+ pi->x = pi->tx;
+ pi->y = pi->ty;
+ pi->w = pi->tw;
+ pi->h = pi->th;
+
+ if (RECT_INTERSECT(pi->x, pi->y, pi->w, pi->h,
+ pd->viewport.x, pd->viewport.y,
+ pd->viewport.w, pd->viewport.h) &&
+ (pi->id != 0) && (pi->id != (pd->page_info_num - 1)))
+ {
+ pi->vis_page = EINA_TRUE;
+ pi->visible = EINA_TRUE;
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.foreclip);
+ }
+ else
+ {
+ pi->vis_page = EINA_FALSE;
+ pi->visible = EINA_FALSE;
+ efl_canvas_object_clip_set(pi->obj, pd->viewport.backclip);
+ }
+ }
+ pd->current_page = (pd->current_page - 1 + pd->cnt) % pd->cnt;
+ pd->head = pd->head->prev;
+ pd->tail = pd->tail->prev;
+ }
+
+#if DEBUG
+ EINA_LIST_FOREACH(pd->page_infos, list, pi)
+ {
+ ERR("[id: %d] vis_page %d visible %d content %d",
+ pi->id, pi->vis_page, pi->visible, pi->content_num);
+ }
+ printf("\n");
+#endif
+
+ pd->move = 0.0;
+}
+
+#include "efl_page_transition_scroll.eo.c"
diff --git a/src/lib/elementary/efl_page_transition_scroll.eo b/src/lib/elementary/efl_page_transition_scroll.eo
new file mode 100644
index 0000000000..f9bcf48df1
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition_scroll.eo
@@ -0,0 +1,10 @@
+class Efl.Page.Transition.Scroll (Efl.Page.Transition)
+{
+ [[Efl ui pagescroller effect scroll class]]
+ implements {
+ Efl.Page.Transition.bind;
+ Efl.Page.Transition.init;
+ Efl.Page.Transition.update;
+ Efl.Page.Transition.finish;
+ }
+}
diff --git a/src/lib/elementary/efl_page_transition_scroll.h b/src/lib/elementary/efl_page_transition_scroll.h
new file mode 100644
index 0000000000..687d210306
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition_scroll.h
@@ -0,0 +1,12 @@
+#ifndef EFL_PAGE_TRANSITION_SCROLL_H
+#define EFL_PAGE_TRANSITION_SCROLL_H
+
+
+typedef struct _Efl_Page_Transition_Scroll_Data Efl_Page_Transition_Scroll_Data;
+
+struct _Efl_Page_Transition_Scroll_Data
+{
+ Efl_Object *pager;
+};
+
+#endif
diff --git a/src/lib/elementary/efl_ui_pager.c b/src/lib/elementary/efl_ui_pager.c
new file mode 100644
index 0000000000..a8c9b69b04
--- /dev/null
+++ b/src/lib/elementary/efl_ui_pager.c
@@ -0,0 +1,718 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#define EFL_PACK_LAYOUT_PROTECTED
+
+#include <Elementary.h>
+#include "elm_priv.h"
+#include "efl_ui_widget_pager.h"
+#include "efl_page_transition.h"
+
+#define MY_CLASS EFL_UI_PAGER_CLASS
+
+#define CURRENT_PAGE_SET 0
+
+#define INTERSECT(x1, w1, x2, w2) \
+ (!(((x1) + (w1) <= (x2)) || ((x2) + (w2) <= (x1))))
+#define RECT_INTERSECT(x1, y1, w1, h1, x2, y2, w2, h2) \
+ ((INTERSECT(x1, w1, x2, w2)) && (INTERSECT(y1, h1, y2, h2)))
+
+
+static void
+_efl_ui_pager_update(Eo *obj)
+{
+ EFL_UI_PAGER_DATA_GET(obj, pd);
+
+ if (pd->cnt == 0) return;
+
+ efl_page_transition_update(pd->transition);
+
+ efl_event_callback_call(obj, EFL_UI_PAGER_EVENT_UPDATED, NULL);
+}
+
+static void
+_job(void *data)
+{
+ Evas_Object *obj = data;
+ EFL_UI_PAGER_DATA_GET(obj, sd);
+
+ double t = 0;
+ Eina_Bool prev = EINA_FALSE, next = EINA_FALSE;
+
+ sd->job = NULL;
+
+ if (sd->dir == EFL_UI_DIR_HORIZONTAL)
+ t = ((double)sd->mouse_down.x - (double)sd->mouse_x) / (double)sd->w;
+ else
+ t = ((double)sd->mouse_down.y - (double)sd->mouse_y) / (double)sd->h;
+
+ if (t > 1.0) t = 1.0;
+ else if (t < -1.0) t = -1.0;
+
+ if (sd->move == t) return;
+
+ sd->move = t;
+
+ if (t < 0) prev = EINA_TRUE;
+ else if (t > 0) next = EINA_TRUE;
+
+ if (sd->prev_block && prev) return;
+ else if (sd->next_block && next) return;
+
+#if 0
+ //FIXME loop is not handled yet
+ if (!sd->loop && ((next && sd->mouse_down.page == (sd->cnt - 1))
+ || (prev && sd->mouse_down.page == 0))) return;
+#endif
+
+ _efl_ui_pager_update(obj);
+}
+
+static Eina_Bool
+_animator(void *data, double pos)
+{
+ Evas_Object *obj = data;
+ double p;
+
+ EFL_UI_PAGER_DATA_GET(obj, sd);
+
+ p = ecore_animator_pos_map(pos, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
+
+ if (sd->move < 0.0)
+ {
+ if (sd->move > -0.5)
+ sd->move = sd->move * (1 - p);
+ else
+ sd->move = (-1) - (-1 - sd->move) * (1 - p);
+ }
+ else
+ {
+ if (sd->move < 0.5)
+ sd->move = sd->move * (1 - p);
+ else
+ sd->move = 1 - (1 - sd->move) * (1 - p);
+ }
+
+ _efl_ui_pager_update(obj);
+
+ if (pos < 1.0) return ECORE_CALLBACK_RENEW;
+
+ if (sd->move == 1.0 || sd->move == -1.0)
+ efl_page_transition_finish(sd->transition);
+
+ sd->animator = NULL;
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_mouse_down_cb(void *data,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
+ void *event_info)
+{
+ Evas_Event_Mouse_Down *ev = event_info;
+ Evas_Object *pc = data;
+ EFL_UI_PAGER_DATA_GET(pc, sd);
+
+ if (ev->button != 1) return;
+ if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+
+ if (sd->move != 0.0) return; //FIXME
+
+ ELM_SAFE_FREE(sd->animator, ecore_animator_del);
+
+ sd->move_started = EINA_FALSE;
+ sd->mouse_down.enabled = EINA_TRUE;
+
+ sd->mouse_x = ev->canvas.x - sd->x;
+ sd->mouse_y = ev->canvas.y - sd->y;
+
+ sd->mouse_down.x = sd->mouse_x;
+ sd->mouse_down.y = sd->mouse_y;
+}
+
+static void
+_mouse_move_cb(void *data,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
+ void *event_info)
+{
+ Evas_Event_Mouse_Move *ev = event_info;
+ Evas_Object *pc = data;
+ EFL_UI_PAGER_DATA_GET(pc, sd);
+
+ if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+ if (!sd->mouse_down.enabled) return;
+
+ sd->mouse_x = ev->cur.canvas.x - sd->x;
+ sd->mouse_y = ev->cur.canvas.y - sd->y;
+
+ if (!sd->move_started)
+ {
+ Evas_Coord dx, dy;
+ dx = sd->mouse_x - sd->mouse_down.x;
+ dy = sd->mouse_y - sd->mouse_down.y;
+
+ if (((dx * dx) + (dy * dy)) <=
+ (_elm_config->finger_size * _elm_config->finger_size / 4))
+ return;
+
+ sd->move_started = EINA_TRUE;
+ }
+
+ ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+
+ ecore_job_del(sd->job);
+ sd->job = ecore_job_add(_job, pc);
+}
+
+static void
+_mouse_up_cb(void *data,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
+ void *event_info)
+{
+ Evas_Event_Mouse_Up *ev = event_info;
+ Evas_Object *pc = data;
+ EFL_UI_PAGER_DATA_GET(pc, sd);
+ double time;
+
+ if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+ if (!sd->mouse_down.enabled) return;
+
+ sd->mouse_down.enabled = EINA_FALSE;
+
+ ELM_SAFE_FREE(sd->job, ecore_job_del);
+
+ if (sd->move == 1.0 || sd->move == -1.0)
+ {
+ efl_page_transition_finish(sd->transition);
+ return;
+ }
+
+ if (sd->move < 0.0)
+ {
+ if (sd->move > -0.5) time = (-1) * sd->move;
+ else time = 1 + sd->move;
+ }
+ else
+ {
+ if (sd->move < 0.5) time = sd->move;
+ else time = 1 - sd->move;
+ }
+
+ if (time < 0.01) time = 0.01;
+ else if (time > 0.99) time = 0.99;
+
+ ecore_animator_del(sd->animator);
+ sd->animator = ecore_animator_timeline_add(time, _animator, pc);
+}
+
+EOLIAN static Eo *
+_efl_ui_pager_efl_object_constructor(Eo *obj,
+ Efl_Ui_Pager_Data *sd EINA_UNUSED)
+{
+ obj = efl_constructor(efl_super(obj, MY_CLASS));
+
+ return obj;
+}
+
+static void
+_page_info_set(Eo *obj, Efl_Ui_Pager_Data *pd)
+{
+ Eina_List *list;
+ Page_Info *pi;
+ int i, tmp;
+
+ for (i = 0; i < pd->page_info_num; i++)
+ {
+ pi = (Page_Info *)malloc(sizeof(Page_Info));
+ if (i == 0) pd->head = pi;
+ else if (i == 4) pd->tail = pi;
+ pi->id = i;
+ pi->pos = i - (pd->side_page_num + 1);
+ pi->content_num = -1;
+ pi->content = NULL;
+ pi->obj = efl_add(EFL_UI_BOX_CLASS, obj);
+ pd->page_infos = eina_list_append(pd->page_infos, pi);
+ }
+
+ EINA_LIST_FOREACH(pd->page_infos, list, pi)
+ {
+ tmp = (pi->id + 1) % pd->page_info_num;
+ pi->next = eina_list_nth(pd->page_infos, tmp);
+
+ tmp = (pi->id - 1 + pd->page_info_num) % pd->page_info_num;
+ pi->prev = eina_list_nth(pd->page_infos, tmp);
+ }
+}
+
+static void
+_event_handler_create(Eo *obj, Efl_Ui_Pager_Data *sd)
+{
+ sd->event = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
+ evas_object_evas_get(obj));
+ evas_object_color_set(sd->event, 0, 0, 0, 0);
+
+ evas_object_event_callback_add(sd->event, EVAS_CALLBACK_MOUSE_DOWN,
+ _mouse_down_cb, obj);
+ evas_object_event_callback_add(sd->event, EVAS_CALLBACK_MOUSE_UP,
+ _mouse_up_cb, obj);
+ evas_object_event_callback_add(sd->event, EVAS_CALLBACK_MOUSE_MOVE,
+ _mouse_move_cb, obj);
+}
+
+EOLIAN static void
+_efl_ui_pager_efl_canvas_group_group_add(Eo *obj,
+ Efl_Ui_Pager_Data *pd)
+{
+ pd->obj = obj;
+ efl_canvas_group_add(efl_super(obj, MY_CLASS));
+ elm_widget_sub_object_parent_add(obj);
+
+ pd->cnt = 0;
+ pd->current_page = -1;
+ pd->side_page_num = 1;
+ pd->page_info_num = 5;
+ pd->move = 0.0;
+ pd->dir = EFL_UI_DIR_HORIZONTAL;
+
+ pd->viewport.foreclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
+ evas_object_evas_get(obj));
+ evas_object_static_clip_set(pd->viewport.foreclip, EINA_TRUE);
+
+ pd->viewport.backclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
+ evas_object_evas_get(obj));
+ evas_object_static_clip_set(pd->viewport.backclip, EINA_TRUE);
+ efl_gfx_visible_set(pd->viewport.backclip, EINA_FALSE);
+
+ _page_info_set(obj, pd);
+ _event_handler_create(obj, pd);
+
+ elm_widget_can_focus_set(obj, EINA_TRUE);
+}
+
+EOLIAN static void
+_efl_ui_pager_efl_canvas_group_group_del(Eo *obj,
+ Efl_Ui_Pager_Data *pd)
+{
+ Page_Info *pi;
+ EINA_LIST_FREE(pd->page_infos, pi)
+ {
+ efl_del(pi->obj);
+ free(pi);
+ }
+
+ efl_canvas_group_del(efl_super(obj, MY_CLASS));
+}
+
+static void
+_page_info_change(Eo *obj, int delta)
+{
+ EFL_UI_PAGER_DATA_GET(obj, pd);
+ Page_Info *pi;
+ int i;
+
+ if (delta > 0)
+ {
+ for (i = 0; i < delta; i++)
+ {
+ pi = (Page_Info *)malloc(sizeof(Page_Info));
+ pi->obj = efl_add(EFL_UI_BOX_CLASS, obj);
+ pi->content_num = -1;
+ pi->content = NULL;
+ pd->page_infos = eina_list_prepend_relative(pd->page_infos, pi, pd->head);
+
+ pi->next = pd->head;
+ pd->head->prev = pi;
+ pi->prev = pd->tail;
+ pd->tail->next = pi;
+ pd->head = pi;
+
+ pi = (Page_Info *)malloc(sizeof(Page_Info));
+ pi->obj = efl_add(EFL_UI_BOX_CLASS, obj);
+ pi->content_num = -1;
+ pi->content = NULL;
+ pd->page_infos = eina_list_append_relative(pd->page_infos, pi, pd->tail);
+
+ pi->next = pd->head;
+ pd->head->prev = pi;
+ pi->prev = pd->tail;
+ pd->tail->next = pi;
+ pd->tail = pi;
+ }
+
+ efl_gfx_stack_raise(pd->event); //FIXME
+ }
+ else
+ {
+ for (i = 0; i > delta; i--)
+ {
+ pi = pd->head;
+ pd->head = pi->next;
+
+ efl_canvas_object_clip_set(pi->content, pd->viewport.backclip);
+ efl_pack_unpack(pi->obj, pi->content);
+ efl_del(pi->obj);
+ pi->prev->next = pi->next;
+ pi->next->prev = pi->prev;
+ pd->page_infos = eina_list_remove(pd->page_infos, pi);
+ free(pi);
+
+ pi = pd->tail;
+ pd->tail = pi->prev;
+
+ efl_canvas_object_clip_set(pi->content, pd->viewport.backclip);
+ efl_pack_unpack(pi->obj, pi->content);
+ efl_del(pi->obj);
+ pi->prev->next = pi->next;
+ pi->next->prev = pi->prev;
+ pd->page_infos = eina_list_remove(pd->page_infos, pi);
+ free(pi);
+ }
+ }
+
+ pi = pd->head;
+ for (i = 0; i < pd->page_info_num; i++)
+ {
+ pi->id = i;
+ pi->pos = i - (pd->side_page_num + 1);
+ pi = pi->next;
+ }
+}
+
+static void
+_page_info_job(void *data)
+{
+ Eo *obj = data;
+ EFL_UI_PAGER_DATA_GET(obj, pd);
+
+ pd->page_info_job = NULL;
+
+ efl_page_transition_init(pd->transition);
+}
+
+EOLIAN static void
+_efl_ui_pager_efl_gfx_size_set(Eo *obj,
+ Efl_Ui_Pager_Data *sd,
+ Eina_Size2D sz)
+{
+ if ((sd->w == sz.w) && (sd->h == sz.h)) return;
+
+ efl_gfx_size_set(efl_super(obj, MY_CLASS), sz);
+
+ sd->w = sz.w;
+ sd->h = sz.h;
+
+ efl_gfx_size_set(sd->event, sz);
+
+ if (sd->page_info_job) ecore_job_del(sd->page_info_job);
+ sd->page_info_job = ecore_job_add(_page_info_job, obj);
+}
+
+EOLIAN static void
+_efl_ui_pager_efl_gfx_position_set(Eo *obj,
+ Efl_Ui_Pager_Data *sd,
+ Eina_Position2D pos)
+{
+ if ((sd->x == pos.x) && (sd->y == pos.y)) return;
+
+ efl_gfx_position_set(efl_super(obj, MY_CLASS), pos);
+
+ sd->x = pos.x;
+ sd->y = pos.y;
+
+ efl_gfx_position_set(sd->event, pos);
+
+ if (sd->page_info_job) ecore_job_del(sd->page_info_job);
+ sd->page_info_job = ecore_job_add(_page_info_job, obj);
+}
+
+EOLIAN static int
+_efl_ui_pager_efl_container_content_count(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *pd)
+{
+ return eina_list_count(pd->content_list);
+}
+
+EOLIAN static Eina_Bool
+_efl_ui_pager_efl_pack_linear_pack_end(Eo *obj,
+ Efl_Ui_Pager_Data *pd,
+ Efl_Gfx *subobj)
+{
+ Page_Info *pi;
+ int id, pi_id, len, i;
+
+ efl_parent_set(subobj, obj);
+
+ pd->content_list = eina_list_append(pd->content_list, subobj);
+ efl_gfx_stack_raise(pd->event); //FIXME
+ id = pd->cnt;
+
+ if (pd->cnt == 0) pd->current_page = 0;
+ pd->cnt += 1;
+
+ //FIXME 1.fix logic: current code works only when the current page num is 0
+ //FIXME 2.use ecore job: don't need to unpack and pack everytime a page is packed
+ len = (pd->side_page_num * 2) + 1;
+ if (pd->cnt > len)
+ {
+ for (i = 1; i <= pd->side_page_num; i++)
+ {
+ pi = eina_list_nth(pd->page_infos, i);
+ if (i == 1)
+ {
+ efl_pack_unpack(pi->obj, pi->content);
+ efl_canvas_object_clip_set(pi->content, pd->viewport.backclip);
+ }
+ else
+ {
+ pi->prev->content = pi->content;
+ pi->prev->content_num = pi->content_num;
+ efl_pack_unpack(pi->obj, pi->content);
+ efl_pack(pi->prev->obj, pi->content);
+ }
+ if (i == pd->side_page_num)
+ {
+ pi->content = subobj;
+ pi->content_num = id;
+ efl_pack(pi->obj, pi->content);
+ efl_canvas_object_clip_set(pi->content, pd->viewport.foreclip);
+ }
+ }
+ }
+ else
+ {
+ pi_id = (id + pd->side_page_num) % len + 1;
+ pi = eina_list_nth(pd->page_infos, pi_id);
+
+ pi->content = subobj;
+ pi->content_num = id;
+ efl_pack(pi->obj, pi->content);
+ efl_canvas_object_clip_set(pi->content, pd->viewport.foreclip);
+ }
+
+ return EINA_TRUE;
+}
+
+EOLIAN static Efl_Gfx *
+_efl_ui_pager_efl_pack_linear_pack_content_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *pd,
+ int index)
+{
+ return eina_list_nth(pd->content_list, index);
+}
+
+EOLIAN static int
+_efl_ui_pager_efl_pack_linear_pack_index_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *pd,
+ const Efl_Gfx *subobj)
+{
+ return eina_list_data_idx(pd->content_list, (void *)subobj);
+}
+
+#if CURRENT_PAGE_SET
+static Eina_Bool
+_change_animator(void *data, double pos)
+{
+ Eo *obj = data;
+ EFL_UI_PAGER_DATA_GET(obj, sd);
+ double p, d;
+
+ p = ecore_animator_pos_map(pos, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
+
+ d = sd->change.src + sd->change.delta * pos;
+
+ sd->page = d;
+ sd->ratio = d - (int)d;
+
+ if (pos == 1.0)
+ sd->page = sd->change.dst;
+
+ _efl_ui_pager_update(obj);
+
+ if (pos < 1.0) return ECORE_CALLBACK_RENEW;
+
+ sd->change.jump = EINA_FALSE;
+ sd->change.animator = NULL;
+
+ return ECORE_CALLBACK_CANCEL;
+}
+#endif
+
+EOLIAN static void
+_efl_ui_pager_current_page_set(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd EINA_UNUSED,
+ int index EINA_UNUSED)
+{
+#if CURRENT_PAGE_SET
+ double time;
+
+ sd->change.src = sd->page + sd->ratio;
+ sd->change.dst = index;
+
+ sd->change.jump = jump;
+ if (sd->ratio != 0) sd->change.jump = EINA_FALSE;
+
+ sd->change.delta = index - sd->change.src;
+ if (sd->change.jump) sd->change.delta = 1.0;
+ if (sd->change.delta == 0) return;
+
+ time = sd->change.delta;
+ if (sd->change.delta < 0) time *= (-1);
+ time /= sd->cnt;
+
+ ecore_animator_del(sd->change.animator);
+ sd->change.animator = ecore_animator_timeline_add(time, _change_animator, obj);
+#endif
+}
+
+EOLIAN static int
+_efl_ui_pager_current_page_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd)
+{
+ return sd->page;
+}
+
+EOLIAN static Efl_Page_Transition *
+_efl_ui_pager_transition_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd)
+{
+ return sd->transition;
+}
+
+EOLIAN static void
+_efl_ui_pager_transition_set(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ Efl_Page_Transition *transition)
+{
+ efl_page_transition_bind(transition, obj);
+ sd->transition = transition;
+}
+
+EOLIAN static Efl_Ui_Dir
+_efl_ui_pager_efl_ui_direction_direction_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd)
+{
+ return sd->dir;
+}
+
+EOLIAN static void
+_efl_ui_pager_efl_ui_direction_direction_set(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ Efl_Ui_Dir dir)
+{
+ if (dir != EFL_UI_DIR_VERTICAL &&
+ dir != EFL_UI_DIR_HORIZONTAL)
+ return;
+
+ sd->dir = dir;
+}
+
+EOLIAN static void
+_efl_ui_pager_page_size_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ int *width,
+ int *height)
+{
+ if (width) *width = sd->page_spec.w;
+ if (height) *height = sd->page_spec.h;
+}
+
+EOLIAN static void
+_efl_ui_pager_page_size_set(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ int width,
+ int height)
+{
+ sd->page_spec.w = width;
+ sd->page_spec.h = height;
+
+ if (sd->page_info_job) ecore_job_del(sd->page_info_job);
+ sd->page_info_job = ecore_job_add(_page_info_job, obj);
+}
+
+EOLIAN static int
+_efl_ui_pager_padding_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd)
+{
+ return sd->page_spec.padding;
+}
+
+EOLIAN static void
+_efl_ui_pager_padding_set(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ int padding)
+{
+ sd->page_spec.padding = padding;
+
+ if (sd->page_info_job) ecore_job_del(sd->page_info_job);
+ sd->page_info_job = ecore_job_add(_page_info_job, obj);
+}
+
+EOLIAN static void
+_efl_ui_pager_scroll_block_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ Eina_Bool *prev,
+ Eina_Bool *next)
+{
+ *prev = sd->prev_block;
+ *next = sd->next_block;
+}
+
+EOLIAN static void
+_efl_ui_pager_scroll_block_set(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ Eina_Bool prev,
+ Eina_Bool next)
+{
+ sd->prev_block = prev;
+ sd->next_block = next;
+}
+
+EOLIAN static void
+_efl_ui_pager_loop_set(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd,
+ Eina_Bool loop_enabled)
+{
+ sd->loop = loop_enabled;
+}
+
+EOLIAN static Eina_Bool
+_efl_ui_pager_loop_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd)
+{
+ return sd->loop;
+}
+
+EOLIAN static int
+_efl_ui_pager_side_page_num_get(Eo *obj EINA_UNUSED,
+ Efl_Ui_Pager_Data *sd)
+{
+ return sd->side_page_num;
+}
+
+EOLIAN static void
+_efl_ui_pager_side_page_num_set(Eo *obj,
+ Efl_Ui_Pager_Data *sd,
+ int side_page_num)
+{
+ if (sd->side_page_num == side_page_num) return;
+
+ int delta = side_page_num - sd->side_page_num;
+ sd->side_page_num = side_page_num;
+ sd->page_info_num = (side_page_num * 2) + 3;
+
+ _page_info_change(obj, delta);
+
+ if (sd->page_info_job) ecore_job_del(sd->page_info_job);
+ sd->page_info_job = ecore_job_add(_page_info_job, obj);
+}
+
+
+
+#define EFL_UI_PAGER_EXTRA_OPS \
+ EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_pager)
+
+#include "efl_ui_pager.eo.c"
diff --git a/src/lib/elementary/efl_ui_pager.eo b/src/lib/elementary/efl_ui_pager.eo
new file mode 100644
index 0000000000..088e89c247
--- /dev/null
+++ b/src/lib/elementary/efl_ui_pager.eo
@@ -0,0 +1,60 @@
+class Efl.Ui.Pager (Elm.Widget, Efl.Pack.Linear, Efl.Ui.Direction)
+{
+ [[Efl ui pager class]]
+ event_prefix: efl_ui_pager;
+ eo_prefix: efl_ui_pager;
+ methods {
+ @property transition {
+ [[Page transition effect]]
+ values {
+ transition: Efl.Page.Transition; [[transition effect]]
+ }
+ }
+ @property current_page {
+ [[Set the currently selected page]]
+ values {
+ index: int;
+ }
+ }
+ @property scroll_block {
+ values {
+ prev: bool;
+ next: bool;
+ }
+ }
+ @property loop {
+ values {
+ loop_enabled: bool;
+ }
+ }
+ @property page_size {
+ values {
+ width: int;
+ height: int;
+ }
+ }
+ @property padding {
+ values {
+ padding: int;
+ }
+ }
+ @property side_page_num {
+ values {
+ side_page_num: int;
+ }
+ }
+ }
+ implements {
+ Efl.Object.constructor;
+ Efl.Gfx.size { set; }
+ Efl.Gfx.position { set; }
+ Efl.Container.content_count;
+ Efl.Pack.Linear.pack_end;
+ Efl.Pack.Linear.pack_content_get;
+ Efl.Pack.Linear.pack_index_get;
+ Efl.Ui.Direction.direction { set; get; }
+ }
+ events {
+ updated; [[Called when pager is scrolled]]
+ }
+}
diff --git a/src/lib/elementary/efl_ui_widget_pager.h b/src/lib/elementary/efl_ui_widget_pager.h
new file mode 100644
index 0000000000..d177046075
--- /dev/null
+++ b/src/lib/elementary/efl_ui_widget_pager.h
@@ -0,0 +1,92 @@
+#ifndef EFL_UI_WIDGET_PAGER_H
+#define EFL_UI_WIDGET_PAGER_H
+
+
+#include <Elementary.h>
+
+#include "efl_page_transition.h"
+
+typedef struct _Page_Info
+{
+ Evas_Map *map;
+ int id;
+ int pos;
+ int content_num;
+ Eo *obj;
+ Eo *content;
+ Evas_Coord x, y, w, h;
+ Evas_Coord tx, ty, tw, th;
+ struct _Page_Info *prev, *next;
+
+ Eina_Bool visible;
+ Eina_Bool vis_page;
+
+} Page_Info;
+
+typedef struct _Efl_Ui_Pager_Data
+{
+ Eo *obj;
+ Eina_List *page_infos;
+ Eina_List *content_list;
+
+ Evas_Object *event;
+ Ecore_Animator *animator;
+ Ecore_Job *job;
+ Ecore_Job *page_info_job;
+
+ Evas_Coord x, y, w, h;
+ Evas_Coord mouse_x, mouse_y;
+ Evas_Coord mouse_down_x, mouse_down_y;
+
+ struct {
+ Evas_Object *foreclip;
+ Evas_Object *backclip;
+
+ Evas_Coord x, y, w, h;
+ } viewport;
+
+ struct {
+ int w, h;
+ int padding;
+ } page_spec;
+
+ Page_Info *head, *tail;
+
+ struct {
+ Evas_Coord x, y;
+ int page;
+ double ratio;
+ Eina_Bool enabled;
+ } mouse_down;
+
+ int cnt;
+ int page;
+ int current_page;
+ int side_page_num;
+ int page_info_num;
+ double ratio;
+ double move;
+
+ struct {
+ Ecore_Animator *animator;
+ double src;
+ double dst;
+ double delta;
+ Eina_Bool jump;
+ } change;
+
+ Efl_Ui_Dir dir;
+ Efl_Page_Transition *transition;
+
+ Eina_Bool move_started : 1;
+ Eina_Bool map_enabled : 1;
+ Eina_Bool prev_block : 1;
+ Eina_Bool next_block: 1;
+ Eina_Bool loop : 1;
+
+} Efl_Ui_Pager_Data;
+
+#define EFL_UI_PAGER_DATA_GET(o, sd) \
+ Efl_Ui_Pager_Data *sd = efl_data_scope_get(o, EFL_UI_PAGER_CLASS)
+
+#endif