diff options
author | Jaeun Choi <jaeun12.choi@samsung.com> | 2017-10-26 16:41:38 +0900 |
---|---|---|
committer | Jaeun Choi <jaeun12.choi@samsung.com> | 2018-04-23 16:28:41 +0900 |
commit | 0c8b01f47501cf0ecd2b41d76ef907aa24bcd6e7 (patch) | |
tree | 082d3d9bcd94cfae6bbbb88976dcca98c61f1dc5 | |
parent | 9cbba2d0b452934b485706de5f8956c984556e29 (diff) | |
download | efl-0c8b01f47501cf0ecd2b41d76ef907aa24bcd6e7.tar.gz |
efl_ui_pager: add a new class
-rw-r--r-- | src/Makefile_Elementary.am | 9 | ||||
-rw-r--r-- | src/lib/elementary/Elementary.h | 3 | ||||
-rw-r--r-- | src/lib/elementary/efl_page_transition.c | 47 | ||||
-rw-r--r-- | src/lib/elementary/efl_page_transition.eo | 24 | ||||
-rw-r--r-- | src/lib/elementary/efl_page_transition.h | 13 | ||||
-rw-r--r-- | src/lib/elementary/efl_page_transition_scroll.c | 315 | ||||
-rw-r--r-- | src/lib/elementary/efl_page_transition_scroll.eo | 10 | ||||
-rw-r--r-- | src/lib/elementary/efl_page_transition_scroll.h | 12 | ||||
-rw-r--r-- | src/lib/elementary/efl_ui_pager.c | 718 | ||||
-rw-r--r-- | src/lib/elementary/efl_ui_pager.eo | 60 | ||||
-rw-r--r-- | src/lib/elementary/efl_ui_widget_pager.h | 92 |
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 |