summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaeun Choi <jaeun12.choi@samsung.com>2018-04-23 18:43:11 +0900
committerJaeun Choi <jaeun12.choi@samsung.com>2018-04-23 20:33:04 +0900
commite74ebca670b3ebe4b2dc86cb7fb7a2100b86325c (patch)
tree57dc9156904303016e0ea8824e672cdbf0303f79
parentea84f4450cf63d94589681ac67b1b6463e143723 (diff)
efl_ui_pager: Add Efl.Ui.Pager class and related classes
Efl.Ui.Pager is a widget which contains many pages in a linear fashion and allows users to scroll through them. Users can attach Efl.Page.Transition and Efl.Page.Indicator to a pager.
-rw-r--r--data/elementary/themes/Makefile.am3
-rw-r--r--data/elementary/themes/default.edc1
-rw-r--r--data/elementary/themes/edc/efl/pager.edc66
-rw-r--r--src/Makefile_Elementary.am17
-rw-r--r--src/lib/elementary/Elementary.h11
-rw-r--r--src/lib/elementary/efl_page_indicator.c58
-rw-r--r--src/lib/elementary/efl_page_indicator.eo18
-rw-r--r--src/lib/elementary/efl_page_indicator.h23
-rw-r--r--src/lib/elementary/efl_page_indicator_icon.c152
-rw-r--r--src/lib/elementary/efl_page_indicator_icon.eo13
-rw-r--r--src/lib/elementary/efl_page_indicator_icon.h19
-rw-r--r--src/lib/elementary/efl_page_transition.c107
-rw-r--r--src/lib/elementary/efl_page_transition.eo17
-rw-r--r--src/lib/elementary/efl_page_transition.h27
-rw-r--r--src/lib/elementary/efl_page_transition_scroll.c606
-rw-r--r--src/lib/elementary/efl_page_transition_scroll.eo22
-rw-r--r--src/lib/elementary/efl_page_transition_scroll.h93
-rw-r--r--src/lib/elementary/efl_ui_pager.c811
-rw-r--r--src/lib/elementary/efl_ui_pager.eo101
-rw-r--r--src/lib/elementary/efl_ui_widget_pager.h69
-rw-r--r--src/lib/elementary/elm_priv.h10
21 files changed, 2242 insertions, 2 deletions
diff --git a/data/elementary/themes/Makefile.am b/data/elementary/themes/Makefile.am
index fc285c6..8ae0844 100644
--- a/data/elementary/themes/Makefile.am
+++ b/data/elementary/themes/Makefile.am
@@ -1040,7 +1040,8 @@ elementary/themes/edc/efl/textpath.edc \
1040elementary/themes/edc/efl/tooltip.edc \ 1040elementary/themes/edc/efl/tooltip.edc \
1041elementary/themes/edc/efl/video.edc \ 1041elementary/themes/edc/efl/video.edc \
1042elementary/themes/edc/efl/list.edc \ 1042elementary/themes/edc/efl/list.edc \
1043elementary/themes/edc/efl/win.edc 1043elementary/themes/edc/efl/win.edc \
1044elementary/themes/edc/efl/pager.edc
1044 1045
1045elementary_fdo_actions_128_files = \ 1046elementary_fdo_actions_128_files = \
1046 elementary/themes/fdo/actions/128/address-book-new.png \ 1047 elementary/themes/fdo/actions/128/address-book-new.png \
diff --git a/data/elementary/themes/default.edc b/data/elementary/themes/default.edc
index d7c823e..00f8973 100644
--- a/data/elementary/themes/default.edc
+++ b/data/elementary/themes/default.edc
@@ -196,4 +196,5 @@ collections {
196#include "edc/efl/textpath.edc" 196#include "edc/efl/textpath.edc"
197#include "edc/efl/win.edc" 197#include "edc/efl/win.edc"
198#include "edc/efl/uiclock.edc" 198#include "edc/efl/uiclock.edc"
199#include "edc/efl/pager.edc"
199} 200}
diff --git a/data/elementary/themes/edc/efl/pager.edc b/data/elementary/themes/edc/efl/pager.edc
new file mode 100644
index 0000000..397af0b
--- /dev/null
+++ b/data/elementary/themes/edc/efl/pager.edc
@@ -0,0 +1,66 @@
1group { "efl/pager";
2 parts {
3 spacer { "base";
4 scale;
5 desc { "default";
6 }
7 }
8 swallow { "elm.swallow.background";
9 scale;
10 desc { "default";
11 }
12 }
13 swallow { "page_root";
14 scale;
15 desc { "default";
16 rel1.relative: 0.0 1.0;
17 rel1.to: "indicator";
18 }
19 }
20 swallow { "indicator";
21 scale;
22 desc { "default";
23 rel2.relative: 1.0 0.0;
24 align: 0.5 0.0;
25 min: 0 50;
26 }
27 }
28 swallow { "event";
29 scale;
30 repeat_events: 1;
31 desc { "default";
32 }
33 }
34 }
35}
36
37group { "efl/pager/indicator";
38 images {
39 image: "ring_white_middle.png" COMP;
40 }
41 parts {
42 spacer { "base";
43 scale;
44 desc { "default";
45 }
46 }
47 image { "icon";
48 scale;
49 desc { "default";
50 image.normal: "ring_white_middle.png";
51 color: 0 0 0 255;
52 min: 6 6;
53 }
54 desc { "selected";
55 inherit: "default";
56 color: 255 0 0 255;
57 }
58 }
59 }
60 script {
61 public message(Msg_Type:type, id, ...) {
62 set_tween_state(PART:"icon", getfarg(2),
63 "default", 0.0, "selected", 0.0);
64 }
65 }
66}
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index 35f9d0e..d7d3e1d 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -105,6 +105,11 @@ elm_public_eolian_files = \
105 lib/elementary/efl_ui_dnd.eo \ 105 lib/elementary/efl_ui_dnd.eo \
106 lib/elementary/efl_ui_dnd_container.eo \ 106 lib/elementary/efl_ui_dnd_container.eo \
107 lib/elementary/efl_ui_focus_manager_window_root.eo \ 107 lib/elementary/efl_ui_focus_manager_window_root.eo \
108 lib/elementary/efl_ui_pager.eo \
109 lib/elementary/efl_page_transition.eo \
110 lib/elementary/efl_page_transition_scroll.eo \
111 lib/elementary/efl_page_indicator.eo \
112 lib/elementary/efl_page_indicator_icon.eo \
108 $(NULL) 113 $(NULL)
109 114
110# More public files -- FIXME 115# More public files -- FIXME
@@ -400,7 +405,12 @@ includesunstable_HEADERS = \
400 lib/elementary/efl_ui_widget_scroll_manager.h \ 405 lib/elementary/efl_ui_widget_scroll_manager.h \
401 lib/elementary/efl_ui_widget_pan.h \ 406 lib/elementary/efl_ui_widget_pan.h \
402 lib/elementary/efl_ui_nstate_private.h \ 407 lib/elementary/efl_ui_nstate_private.h \
403 lib/elementary/Efl_Ui.h 408 lib/elementary/Efl_Ui.h \
409 lib/elementary/efl_ui_widget_pager.h \
410 lib/elementary/efl_page_transition.h \
411 lib/elementary/efl_page_transition_scroll.h \
412 lib/elementary/efl_page_indicator.h \
413 lib/elementary/efl_page_indicator_icon.h
404includesunstabledir = $(includedir)/elementary-@VMAJ@ 414includesunstabledir = $(includedir)/elementary-@VMAJ@
405 415
406nodist_includesunstable_HEADERS = \ 416nodist_includesunstable_HEADERS = \
@@ -805,6 +815,11 @@ lib_elementary_libelementary_la_SOURCES = \
805 lib/elementary/efl_ui_dnd.c \ 815 lib/elementary/efl_ui_dnd.c \
806 static_libs/buildsystem/buildsystem.h \ 816 static_libs/buildsystem/buildsystem.h \
807 static_libs/buildsystem/buildsystem_autotools.c \ 817 static_libs/buildsystem/buildsystem_autotools.c \
818 lib/elementary/efl_ui_pager.c \
819 lib/elementary/efl_page_transition.c \
820 lib/elementary/efl_page_transition_scroll.c \
821 lib/elementary/efl_page_indicator.c \
822 lib/elementary/efl_page_indicator_icon.c \
808 $(NULL) 823 $(NULL)
809 824
810 825
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 76b9b0a..8fe0230 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -341,6 +341,17 @@ typedef Eo Efl_Ui_Focus_Manager;
341# include <efl_ui_navigation_bar_part_back_button.eo.h> 341# include <efl_ui_navigation_bar_part_back_button.eo.h>
342# include <efl_ui_navigation_layout.eo.h> 342# include <efl_ui_navigation_layout.eo.h>
343# include <efl_ui_stack.eo.h> 343# include <efl_ui_stack.eo.h>
344
345# ifndef _EFL_UI_PAGER_EO_CLASS_TYPE
346# define _EFL_UI_PAGER_EO_CLASS_TYPE
347typedef Eo Efl_Ui_Pager;
348# endif
349
350# include <efl_page_transition.eo.h>
351# include <efl_page_transition_scroll.eo.h>
352# include <efl_page_indicator.eo.h>
353# include <efl_page_indicator_icon.eo.h>
354# include <efl_ui_pager.eo.h>
344#endif 355#endif
345 356
346/* include deprecated calls last of all */ 357/* include deprecated calls last of all */
diff --git a/src/lib/elementary/efl_page_indicator.c b/src/lib/elementary/efl_page_indicator.c
new file mode 100644
index 0000000..86ea851
--- /dev/null
+++ b/src/lib/elementary/efl_page_indicator.c
@@ -0,0 +1,58 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6#include "elm_priv.h"
7
8#include "efl_page_indicator.h"
9#include "efl_ui_widget_pager.h"
10
11#define MY_CLASS EFL_PAGE_INDICATOR_CLASS
12
13
14
15EOLIAN static void
16_efl_page_indicator_update(Eo *obj EINA_UNUSED,
17 Efl_Page_Indicator_Data *pd EINA_UNUSED,
18 double pos EINA_UNUSED)
19{
20
21}
22
23EOLIAN static void
24_efl_page_indicator_pack(Eo *obj EINA_UNUSED,
25 Efl_Page_Indicator_Data *pd,
26 int index EINA_UNUSED)
27{
28 pd->cnt++;
29}
30
31EOLIAN static void
32_efl_page_indicator_bind(Eo *obj EINA_UNUSED,
33 Efl_Page_Indicator_Data *pd,
34 Eo *pager,
35 Efl_Canvas_Group *idbox)
36{
37 if (pd->pager.obj == pager) return;
38
39 pd->pager.obj = pager;
40 pd->idbox = idbox;
41
42 if (pager)
43 pd->cnt = efl_content_count(pd->pager.obj);
44}
45
46
47EOAPI EFL_VOID_FUNC_BODYV(efl_page_indicator_update,
48 EFL_FUNC_CALL(pos), double pos)
49EOAPI EFL_VOID_FUNC_BODYV(efl_page_indicator_pack,
50 EFL_FUNC_CALL(index), int index)
51
52#define EFL_PAGE_INDICATOR_EXTRA_OPS \
53 EFL_OBJECT_OP_FUNC(efl_page_indicator_update, \
54 _efl_page_indicator_update), \
55 EFL_OBJECT_OP_FUNC(efl_page_indicator_pack, \
56 _efl_page_indicator_pack)
57
58#include "efl_page_indicator.eo.c"
diff --git a/src/lib/elementary/efl_page_indicator.eo b/src/lib/elementary/efl_page_indicator.eo
new file mode 100644
index 0000000..110c4be
--- /dev/null
+++ b/src/lib/elementary/efl_page_indicator.eo
@@ -0,0 +1,18 @@
1class Efl.Page.Indicator (Efl.Object)
2{
3 [[Page indicator
4
5 Page indicator is used with @Efl.Ui.Pager.
6 It is located on the top layer of pager widget and helps users to know
7 the number of pages and the current page's index without scrolling.
8 ]]
9 methods {
10 bind {
11 [[set object]]
12 params {
13 @in pager: Efl.Ui.Pager; [[pager object]]
14 @in group: Efl.Canvas.Group; [[a dummy object for layer adjustment]]
15 }
16 }
17 }
18}
diff --git a/src/lib/elementary/efl_page_indicator.h b/src/lib/elementary/efl_page_indicator.h
new file mode 100644
index 0000000..42dc886
--- /dev/null
+++ b/src/lib/elementary/efl_page_indicator.h
@@ -0,0 +1,23 @@
1#ifndef EFL_PAGE_INDICATOR_H
2#define EFL_PAGE_INDICATOR_H
3
4typedef struct _Efl_Page_Indicator_Data Efl_Page_Indicator_Data;
5
6struct _Efl_Page_Indicator_Data
7{
8 struct {
9 Efl_Object *obj;
10 Efl_Object *group;
11 Evas_Coord x, y, w, h;
12 } pager;
13
14 Efl_Ui_Box *idbox;
15
16 int cnt;
17};
18
19#define EFL_PAGE_INDICATOR_DATA_GET(o, pd) \
20 Efl_Page_Indicator_Data *pd = \
21 efl_data_scope_get(o, EFL_PAGE_INDICATOR_CLASS)
22
23#endif
diff --git a/src/lib/elementary/efl_page_indicator_icon.c b/src/lib/elementary/efl_page_indicator_icon.c
new file mode 100644
index 0000000..9b9f02c
--- /dev/null
+++ b/src/lib/elementary/efl_page_indicator_icon.c
@@ -0,0 +1,152 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6#include "elm_priv.h"
7
8#include "efl_page_indicator_icon.h"
9#include "efl_page_indicator.h"
10#include "efl_ui_widget_pager.h"
11
12#define MY_CLASS EFL_PAGE_INDICATOR_ICON_CLASS
13
14
15
16EOLIAN static void
17_efl_page_indicator_icon_update(Eo *obj,
18 Efl_Page_Indicator_Icon_Data *pd,
19 double pos)
20{
21 EFL_PAGE_INDICATOR_DATA_GET(obj, spd);
22 Eo *item;
23 int page = efl_ui_pager_current_page_get(spd->pager.obj);
24 double delta = fabs(pos);
25
26 if (pd->curr)
27 {
28 eina_value_set(pd->v, 0.0);
29 efl_layout_signal_message_send(pd->curr, 1, *(pd->v));
30 if (pd->adj) efl_layout_signal_message_send(pd->adj, 1, *(pd->v));
31 }
32
33 item = eina_list_nth(pd->items, page);
34 eina_value_set(pd->v, (1.0 - delta));
35 efl_layout_signal_message_send(item, 1, *(pd->v));
36 pd->curr = item;
37
38 if (pos < 0)
39 item = eina_list_nth(pd->items, (page - 1 + spd->cnt) % spd->cnt);
40 else
41 item = eina_list_nth(pd->items, (page + 1 + spd->cnt) % spd->cnt);
42
43 eina_value_set(pd->v, delta);
44 efl_layout_signal_message_send(item, 1, *(pd->v));
45 pd->adj = item;
46}
47
48EOLIAN static void
49_efl_page_indicator_icon_pack(Eo *obj,
50 Efl_Page_Indicator_Icon_Data *pd,
51 int index)
52{
53 EFL_PAGE_INDICATOR_DATA_GET(obj, spd);
54 Eo *item, *existing;
55
56 efl_page_indicator_pack(efl_super(obj, MY_CLASS), index);
57
58 item = efl_add(EFL_CANVAS_LAYOUT_CLASS, spd->idbox);
59 elm_widget_theme_object_set(spd->idbox, item,
60 "pager", "indicator", "default");
61 efl_gfx_size_hint_align_set(item, 0.5, 0.5);
62 efl_gfx_size_hint_weight_set(item, 0, 0);
63
64 if (index == 0)
65 {
66 pd->items = eina_list_prepend(pd->items, item);
67 efl_pack_begin(spd->idbox, item);
68 }
69 else if (index == (spd->cnt - 1))
70 {
71 pd->items = eina_list_append(pd->items, item);
72 efl_pack_end(spd->idbox, item);
73 }
74 else
75 {
76 existing = eina_list_nth(pd->items, index);
77 pd->items = eina_list_prepend_relative(pd->items, item, existing);
78 efl_pack_before(spd->idbox, item, existing);
79 }
80}
81
82EOLIAN static void
83_efl_page_indicator_icon_efl_page_indicator_bind(Eo *obj,
84 Efl_Page_Indicator_Icon_Data *pd,
85 Eo *pager,
86 Efl_Canvas_Group *idbox)
87{
88 EFL_PAGE_INDICATOR_DATA_GET(obj, spd);
89 Eo *item;
90 int i, page;
91
92 if (spd->pager.obj)
93 {
94 EINA_LIST_FREE(pd->items, item)
95 {
96 efl_del(item);
97 }
98 }
99
100 efl_page_indicator_bind(efl_super(obj, MY_CLASS), pager, idbox);
101
102 if (spd->pager.obj)
103 {
104 efl_ui_direction_set(spd->idbox, EFL_UI_DIR_HORIZONTAL);
105 efl_pack_padding_set(spd->idbox, 15, 15, EINA_TRUE);
106
107 pd->v = eina_value_float_new(0.0);
108
109 if (spd->cnt != 0)
110 {
111 for (i = 0; i < spd->cnt; i++)
112 {
113 item = efl_add(EFL_CANVAS_LAYOUT_CLASS, spd->idbox);
114 pd->items = eina_list_append(pd->items, item);
115
116 elm_widget_theme_object_set(spd->idbox, item,
117 "pager", "indicator", "default");
118 efl_gfx_size_hint_align_set(item, 0.5, 0.5);
119 efl_gfx_size_hint_weight_set(item, 0, 0);
120 efl_pack_end(spd->idbox, item);
121 }
122
123 page = efl_ui_pager_current_page_get(spd->pager.obj);
124 item = eina_list_nth(pd->items, page);
125 eina_value_set(pd->v, 1.0);
126 efl_layout_signal_message_send(item, 1, *(pd->v));
127
128 pd->curr = item;
129 }
130 }
131}
132
133EOLIAN static void
134_efl_page_indicator_icon_efl_object_invalidate(Eo *obj,
135 Efl_Page_Indicator_Icon_Data *pd)
136{
137 Eo *item;
138
139 EINA_LIST_FREE(pd->items, item)
140 efl_del(item);
141
142 efl_invalidate(efl_super(obj, MY_CLASS));
143}
144
145
146#define EFL_PAGE_INDICATOR_ICON_EXTRA_OPS \
147 EFL_OBJECT_OP_FUNC(efl_page_indicator_update, \
148 _efl_page_indicator_icon_update), \
149 EFL_OBJECT_OP_FUNC(efl_page_indicator_pack, \
150 _efl_page_indicator_icon_pack)
151
152#include "efl_page_indicator_icon.eo.c"
diff --git a/src/lib/elementary/efl_page_indicator_icon.eo b/src/lib/elementary/efl_page_indicator_icon.eo
new file mode 100644
index 0000000..d837072
--- /dev/null
+++ b/src/lib/elementary/efl_page_indicator_icon.eo
@@ -0,0 +1,13 @@
1class Efl.Page.Indicator.Icon (Efl.Page.Indicator)
2{
3 [[Icon type page indicator
4
5 This class offers icon type indicator for @Efl.Ui.Pager.
6 This type of page indicator creates the same number of icons as pages and
7 arrange them in a linear order. An icon has two states: default and selected.
8 ]]
9 implements {
10 Efl.Object.invalidate;
11 Efl.Page.Indicator.bind;
12 }
13}
diff --git a/src/lib/elementary/efl_page_indicator_icon.h b/src/lib/elementary/efl_page_indicator_icon.h
new file mode 100644
index 0000000..3c125fd
--- /dev/null
+++ b/src/lib/elementary/efl_page_indicator_icon.h
@@ -0,0 +1,19 @@
1#ifndef EFL_PAGE_INDICATOR_ICON_H
2#define EFL_PAGE_INDICATOR_ICON_H
3
4typedef struct _Efl_Page_Indicator_Icon_Data Efl_Page_Indicator_Icon_Data;
5
6struct _Efl_Page_Indicator_Icon_Data
7{
8 Eo *curr, *adj;
9
10 Eina_List *items;
11 Eina_Value *v;
12};
13
14
15#define EFL_PAGE_INDICATOR_ICON_DATA_GET(o, pd) \
16 Efl_Page_Indicator_Icon_Data *pd = \
17 efl_data_scope_get(o, EFL_PAGE_INDICATOR_ICON_CLASS)
18
19#endif
diff --git a/src/lib/elementary/efl_page_transition.c b/src/lib/elementary/efl_page_transition.c
new file mode 100644
index 0000000..e3e5e21
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition.c
@@ -0,0 +1,107 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6#include "elm_priv.h"
7
8#include "efl_page_transition.h"
9#include "efl_ui_widget_pager.h"
10
11#define MY_CLASS EFL_PAGE_TRANSITION_CLASS
12
13
14EOLIAN static void
15_efl_page_transition_page_size_set(Eo *obj EINA_UNUSED,
16 Efl_Page_Transition_Data *pd,
17 Eina_Size2D sz)
18{
19 pd->page_spec.sz = sz;
20}
21
22EOLIAN static void
23_efl_page_transition_padding_size_set(Eo *obj EINA_UNUSED,
24 Efl_Page_Transition_Data *pd,
25 int padding)
26{
27 pd->page_spec.padding = padding;
28}
29
30EOLIAN static void
31_efl_page_transition_bind(Eo *obj EINA_UNUSED,
32 Efl_Page_Transition_Data *pd,
33 Eo *pager,
34 Efl_Canvas_Group *group)
35{
36 Eina_Rect group_rect;
37
38 if (pd->pager.obj == pager) return;
39
40 pd->pager.obj = pager;
41 pd->pager.group = group;
42
43 if (pager)
44 {
45 group_rect = efl_gfx_geometry_get(group);
46
47 pd->pager.x = group_rect.x;
48 pd->pager.y = group_rect.y;
49 pd->pager.w = group_rect.w;
50 pd->pager.h = group_rect.h;
51
52 pd->page_spec.sz = efl_ui_pager_page_size_get(pager);
53 pd->page_spec.padding = efl_ui_pager_padding_get(pager);
54 pd->loop = efl_ui_pager_loop_mode_get(pager);
55 }
56}
57
58EOLIAN static void
59_efl_page_transition_update(Eo *obj EINA_UNUSED,
60 Efl_Page_Transition_Data *pd EINA_UNUSED,
61 double move EINA_UNUSED)
62{
63
64}
65
66EOLIAN static void
67_efl_page_transition_curr_page_change(Eo *obj EINA_UNUSED,
68 Efl_Page_Transition_Data *pd EINA_UNUSED,
69 int diff EINA_UNUSED)
70{
71
72}
73
74EOLIAN static void
75_efl_page_transition_loop_set(Eo *obj EINA_UNUSED,
76 Efl_Page_Transition_Data *pd,
77 Efl_Ui_Pager_Loop loop)
78{
79 pd->loop = loop;
80}
81
82
83EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_update,
84 EFL_FUNC_CALL(move), double move)
85EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_curr_page_change,
86 EFL_FUNC_CALL(move), double move)
87EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_page_size_set,
88 EFL_FUNC_CALL(sz), Eina_Size2D sz)
89EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_padding_size_set,
90 EFL_FUNC_CALL(padding), int padding)
91EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_loop_set,
92 EFL_FUNC_CALL(loop), Efl_Ui_Pager_Loop loop)
93
94
95#define EFL_PAGE_TRANSITION_EXTRA_OPS \
96 EFL_OBJECT_OP_FUNC(efl_page_transition_update, \
97 _efl_page_transition_update), \
98 EFL_OBJECT_OP_FUNC(efl_page_transition_curr_page_change, \
99 _efl_page_transition_curr_page_change), \
100 EFL_OBJECT_OP_FUNC(efl_page_transition_page_size_set, \
101 _efl_page_transition_page_size_set), \
102 EFL_OBJECT_OP_FUNC(efl_page_transition_padding_size_set, \
103 _efl_page_transition_padding_size_set), \
104 EFL_OBJECT_OP_FUNC(efl_page_transition_loop_set, \
105 _efl_page_transition_loop_set)
106
107#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 0000000..77e359c
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition.eo
@@ -0,0 +1,17 @@
1class Efl.Page.Transition (Efl.Object)
2{
3 [[Page transition for @Efl.Ui.Pager
4
5 A page transition is essential to @Efl.Ui.Pager object and invoked whenever
6 pages are rearranged or scrolled (see @Efl.Ui.Pager).
7 ]]
8 methods {
9 bind {
10 [[set object]]
11 params {
12 @in pager: Efl.Ui.Pager; [[pager object]]
13 @in group: Efl.Canvas.Group; [[a dummy object for layer adjustment]]
14 }
15 }
16 }
17}
diff --git a/src/lib/elementary/efl_page_transition.h b/src/lib/elementary/efl_page_transition.h
new file mode 100644
index 0000000..38d4e6b
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition.h
@@ -0,0 +1,27 @@
1#ifndef EFL_PAGE_TRANSITION_H
2#define EFL_PAGE_TRANSITION_H
3
4
5typedef struct _Efl_Page_Transition_Data Efl_Page_Transition_Data;
6
7struct _Efl_Page_Transition_Data
8{
9 struct {
10 Efl_Object *obj;
11 Efl_Canvas_Group *group;
12 Evas_Coord x, y, w, h;
13 } pager;
14
15 struct {
16 Eina_Size2D sz;
17 Evas_Coord padding;
18 } page_spec;
19
20 Efl_Ui_Pager_Loop loop;
21};
22
23#define EFL_PAGE_TRANSITION_DATA_GET(o, pd) \
24 Efl_Page_Transition_Data *pd = \
25 efl_data_scope_get(o, EFL_PAGE_TRANSITION_CLASS)
26
27#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 0000000..ef8f850
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition_scroll.c
@@ -0,0 +1,606 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include <Elementary.h>
6#include "elm_priv.h"
7
8#include "efl_page_transition_scroll.h"
9#include "efl_page_transition.h"
10#include "efl_ui_widget_pager.h"
11
12#define MY_CLASS EFL_PAGE_TRANSITION_SCROLL_CLASS
13
14
15
16static void
17_page_info_deallocate(Efl_Page_Transition_Scroll_Data *pd)
18{
19 Page_Info *pi;
20
21 EINA_LIST_FREE(pd->page_infos, pi)
22 {
23 if (pi->content)
24 efl_pack_unpack(pi->obj, pi->content);
25
26 efl_del(pi->obj);
27 free(pi);
28 }
29
30 pd->head = NULL;
31 pd->tail = NULL;
32}
33
34static void
35_page_info_allocate(Efl_Page_Transition_Scroll_Data *pd,
36 Efl_Page_Transition_Data *spd)
37{
38 Page_Info *pi, *prev = NULL;
39 int i;
40
41 for (i = 0; i < pd->page_info_num; i++)
42 {
43 pi = calloc(1, sizeof(*pi));
44 if (i == 0) pd->head = pi;
45 else if (i == (pd->page_info_num - 1)) pd->tail = pi;
46 pi->id = i;
47 pi->pos = i - (pd->side_page_num + 1);
48 pi->content_num = -1;
49 pi->content = NULL;
50
51 pi->obj = efl_add(EFL_UI_BOX_CLASS, spd->pager.obj);
52 efl_canvas_group_member_add(spd->pager.group, pi->obj);
53 pd->page_infos = eina_list_append(pd->page_infos, pi);
54
55 if (prev)
56 {
57 pi->prev = prev;
58 prev->next = pi;
59 }
60 prev = pi;
61 }
62
63 pd->head->prev = pd->tail;
64 pd->tail->next = pd->head;
65}
66
67static void
68_content_show(Efl_Page_Transition_Scroll_Data *pd,
69 Efl_Page_Transition_Data *spd)
70{
71 Eina_List *list;
72 Page_Info *pi;
73 int tmp_id;
74 Eo *tmp;
75 int curr_page, cnt;
76
77 curr_page = efl_ui_pager_current_page_get(spd->pager.obj);
78 cnt = efl_content_count(spd->pager.obj);
79
80 // at this point, the number of visible pages might have been changed,
81 // so empty all boxes and refill them with the right contents.
82 // FIXME make logic efficient: don't have to empty all and fill all the time
83 EINA_LIST_FOREACH(pd->page_infos, list, pi)
84 {
85 if (pi->content)
86 {
87 efl_pack_unpack(pi->obj, pi->content);
88 efl_canvas_object_clip_set(pi->content, pd->backclip);
89
90 pi->content_num = -1;
91 pi->content = NULL;
92 pi->visible = EINA_FALSE;
93 }
94 efl_canvas_object_clip_set(pi->obj, pd->backclip);
95 }
96
97 EINA_LIST_FOREACH(pd->page_infos, list, pi)
98 {
99 if (pi->vis_page)
100 {
101 tmp_id = (curr_page + pi->pos + cnt) % cnt;
102
103 if ((spd->loop == EFL_UI_PAGER_LOOP_DISABLED)
104 && ((pi->pos) * (tmp_id - curr_page) < 0)) continue;
105
106 tmp = efl_pack_content_get(spd->pager.obj, tmp_id);
107 if (tmp)
108 {
109 efl_canvas_object_clip_set(pi->obj, pd->foreclip);
110
111 efl_pack(pi->obj, tmp);
112 efl_canvas_object_clip_set(tmp, pd->foreclip);
113
114 pi->content_num = tmp_id;
115 pi->content = tmp;
116 pi->visible = EINA_TRUE;
117 }
118 }
119 }
120}
121
122//FIXME use ecore_job
123static void
124_page_info_geometry_change(Efl_Page_Transition_Scroll_Data *pd,
125 Efl_Page_Transition_Data *spd)
126{
127 Eina_List *list;
128 Page_Info *pi;
129 int content_w;
130
131 content_w = spd->page_spec.sz.w
132 + ((spd->page_spec.sz.w + spd->page_spec.padding) * pd->side_page_num * 2);
133
134 if (content_w < spd->pager.w)
135 {
136 EINA_RECTANGLE_SET(&pd->viewport,
137 spd->pager.x + ((spd->pager.w - content_w) / 2),
138 spd->pager.y,
139 content_w,
140 spd->pager.h);
141 }
142 else
143 {
144 EINA_RECTANGLE_SET(&pd->viewport,
145 spd->pager.x,
146 spd->pager.y,
147 spd->pager.w,
148 spd->pager.h);
149 }
150
151 efl_gfx_geometry_set(pd->foreclip, (Eina_Rect) pd->viewport);
152
153 // this loop resets the geometry of each page based on the geometry of
154 // the pager object, the page size, and the padding size.
155 EINA_LIST_FOREACH(pd->page_infos, list, pi)
156 {
157 EINA_RECTANGLE_SET(&pi->geometry,
158 spd->pager.x + (spd->pager.w / 2)
159 + pi->pos * (spd->page_spec.sz.w + spd->page_spec.padding)
160 - (spd->page_spec.sz.w / 2),
161 spd->pager.y + (spd->pager.h / 2) - (spd->page_spec.sz.h / 2),
162 spd->page_spec.sz.w,
163 spd->page_spec.sz.h);
164
165 if (eina_rectangles_intersect(&pi->geometry, &pd->viewport) &&
166 ((pi->id != 0) && (pi->id != (pd->page_info_num - 1))))
167 {
168 pi->vis_page = EINA_TRUE;
169 pi->visible = EINA_TRUE;
170 efl_canvas_object_clip_set(pi->obj, pd->foreclip);
171 }
172 else
173 {
174 pi->vis_page = EINA_FALSE;
175 pi->visible = EINA_FALSE;
176 efl_canvas_object_clip_set(pi->obj, pd->backclip);
177 }
178
179 efl_gfx_geometry_set(pi->obj, (Eina_Rect) pi->geometry);
180 }
181
182 if (efl_content_count(spd->pager.obj) > 0) _content_show(pd, spd);
183}
184
185static void
186_resize_cb(void *data, const Efl_Event *ev)
187{
188 Efl_Page_Transition_Scroll *obj = data;
189 EFL_PAGE_TRANSITION_SCROLL_DATA_GET(obj, pd);
190 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
191
192 Eina_Size2D sz;
193
194 Efl_Ui_Pager *pager = ev->object;
195
196 sz = efl_gfx_size_get(pager);
197
198 spd->pager.w = sz.w;
199 spd->pager.h = sz.h;
200
201 _page_info_geometry_change(pd, spd);
202}
203
204static void
205_move_cb(void *data, const Efl_Event *ev)
206{
207 Efl_Page_Transition_Scroll *obj = data;
208 EFL_PAGE_TRANSITION_SCROLL_DATA_GET(obj, pd);
209 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
210
211 Eina_Position2D pos;
212
213 Efl_Ui_Pager *pager = ev->object;
214
215 pos = efl_gfx_position_get(pager);
216
217 spd->pager.x = pos.x;
218 spd->pager.y = pos.y;
219
220 _page_info_geometry_change(pd, spd);
221}
222
223EOLIAN static void
224_efl_page_transition_scroll_efl_page_transition_bind(Eo *obj,
225 Efl_Page_Transition_Scroll_Data *pd,
226 Eo *pager,
227 Efl_Canvas_Group *group)
228{
229 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
230
231 if (spd->pager.obj == pager) return;
232
233 if (spd->pager.obj)
234 {
235 efl_event_callback_del(spd->pager.group, EFL_GFX_EVENT_RESIZE, _resize_cb, obj);
236 efl_event_callback_del(spd->pager.group, EFL_GFX_EVENT_MOVE, _move_cb, obj);
237
238 _page_info_deallocate(pd);
239 efl_del(pd->foreclip);
240 efl_del(pd->backclip);
241 }
242
243 efl_page_transition_bind(efl_super(obj, MY_CLASS), pager, group);
244
245 if (spd->pager.obj)
246 {
247 int cnt, i;
248 Eo *item;
249
250 efl_event_callback_add(spd->pager.group, EFL_GFX_EVENT_RESIZE, _resize_cb, obj);
251 efl_event_callback_add(spd->pager.group, EFL_GFX_EVENT_MOVE, _move_cb, obj);
252
253 pd->foreclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
254 evas_object_evas_get(spd->pager.obj));
255 evas_object_static_clip_set(pd->foreclip, EINA_TRUE);
256
257 pd->backclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
258 evas_object_evas_get(spd->pager.obj));
259 evas_object_static_clip_set(pd->backclip, EINA_TRUE);
260 efl_gfx_visible_set(pd->backclip, EINA_FALSE);
261
262 cnt = efl_content_count(spd->pager.obj);
263 for (i = 0; i < cnt; i++)
264 {
265 item = efl_pack_content_get(spd->pager.obj, i);
266 efl_canvas_object_clip_set(item, pd->backclip);
267 }
268 _page_info_allocate(pd, spd);
269 _page_info_geometry_change(pd, spd);
270 }
271}
272
273EOLIAN static void
274_efl_page_transition_scroll_page_size_set(Eo *obj,
275 Efl_Page_Transition_Scroll_Data *pd,
276 Eina_Size2D sz)
277{
278 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
279
280 efl_page_transition_page_size_set(efl_super(obj, MY_CLASS), sz);
281 _page_info_geometry_change(pd, spd);
282}
283
284EOLIAN static void
285_efl_page_transition_scroll_padding_size_set(Eo *obj,
286 Efl_Page_Transition_Scroll_Data *pd,
287 int padding)
288{
289 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
290
291 efl_page_transition_padding_size_set(efl_super(obj, MY_CLASS), padding);
292 _page_info_geometry_change(pd, spd);
293}
294
295EOLIAN static void
296_efl_page_transition_scroll_update(Eo *obj,
297 Efl_Page_Transition_Scroll_Data *pd,
298 double pos)
299{
300 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
301
302 double t;
303 int tmp_id, curr_page, cnt;
304 Eo *tmp;
305 Eina_List *list;
306 Page_Info *pi, *tpi;
307
308 t = pos;
309 if (t < 0) t *= (-1);
310
311 curr_page = efl_ui_pager_current_page_get(spd->pager.obj);
312 cnt = efl_content_count(spd->pager.obj);
313
314 // while pages are scrolled,
315 // 1. the geometry of each page needs to be changed
316 // 2. if a page gets out of the viewport, it needs to be hidden
317 // 3. if a page gets into the viewport, it needs to be shown
318 EINA_LIST_FOREACH(pd->page_infos, list, pi)
319 {
320 if (pos < 0) // if scrolled right, each page takes next page's position
321 tpi = pi->next;
322 else // else if scrolled left, each page takes prev page's position
323 tpi = pi->prev;
324
325 EINA_RECTANGLE_SET(&pi->temp,
326 tpi->geometry.x * t + pi->geometry.x * (1 - t),
327 tpi->geometry.y,
328 tpi->geometry.w,
329 tpi->geometry.h);
330
331 efl_gfx_geometry_set(pi->obj, (Eina_Rect) pi->temp);
332
333 if (!pi->vis_page && !tpi->vis_page) continue;
334
335 if (!eina_rectangles_intersect(&pi->temp, &pd->viewport))
336 {
337 if (pi->content)
338 {
339 efl_canvas_object_clip_set(pi->obj, pd->backclip);
340
341 efl_pack_unpack(pi->obj, pi->content);
342 efl_canvas_object_clip_set(pi->content, pd->backclip);
343
344 pi->content_num = -1;
345 pi->content = NULL;
346 pi->visible = EINA_FALSE;
347
348 }
349 }
350 else
351 {
352 tmp_id = (curr_page + pi->pos + cnt) % cnt;
353 if (pi->content_num != tmp_id)
354 {
355 if (pi->content) //FIXME if the content num is the same, do nothing
356 {
357 efl_pack_unpack(pi->obj, pi->content);
358 efl_canvas_object_clip_set(pi->content, pd->backclip);
359
360 pi->content_num = -1;
361 pi->content = NULL;
362 }
363
364 if ((spd->loop == EFL_UI_PAGER_LOOP_DISABLED)
365 && ((pi->pos) * (tmp_id - curr_page) < 0)) continue;
366 tmp = efl_pack_content_get(spd->pager.obj, tmp_id);
367
368 if (tmp)
369 {
370 efl_canvas_object_clip_set(pi->obj, pd->foreclip);
371
372 efl_pack(pi->obj, tmp);
373 efl_canvas_object_clip_set(tmp, pd->foreclip);
374
375 pi->content_num = tmp_id;
376 pi->content = tmp;
377 pi->visible = EINA_TRUE;
378 }
379 }
380 }
381 }
382}
383
384EOLIAN static void
385_efl_page_transition_scroll_curr_page_change(Eo *obj EINA_UNUSED,
386 Efl_Page_Transition_Scroll_Data *pd,
387 double pos)
388{
389 Eina_List *list;
390 Page_Info *pi, *target;
391
392 // after the current page is changed, page infos need to be updated
393 // with a new id based on the new geometry of the boxes.
394 EINA_LIST_FOREACH(pd->page_infos, list, pi)
395 {
396 if (EINA_DBL_EQ(pos, 1.0))
397 {
398 pi->id = (pi->id - 1 + pd->page_info_num) % pd->page_info_num;
399 target = pi->prev;
400 }
401 else if (EINA_DBL_EQ(pos, -1.0))
402 {
403 pi->id = (pi->id + 1) % pd->page_info_num;
404 target = pi->next;
405 }
406 pi->pos = pi->id - (pd->side_page_num + 1);
407
408 EINA_RECTANGLE_SET(&pi->temp,
409 target->geometry.x,
410 target->geometry.y,
411 target->geometry.w,
412 target->geometry.h);
413
414 if (eina_rectangles_intersect(&pi->temp, &pd->viewport) &&
415 (pi->id != 0) && (pi->id != (pd->page_info_num - 1)))
416 {
417 pi->vis_page = EINA_TRUE;
418 pi->visible = EINA_TRUE;
419 efl_canvas_object_clip_set(pi->obj, pd->foreclip);
420 }
421 else
422 {
423 pi->vis_page = EINA_FALSE;
424 pi->visible = EINA_FALSE;
425 efl_canvas_object_clip_set(pi->obj, pd->backclip);
426 if (pi->content)
427 {
428 efl_pack_unpack(pi->obj, pi->content);
429 efl_canvas_object_clip_set(pi->content, pd->backclip);
430 }
431 }
432 }
433
434 if (EINA_DBL_EQ(pos, 1.0))
435 {
436 pd->head = pd->head->next;
437 pd->tail = pd->tail->next;
438 }
439 else if (EINA_DBL_EQ(pos, -1.0))
440 {
441 pd->head = pd->head->prev;
442 pd->tail = pd->tail->prev;
443 }
444
445 EINA_LIST_FOREACH(pd->page_infos, list, pi)
446 {
447 EINA_RECTANGLE_SET(&pi->geometry,
448 pi->temp.x,
449 pi->temp.y,
450 pi->temp.w,
451 pi->temp.h);
452 }
453}
454
455EOLIAN static int
456_efl_page_transition_scroll_side_page_num_get(const Eo *obj EINA_UNUSED,
457 Efl_Page_Transition_Scroll_Data *pd)
458{
459 return pd->side_page_num;
460}
461
462static Page_Info *
463_add_item(Efl_Page_Transition_Scroll_Data *pd, Efl_Page_Transition_Data *spd)
464{
465 Page_Info *pi;
466
467 pi = calloc(1, sizeof(*pi));
468 pi->obj = efl_add(EFL_UI_BOX_CLASS, spd->pager.obj);
469 efl_canvas_group_member_add(spd->pager.group, pi->obj);
470 pi->content_num = -1;
471 pi->content = NULL;
472
473 pi->next = pd->head;
474 pd->head->prev = pi;
475 pi->prev = pd->tail;
476 pd->tail->next = pi;
477
478 return pi;
479}
480
481static void
482_remove_item(Page_Info *pi, Efl_Page_Transition_Scroll_Data *pd)
483{
484 efl_canvas_object_clip_set(pi->content, pd->backclip);
485 efl_pack_unpack(pi->obj, pi->content);
486 efl_del(pi->obj);
487 pi->prev->next = pi->next;
488 pi->next->prev = pi->prev;
489 pd->page_infos = eina_list_remove(pd->page_infos, pi);
490 free(pi);
491}
492
493EOLIAN static void
494_efl_page_transition_scroll_side_page_num_set(Eo *obj,
495 Efl_Page_Transition_Scroll_Data *pd,
496 int side_page_num)
497{
498 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
499 Page_Info *pi;
500 int delta, i;
501
502 if (pd->side_page_num == side_page_num) return;
503
504 delta = side_page_num - pd->side_page_num;
505 pd->side_page_num = side_page_num;
506 pd->page_info_num = (side_page_num * 2) + 3;
507
508 if (!spd->pager.obj) return;
509
510 if (delta > 0)
511 {
512 // side_page_num is increased, so add boxes at both ends by the diff
513 for (i = 0; i < delta; i++)
514 {
515 pi = _add_item(pd, spd);
516 pd->page_infos = eina_list_prepend_relative(pd->page_infos, pi, pd->head);
517 pd->head = pi;
518 efl_gfx_stack_below(pi->obj, pi->next->obj);
519
520 pi = _add_item(pd, spd);
521 pd->page_infos = eina_list_append_relative(pd->page_infos, pi, pd->tail);
522 pd->tail = pi;
523 efl_gfx_stack_above(pi->obj, pi->prev->obj);
524 }
525 }
526 else
527 {
528 // side_page_num is decreased, so remove boxes at both ends by the diff
529 for (i = 0; i > delta; i--)
530 {
531 pi = pd->head;
532 pd->head = pi->next;
533 _remove_item(pi, pd);
534
535 pi = pd->tail;
536 pd->tail = pi->prev;
537 _remove_item(pi, pd);
538 }
539 }
540
541 pi = pd->head;
542 for (i = 0; i < pd->page_info_num; i++)
543 {
544 pi->id = i;
545 pi->pos = i - (pd->side_page_num + 1);
546 pi = pi->next;
547 }
548
549 _page_info_geometry_change(pd, spd);
550}
551
552EOLIAN static void
553_efl_page_transition_scroll_loop_set(Eo *obj,
554 Efl_Page_Transition_Scroll_Data *pd,
555 Efl_Ui_Pager_Loop loop)
556{
557 EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
558
559 if (spd->loop == loop) return;
560
561 efl_page_transition_loop_set(efl_super(obj, MY_CLASS), loop);
562
563 _content_show(pd, spd);
564}
565
566EOLIAN static Eo *
567_efl_page_transition_scroll_efl_object_constructor(Eo *obj,
568 Efl_Page_Transition_Scroll_Data *pd)
569{
570 obj = efl_constructor(efl_super(obj, MY_CLASS));
571
572 pd->side_page_num = 1;
573 pd->page_info_num = pd->side_page_num * 2 + 3;
574
575 return obj;
576}
577
578EOLIAN static void
579_efl_page_transition_scroll_efl_object_invalidate(Eo *obj,
580 Efl_Page_Transition_Scroll_Data *pd)
581{
582 Page_Info *pi;
583
584 EINA_LIST_FREE(pd->page_infos, pi)
585 {
586 efl_del(pi->obj);
587 free(pi);
588 }
589
590 efl_invalidate(efl_super(obj, MY_CLASS));
591}
592
593
594#define EFL_PAGE_TRANSITION_SCROLL_EXTRA_OPS \
595 EFL_OBJECT_OP_FUNC(efl_page_transition_update, \
596 _efl_page_transition_scroll_update), \
597 EFL_OBJECT_OP_FUNC(efl_page_transition_curr_page_change, \
598 _efl_page_transition_scroll_curr_page_change), \
599 EFL_OBJECT_OP_FUNC(efl_page_transition_page_size_set, \
600 _efl_page_transition_scroll_page_size_set), \
601 EFL_OBJECT_OP_FUNC(efl_page_transition_padding_size_set, \
602 _efl_page_transition_scroll_padding_size_set), \
603 EFL_OBJECT_OP_FUNC(efl_page_transition_loop_set, \
604 _efl_page_transition_scroll_loop_set)
605
606#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 0000000..b1d6020
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition_scroll.eo
@@ -0,0 +1,22 @@
1class Efl.Page.Transition.Scroll (Efl.Page.Transition)
2{
3 [[Page transition for @Efl.Ui.Pager
4
5 With this type of transition, pages are arranged linearly and move parallel
6 to the screen by scrolling. The current page is displayed at center, and
7 previous and next pages might be displayed optionally.
8 ]]
9 methods {
10 @property side_page_num {
11 [[The number of pages displayed on each side of the current page]]
12 values {
13 side_page_num: int;
14 }
15 }
16 }
17 implements {
18 Efl.Object.constructor;
19 Efl.Object.invalidate;
20 Efl.Page.Transition.bind;
21 }
22}
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 0000000..b4203d7
--- /dev/null
+++ b/src/lib/elementary/efl_page_transition_scroll.h
@@ -0,0 +1,93 @@
1#ifndef EFL_PAGE_TRANSITION_SCROLL_H
2#define EFL_PAGE_TRANSITION_SCROLL_H
3
4//#include "efl_ui_widget_pager.h"
5
6
7/**
8 * This is a description on how scroll transition works.
9 *
10 * Regardless of the number of pages, scroll transition maintains a fixed number
11 * of boxes which can contain pages. The boxes move along with scrolling and
12 * some of them are emptied or filled as they come in or out of screen area.
13 * When pager is scrolled left or right, each box takes the position of its
14 * previous or next box. Since the leftmost and rightmost boxes might move in
15 * reverse direction, they shouldn't be visible. This is why there are dummy
16 * boxes at both ends.
17 *
18 * Here is an example of box arrangement change by scrolling.
19 * The pager has 10 pages, numbered from 1 to 10.
20 * The current page is page5, and side_page_num equals 1.
21 *
22 * head |----- screen area ----| tail
23 * (dummy) | | (dummy)
24 * ---------- ---------- ---------- ---------- ----------
25 * | BOX1 | | BOX2 | | BOX3 | | BOX4 | | BOX5 |
26 * | | | | | | | | | |
27 * | (empty)| | page4 | | page5 | | page6 | | (empty)|
28 * | | | | | | | | | |
29 * | | | | | | | | | |
30 * | | | | | | | | | |
31 * ---------- ---------- ---------- ---------- ----------
32 * | |
33 * |----------------------|
34 *
35 * After scrolling left,
36 * 1. each box takes the position of it's previous box.
37 * 2. head and tail is changed.
38 * 3. The box moved to the end is emptied.
39 * 4. The box moved from the end is filled with content.
40 *
41 * head tail
42 * ---------- ---------- ---------- ---------- ----------
43 * | BOX2 | | BOX3 | | BOX4 | | BOX5 | | BOX1 |
44 * | | | | | | | | | |
45 * | (empty)| | page5 | | page6 | | page7 | | (empty)|
46 * |*emptied| | | | | |*filled | | |
47 * | | | | | | | | | |
48 * | | | | | | | | | |
49 * ---------- ---------- ---------- ---------- ----------
50 *
51 */
52
53
54typedef struct _Page_Info
55{
56 Evas_Map *map;
57 int id;
58 int pos;
59 int content_num;
60 Eo *obj;
61 Eo *content;
62
63 Eina_Rectangle geometry;
64 Eina_Rectangle temp;
65
66 struct _Page_Info *prev, *next;
67
68 Eina_Bool visible;
69 Eina_Bool vis_page;
70
71} Page_Info;
72
73typedef struct _Efl_Page_Transition_Scroll_Data Efl_Page_Transition_Scroll_Data;
74
75struct _Efl_Page_Transition_Scroll_Data
76{
77 Eina_List *page_infos;
78
79 Page_Info *head, *tail;
80
81 int page_info_num;
82 int side_page_num;
83
84 Eo *foreclip;
85 Eo *backclip;
86 Eina_Rectangle viewport;
87};
88
89#define EFL_PAGE_TRANSITION_SCROLL_DATA_GET(o, pd) \
90 Efl_Page_Transition_Scroll_Data *pd = \
91 efl_data_scope_get(o, EFL_PAGE_TRANSITION_SCROLL_CLASS)
92
93#endif
diff --git a/src/lib/elementary/efl_ui_pager.c b/src/lib/elementary/efl_ui_pager.c
new file mode 100644
index 0000000..a5d3211
--- /dev/null
+++ b/src/lib/elementary/efl_ui_pager.c
@@ -0,0 +1,811 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#define EFL_PACK_LAYOUT_PROTECTED
6
7#include <Elementary.h>
8#include "elm_priv.h"
9#include "efl_ui_widget_pager.h"
10#include "efl_page_transition.h"
11
12#define MY_CLASS EFL_UI_PAGER_CLASS
13
14
15static void
16_efl_ui_pager_update(Efl_Ui_Pager_Data *pd)
17{
18 if (pd->cnt == 0) return;
19
20 efl_page_transition_update(pd->transition, pd->curr.pos);
21 if (pd->indicator)
22 efl_page_indicator_update(pd->indicator, pd->curr.pos);
23}
24
25static void
26_job(void *data)
27{
28 Evas_Object *obj = data;
29 EFL_UI_PAGER_DATA_GET(obj, pd);
30
31 int prev_page, page_diff;
32 double prev_pos, pos_diff;
33
34 prev_page = pd->curr.page;
35 prev_pos = pd->curr.pos;
36
37 pd->job = NULL;
38
39 pos_diff = ((double) pd->down.x - (double) pd->mouse_x) / (double) pd->w;
40 pd->curr.pos = pd->down.pos + pos_diff;
41 page_diff = (int) pd->curr.pos;
42
43 //FIXME what if (prev_pos != 0.0)
44 if ((pd->loop == EFL_UI_PAGER_LOOP_DISABLED) &&
45 (((prev_page == 0) && (pd->curr.pos < 0)) ||
46 ((prev_page == (pd->cnt - 1)) && (pd->curr.pos > 0))))
47 {
48 pd->curr.page = prev_page;
49 pd->curr.pos = prev_pos;
50 return;
51 }
52
53 pd->curr.page = (pd->down.page + page_diff + pd->cnt) % pd->cnt;
54 pd->curr.pos -= page_diff;
55
56 //FIXME what if (page_diff >= 2 || page_diff <= -2)
57 if (page_diff != 0)
58 {
59 pd->down.x = pd->mouse_x;
60 pd->down.y = pd->mouse_y;
61 pd->down.page = pd->curr.page;
62 pd->down.pos = pd->curr.pos;
63
64 efl_page_transition_curr_page_change(pd->transition, page_diff);
65 }
66
67 _efl_ui_pager_update(pd);
68
69 return;
70}
71
72static void
73_page_set_animation(void *data, const Efl_Event *event)
74{
75 Efl_Ui_Pager_Data *pd = data;
76 double p = ecore_loop_time_get() - pd->change.start_time;
77 double d, temp_pos;
78 int temp_page;
79
80 if (p >= 1.0) p = 1.0;
81 p = ecore_animator_pos_map(p, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
82
83 d = pd->change.src + pd->change.delta * p;
84 temp_page = d;
85 temp_pos = d - temp_page;
86
87 if ((temp_page < pd->curr.page) && (fabs(pd->curr.page - d) < 1.0))
88 {
89 temp_page += 1;
90 temp_pos -= 1.0;
91 }
92
93 if (pd->curr.page != temp_page)
94 {
95 if (pd->change.delta < 0)
96 efl_page_transition_curr_page_change(pd->transition, -1.0);
97 else
98 efl_page_transition_curr_page_change(pd->transition, 1.0);
99 temp_pos = 0.0;
100 }
101
102 pd->curr.page = temp_page;
103 pd->curr.pos = temp_pos;
104
105 ERR("page %d pos %lf", pd->curr.page, pd->curr.pos);
106
107 _efl_ui_pager_update(pd);
108
109 if (EINA_DBL_EQ(p, 1.0))
110 efl_event_callback_del(event->object, EFL_EVENT_ANIMATOR_TICK,
111 _page_set_animation, pd);
112}
113
114static void
115_mouse_up_animation(void *data, const Efl_Event *event)
116{
117 Efl_Ui_Pager_Data *pd = data;
118 double p = ecore_loop_time_get() - pd->mouse_up_time;
119
120 if (p >= 1.0) p = 1.0;
121 p = ecore_animator_pos_map(p, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
122
123 if (pd->curr.pos < 0.0)
124 {
125 if (pd->curr.pos > -0.5)
126 pd->curr.pos = pd->curr.pos * (1 - p);
127 else
128 pd->curr.pos = (-1) - (-1 - pd->curr.pos) * (1 - p);
129 }
130 else
131 {
132 if (pd->curr.pos < 0.5)
133 pd->curr.pos = pd->curr.pos * (1 - p);
134 else
135 pd->curr.pos = 1 - (1 - pd->curr.pos) * (1 - p);
136 }
137
138 if (EINA_DBL_EQ(pd->curr.pos, 1.0))
139 {
140 efl_page_transition_curr_page_change(pd->transition, 1.0);
141 pd->curr.page = (pd->curr.page + 1 + pd->cnt) % pd->cnt;
142 pd->curr.pos = 0.0;
143 }
144 else if (EINA_DBL_EQ(pd->curr.pos, -1.0))
145 {
146 efl_page_transition_curr_page_change(pd->transition, -1.0);
147 pd->curr.page = (pd->curr.page - 1 + pd->cnt) % pd->cnt;
148 pd->curr.pos = 0.0;
149 }
150
151 _efl_ui_pager_update(pd);
152
153 if (EINA_DBL_EQ(p, 1.0))
154 efl_event_callback_del(event->object, EFL_EVENT_ANIMATOR_TICK,
155 _mouse_up_animation, pd);
156}
157
158static void
159_mouse_down_cb(void *data,
160 const Efl_Event *event)
161{
162 Efl_Input_Pointer *ev = event->info;
163 Eo *obj = data;
164 EFL_UI_PAGER_DATA_GET(obj, pd);
165 Eina_Position2D pos;
166
167 if (efl_input_pointer_button_get(ev) != 1) return;
168 if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
169
170 efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _mouse_up_animation, pd);
171 efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _page_set_animation, pd);
172
173 pd->move_started = EINA_FALSE;
174
175 pos = efl_input_pointer_position_get(ev);
176 pd->mouse_x = pos.x - pd->x;
177 pd->mouse_y = pos.y - pd->y;
178
179 pd->down.enabled = EINA_TRUE;
180 pd->down.x = pd->mouse_x;
181 pd->down.y = pd->mouse_y;
182 pd->down.page = pd->curr.page;
183 pd->down.pos = pd->curr.pos;
184}
185
186static void
187_mouse_move_cb(void *data,
188 const Efl_Event *event)
189{
190 Efl_Input_Pointer *ev = event->info;
191 Eo *obj = data;
192 EFL_UI_PAGER_DATA_GET(obj, pd);
193 Eina_Position2D pos;
194
195 if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
196 if (!pd->down.enabled) return;
197
198 pos = efl_input_pointer_position_get(ev);
199
200 if (pd->prev_block && (pd->mouse_x < (pos.x - pd->x))) return;
201 if (pd->next_block && (pd->mouse_x > (pos.x - pd->x))) return;
202
203 pd->mouse_x = pos.x - pd->x;
204 pd->mouse_y = pos.y - pd->y;
205
206 if (!pd->move_started)
207 {
208 Evas_Coord dx, dy;
209 dx = pd->mouse_x - pd->down.x;
210 dy = pd->mouse_y - pd->down.y;
211
212 if (((dx * dx) + (dy * dy)) <=
213 (_elm_config->finger_size * _elm_config->finger_size / 4))
214 return;
215
216 pd->move_started = EINA_TRUE;
217 }
218
219 ecore_job_del(pd->job);
220 pd->job = ecore_job_add(_job, obj);
221}
222
223static void
224_mouse_up_cb(void *data,
225 const Efl_Event *event)
226{
227 Efl_Input_Pointer *ev = event->info;
228 Eo *obj = data;
229 EFL_UI_PAGER_DATA_GET(obj, pd);
230
231 if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
232 if (!pd->down.enabled) return;
233
234 pd->down.enabled = EINA_FALSE;
235
236 ELM_SAFE_FREE(pd->job, ecore_job_del);
237
238 if (EINA_DBL_EQ(pd->curr.pos, 0.0)) return;
239
240 pd->mouse_up_time = ecore_loop_time_get();
241
242 efl_event_callback_add(obj, EFL_EVENT_ANIMATOR_TICK, _mouse_up_animation, pd);
243}
244
245//FIXME sub_object_parent_add? destruction
246static void
247_event_handler_create(Eo *obj, Efl_Ui_Pager_Data *pd)
248{
249 pd->event = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
250 evas_object_evas_get(obj));
251 evas_object_color_set(pd->event, 0, 0, 0, 0);
252 evas_object_repeat_events_set(pd->event, EINA_TRUE);
253
254 efl_content_set(efl_part(obj, "event"), pd->event);
255
256 efl_event_callback_add(pd->event, EFL_EVENT_POINTER_DOWN,
257 _mouse_down_cb, obj);
258 efl_event_callback_add(pd->event, EFL_EVENT_POINTER_UP,
259 _mouse_up_cb, obj);
260 efl_event_callback_add(pd->event, EFL_EVENT_POINTER_MOVE,
261 _mouse_move_cb, obj);
262}
263
264static void
265_event_handler_del(Eo *obj, Efl_Ui_Pager_Data *pd)
266{
267 efl_content_unset(efl_part(obj, "event"));
268 efl_del(pd->event);
269 pd->event = NULL;
270}
271
272static void
273_resize_cb(void *data, const Efl_Event *ev)
274{
275 Efl_Ui_Pager_Data *pd = data;
276 Eina_Size2D sz;
277
278 sz = efl_gfx_size_get(ev->object);
279
280 pd->w = sz.w;
281 pd->h = sz.h;
282
283 if (pd->fill_width) pd->page_spec.sz.w = pd->w;
284 if (pd->fill_height) pd->page_spec.sz.h = pd->h;
285
286 if (pd->transition)
287 efl_page_transition_page_size_set(pd->transition, pd->page_spec.sz);
288 else
289 {
290 efl_gfx_size_set(pd->foreclip, sz);
291 efl_gfx_size_set(pd->page_box, pd->page_spec.sz);
292 efl_gfx_position_set(pd->page_box,
293 EINA_POSITION2D(pd->x + (pd->w / 2) - (pd->page_spec.sz.w / 2),
294 pd->y + (pd->h / 2) - (pd->page_spec.sz.h / 2)));
295 }
296}
297
298static void
299_move_cb(void *data, const Efl_Event *ev)
300{
301 Efl_Ui_Pager_Data *pd = data;
302 Eina_Position2D pos;
303
304 pos = efl_gfx_position_get(ev->object);
305
306 pd->x = pos.x;
307 pd->y = pos.y;
308
309 if (!pd->transition)
310 {
311 efl_gfx_position_set(pd->foreclip, pos);
312 efl_gfx_position_set(pd->page_box,
313 EINA_POSITION2D(pd->x + (pd->w / 2) - (pd->page_spec.sz.w / 2),
314 pd->y + (pd->h / 2) - (pd->page_spec.sz.h / 2)));
315 }
316}
317
318EOLIAN static Eo *
319_efl_ui_pager_efl_object_constructor(Eo *obj,
320 Efl_Ui_Pager_Data *pd)
321{
322 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
323
324 if (!elm_widget_theme_klass_get(obj))
325 elm_widget_theme_klass_set(obj, "pager");
326
327 obj = efl_constructor(efl_super(obj, MY_CLASS));
328
329 if (!elm_widget_theme_object_set(obj, wd->resize_obj,
330 elm_widget_theme_klass_get(obj),
331 elm_widget_theme_element_get(obj),
332 elm_widget_theme_style_get(obj)))
333 CRI("Failed to set layout!");
334
335 elm_widget_sub_object_parent_add(obj);
336
337 pd->cnt = 0;
338 pd->loop = EFL_UI_PAGER_LOOP_DISABLED;
339
340 pd->curr.page = 0;
341 pd->curr.pos = 0.0;
342
343 pd->transition = NULL;
344 pd->indicator = NULL;
345
346 pd->fill_width = EINA_TRUE;
347 pd->fill_height = EINA_TRUE;
348
349 pd->page_spec.sz.w = -1;
350 pd->page_spec.sz.h = -1;
351
352 elm_widget_can_focus_set(obj, EINA_TRUE);
353
354 pd->page_root = efl_add(EFL_CANVAS_GROUP_CLASS, evas_object_evas_get(obj));
355 efl_content_set(efl_part(obj, "page_root"), pd->page_root);
356
357 efl_event_callback_add(pd->page_root, EFL_GFX_EVENT_RESIZE, _resize_cb, pd);
358 efl_event_callback_add(pd->page_root, EFL_GFX_EVENT_MOVE, _move_cb, pd);
359
360 pd->page_box = efl_add(EFL_UI_BOX_CLASS, obj);
361 efl_canvas_group_member_add(pd->page_root, pd->page_box);
362
363 pd->foreclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
364 evas_object_evas_get(obj));
365 efl_canvas_group_member_add(pd->page_root, pd->foreclip);
366 evas_object_static_clip_set(pd->foreclip, EINA_TRUE);
367 efl_canvas_object_clip_set(pd->page_box, pd->foreclip);
368
369 pd->backclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
370 evas_object_evas_get(obj));
371 efl_canvas_group_member_add(pd->page_root, pd->backclip);
372 evas_object_static_clip_set(pd->backclip, EINA_TRUE);
373 efl_gfx_visible_set(pd->backclip, EINA_FALSE);
374
375 return obj;
376}
377
378EOLIAN static int
379_efl_ui_pager_efl_container_content_count(Eo *obj EINA_UNUSED,
380 Efl_Ui_Pager_Data *pd)
381{
382 return pd->cnt;
383}
384
385EOLIAN static Eina_Bool
386_efl_ui_pager_efl_pack_linear_pack_begin(Eo *obj,
387 Efl_Ui_Pager_Data *pd,
388 Efl_Gfx *subobj)
389{
390 efl_parent_set(subobj, obj);
391 elm_widget_sub_object_add(obj, subobj);
392
393 pd->content_list = eina_list_prepend(pd->content_list, subobj);
394
395 pd->cnt += 1;
396 pd->curr.page += 1;
397
398 if (pd->transition)
399 efl_page_transition_update(pd->transition, pd->curr.pos);
400 else
401 {
402 if (pd->cnt == 1)
403 efl_pack(pd->page_box, subobj);
404 else efl_canvas_object_clip_set(subobj, pd->backclip);
405 }
406
407 if (pd->indicator)
408 {
409 efl_page_indicator_pack(pd->indicator, 0);
410 efl_page_indicator_update(pd->indicator, pd->curr.pos);
411 }
412
413 return EINA_TRUE;
414}
415
416EOLIAN static Eina_Bool
417_efl_ui_pager_efl_pack_linear_pack_end(Eo *obj,
418 Efl_Ui_Pager_Data *pd,
419 Efl_Gfx *subobj)
420{
421 efl_parent_set(subobj, obj);
422 elm_widget_sub_object_add(obj, subobj);
423
424 pd->content_list = eina_list_append(pd->content_list, subobj);
425
426 pd->cnt += 1;
427
428 if (pd->transition)
429 efl_page_transition_update(pd->transition, pd->curr.pos);
430 else
431 {
432 if (pd->cnt == 1)
433 efl_pack(pd->page_box, subobj);
434 else efl_canvas_object_clip_set(subobj, pd->backclip);
435 }
436
437 if (pd->indicator)
438 {
439 efl_page_indicator_pack(pd->indicator, (pd->cnt - 1));
440 efl_page_indicator_update(pd->indicator, pd->curr.pos);
441 }
442
443 return EINA_TRUE;
444}
445
446EOLIAN static Eina_Bool
447_efl_ui_pager_efl_pack_linear_pack_before(Eo *obj,
448 Efl_Ui_Pager_Data *pd,
449 Efl_Gfx *subobj,
450 const Efl_Gfx *existing)
451{
452 int index;
453
454 efl_parent_set(subobj, obj);
455 elm_widget_sub_object_add(obj, subobj);
456
457 index = eina_list_data_idx(pd->content_list, (void *)existing);
458 pd->content_list = eina_list_prepend_relative(pd->content_list, subobj, existing);
459
460 pd->cnt += 1;
461 if (pd->curr.page >= index) pd->curr.page += 1;
462
463 if (pd->transition)
464 efl_page_transition_update(pd->transition, pd->curr.pos);
465 else efl_canvas_object_clip_set(subobj, pd->backclip);
466
467 if (pd->indicator)
468 {
469 efl_page_indicator_pack(pd->indicator, index);
470 efl_page_indicator_update(pd->indicator, pd->curr.pos);
471 }
472
473 return EINA_TRUE;
474}
475
476EOLIAN static Eina_Bool
477_efl_ui_pager_efl_pack_linear_pack_after(Eo *obj,
478 Efl_Ui_Pager_Data *pd,
479 Efl_Gfx *subobj,
480 const Efl_Gfx *existing)
481{
482 int index;
483
484 efl_parent_set(subobj, obj);
485 elm_widget_sub_object_add(obj, subobj);
486
487 index = eina_list_data_idx(pd->content_list, (void *)existing);
488 pd->content_list = eina_list_append_relative(pd->content_list, subobj, existing);
489
490 pd->cnt += 1;
491 if (pd->curr.page > index) pd->curr.page += 1;
492
493 if (pd->transition)
494 efl_page_transition_update(pd->transition, pd->curr.pos);
495 else efl_canvas_object_clip_set(subobj, pd->backclip);
496
497 if (pd->indicator)
498 {
499 efl_page_indicator_pack(pd->indicator, (index + 1));
500 efl_page_indicator_update(pd->indicator, pd->curr.pos);
501 }
502
503 return EINA_TRUE;
504}
505
506EOLIAN static Eina_Bool
507_efl_ui_pager_efl_pack_linear_pack_at(Eo *obj,
508 Efl_Ui_Pager_Data *pd,
509 Efl_Gfx *subobj,
510 int index)
511{
512 Efl_Gfx *existing = NULL;
513
514 efl_parent_set(subobj, obj);
515 elm_widget_sub_object_add(obj, subobj);
516
517 existing = eina_list_nth(pd->content_list, index);
518 pd->content_list = eina_list_prepend_relative(pd->content_list, subobj, existing);
519
520 pd->cnt += 1;
521 if (pd->curr.page >= index) pd->curr.page += 1;
522
523 if (pd->transition)
524 efl_page_transition_update(pd->transition, pd->curr.pos);
525 else efl_canvas_object_clip_set(subobj, pd->backclip);
526
527 if (pd->indicator)
528 {
529 efl_page_indicator_pack(pd->indicator, index);
530 efl_page_indicator_update(pd->indicator, pd->curr.pos);
531 }
532
533 return EINA_TRUE;
534}
535
536EOLIAN static Efl_Gfx *
537_efl_ui_pager_efl_pack_linear_pack_content_get(Eo *obj EINA_UNUSED,
538 Efl_Ui_Pager_Data *pd,
539 int index)
540{
541 return eina_list_nth(pd->content_list, index);
542}
543
544EOLIAN static int
545_efl_ui_pager_efl_pack_linear_pack_index_get(Eo *obj EINA_UNUSED,
546 Efl_Ui_Pager_Data *pd,
547 const Efl_Gfx *subobj)
548{
549 return eina_list_data_idx(pd->content_list, (void *)subobj);
550}
551
552EOLIAN static void
553_efl_ui_pager_current_page_set(Eo *obj,
554 Efl_Ui_Pager_Data *pd,
555 int index)
556{
557 if (index == pd->curr.page) return;
558
559 efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _mouse_up_animation, pd);
560 efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _page_set_animation, pd);
561
562 if (index >= pd->cnt)
563 {
564 ERR("page set fail");
565 return;
566 }
567
568 if (!pd->transition)
569 {
570 Eo *curr;
571
572 curr = eina_list_nth(pd->content_list, pd->curr.page);
573 efl_pack_unpack(pd->page_box, curr);
574 efl_canvas_object_clip_set(curr, pd->backclip);
575
576 pd->curr.page = index;
577 curr = eina_list_nth(pd->content_list, pd->curr.page);
578 efl_pack(pd->page_box, curr);
579
580 if (pd->indicator)
581 efl_page_indicator_update(pd->indicator, pd->curr.pos);
582
583 return;
584 }
585
586 pd->change.src = pd->curr.page + pd->curr.pos;
587 pd->change.delta = index - pd->change.src;
588
589 if (pd->change.delta == 0) return;
590
591 pd->change.start_time = ecore_loop_time_get();
592 efl_event_callback_add(obj, EFL_EVENT_ANIMATOR_TICK, _page_set_animation, pd);
593}
594
595EOLIAN static int
596_efl_ui_pager_current_page_get(const Eo *obj EINA_UNUSED,
597 Efl_Ui_Pager_Data *pd)
598{
599 return pd->curr.page;
600}
601
602EOLIAN static void
603_efl_ui_pager_transition_set(Eo *obj,
604 Efl_Ui_Pager_Data *pd,
605 Efl_Page_Transition *transition)
606{
607 if (pd->transition == transition) return;
608
609 if (pd->transition)
610 efl_page_transition_bind(pd->transition, NULL, NULL);
611 else
612 {
613 Eo *curr;
614
615 curr = eina_list_nth(pd->content_list, pd->curr.page);
616 efl_pack_unpack(pd->page_box, curr);
617 efl_canvas_object_clip_set(pd->page_box, pd->backclip);
618 }
619
620 pd->transition = transition;
621
622 if (pd->transition)
623 {
624 if (!pd->event) _event_handler_create(obj, pd);
625 efl_page_transition_bind(pd->transition, obj, pd->page_root);
626 }
627 else
628 {
629 Eina_List *list;
630 Eo *curr;
631
632 _event_handler_del(obj, pd);
633
634 efl_canvas_object_clip_set(pd->page_box, pd->foreclip);
635
636 EINA_LIST_FOREACH(pd->content_list, list, curr)
637 {
638 efl_canvas_object_clip_set(curr, pd->backclip);
639 }
640
641 curr = eina_list_nth(pd->content_list, pd->curr.page);
642 efl_pack(pd->page_box, curr);
643 }
644}
645
646EOLIAN static void
647_efl_ui_pager_indicator_set(Eo *obj EINA_UNUSED,
648 Efl_Ui_Pager_Data *pd,
649 Efl_Page_Indicator *indicator)
650{
651 if (pd->indicator == indicator) return;
652
653 if (pd->indicator)
654 {
655 efl_page_indicator_bind(pd->indicator, NULL, NULL);
656 pd->indicator = NULL;
657 }
658
659 pd->indicator = indicator;
660
661 if (!pd->indicator)
662 {
663 if (pd->idbox)
664 {
665 efl_del(pd->idbox);
666 pd->idbox = NULL;
667 }
668 return;
669 }
670
671 if (!pd->idbox)
672 {
673 pd->idbox = efl_add(EFL_UI_BOX_CLASS, obj);
674 efl_content_set(efl_part(obj, "indicator"), pd->idbox);
675 }
676
677 efl_page_indicator_bind(pd->indicator, obj, pd->idbox);
678}
679
680EOLIAN Eina_Size2D
681_efl_ui_pager_page_size_get(const Eo *obj EINA_UNUSED,
682 Efl_Ui_Pager_Data *pd)
683{
684 return pd->page_spec.sz;
685}
686
687EOLIAN static void
688_efl_ui_pager_page_size_set(Eo *obj EINA_UNUSED,
689 Efl_Ui_Pager_Data *pd,
690 Eina_Size2D sz)
691{
692 if (sz.w < -1 || sz.h < -1) return;
693
694 if (sz.w == -1)
695 {
696 pd->fill_width = EINA_TRUE;
697 pd->page_spec.sz.w = pd->w;
698 }
699 else
700 {
701 pd->fill_width = EINA_FALSE;
702 pd->page_spec.sz.w = sz.w;
703 }
704 if (sz.h == -1)
705 {
706 pd->fill_height = EINA_TRUE;
707 pd->page_spec.sz.h = pd->h;
708 }
709 else
710 {
711 pd->fill_height = EINA_FALSE;
712 pd->page_spec.sz.h = sz.h;
713 }
714
715 if (pd->transition)
716 efl_page_transition_page_size_set(pd->transition, pd->page_spec.sz);
717 else
718 efl_gfx_size_set(pd->page_box, pd->page_spec.sz);
719}
720
721EOLIAN static int
722_efl_ui_pager_padding_get(const Eo *obj EINA_UNUSED,
723 Efl_Ui_Pager_Data *pd)
724{
725 return pd->page_spec.padding;
726}
727
728EOLIAN static void
729_efl_ui_pager_padding_set(Eo *obj EINA_UNUSED,
730 Efl_Ui_Pager_Data *pd,
731 int padding)
732{
733 pd->page_spec.padding = padding;
734
735 efl_page_transition_padding_size_set(pd->transition, padding);
736}
737
738EOLIAN static void
739_efl_ui_pager_scroll_block_get(const Eo *obj EINA_UNUSED,
740 Efl_Ui_Pager_Data *pd,
741 Eina_Bool *prev,
742 Eina_Bool *next)
743{
744 if (prev) *prev = pd->prev_block;
745 if (next) *next = pd->next_block;
746}
747
748EOLIAN static void
749_efl_ui_pager_scroll_block_set(Eo *obj EINA_UNUSED,
750 Efl_Ui_Pager_Data *pd,
751 Eina_Bool prev,
752 Eina_Bool next)
753{
754 pd->prev_block = prev;
755 pd->next_block = next;
756}
757
758EOLIAN static void
759_efl_ui_pager_loop_mode_set(Eo *obj EINA_UNUSED,
760 Efl_Ui_Pager_Data *pd,
761 Efl_Ui_Pager_Loop loop)
762{
763 pd->loop = loop;
764
765 efl_page_transition_loop_set(pd->transition, loop);
766}
767
768EOLIAN static Efl_Ui_Pager_Loop
769_efl_ui_pager_loop_mode_get(const Eo *obj EINA_UNUSED,
770 Efl_Ui_Pager_Data *pd)
771{
772 return pd->loop;
773}
774
775EOLIAN static Eina_Bool
776_efl_ui_pager_efl_pack_pack_clear(Eo *obj EINA_UNUSED,
777 Efl_Ui_Pager_Data *pd EINA_UNUSED)
778{
779 ERR("Soon to be implemented");
780 return EINA_FALSE;
781}
782
783EOLIAN static Eina_Bool
784_efl_ui_pager_efl_pack_unpack_all(Eo *obj EINA_UNUSED,
785 Efl_Ui_Pager_Data *pd EINA_UNUSED)
786{
787 ERR("Soon to be implemented");
788 return EINA_FALSE;
789}
790
791EOLIAN static Eina_Bool
792_efl_ui_pager_efl_pack_unpack(Eo *obj EINA_UNUSED,
793 Efl_Ui_Pager_Data *pd EINA_UNUSED,
794 Efl_Gfx *subobj EINA_UNUSED)
795{
796 ERR("Soon to be implemented");
797 return EINA_FALSE;
798}
799
800EOLIAN static Efl_Gfx *
801_efl_ui_pager_efl_pack_linear_pack_unpack_at(Eo *obj EINA_UNUSED,
802 Efl_Ui_Pager_Data *pd EINA_UNUSED,
803 int index EINA_UNUSED)
804{
805 ERR("Soon to be implemented");
806 return NULL;
807}
808
809
810
811#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 0000000..75d050d
--- /dev/null
+++ b/src/lib/elementary/efl_ui_pager.eo
@@ -0,0 +1,101 @@
1enum Efl.Ui.Pager.Loop
2{
3 [[Efl ui pager loop mode]]
4 disabled,
5 enabled
6}
7
8class Efl.Ui.Pager (Efl.Ui.Layout, Efl.Pack.Linear)
9{
10 [[Pager widget
11
12 A pager contains many pages in a linear fashion and allows users to scroll
13 through pages. Each page is numbered according to linear order and
14 one of the pages is marked as 'current page' and displayed in the middle.
15 The way each page is displayed is defined by @Efl.Page.Transition object,
16 allowing users to adopt different types of transition.
17 The most common use case of this widget is the home screen of mobile devices.
18 ]]
19 methods {
20 @property transition {
21 [[Page transition effect
22
23 Page transition is in charge of displaying pages in a specific way and
24 invoked every time page layout needs to be updated.
25 ]]
26 set {
27 [[Set a page transition effect]]
28 }
29 values {
30 transition: Efl.Page.Transition @nullable; [[transition effect]]
31 }
32 }
33 @property indicator {
34 [[Page indicator
35
36 Page indicator, located on the top layer of pager widget, helps users
37 to know the number of pages and the current page's index without scrolling.
38 ]]
39 set {
40 [[Set a page indicator]]
41 }
42 values {
43 indicator: Efl.Page.Indicator @nullable; [[indicator class]]
44 }
45 }
46 @property current_page {
47 [[One page is selected as the current page and mainly displayed.]]
48 set {
49 [[Set one page as current page]]
50 }
51 get {
52 [[Get the current page]]
53 }
54 values {
55 index: int;
56 }
57 }
58 @property scroll_block {
59 [[Pages can be scrolled back and forth by default. This property allows
60 limiting the direction of scrolling, or blocking scroll gesture at all.
61 ]]
62 values {
63 prev: bool;
64 next: bool;
65 }
66 }
67 @property loop_mode {
68 [[Pager is not scrolled after it's scrolled to the end by default.
69 This property gives the option to make a loop through pages.
70 ]]
71 values {
72 loop: Efl.Ui.Pager.Loop;
73 }
74 }
75 @property page_size {
76 values {
77 size: Eina.Size2D;
78 }
79 }
80 @property padding {
81 values {
82 padding: int;
83 }
84 }
85 }
86 implements {
87 Efl.Object.constructor;
88 Efl.Container.content_count;
89 Efl.Pack.pack_clear; //TODO
90 Efl.Pack.unpack_all; //TODO
91 Efl.Pack.unpack; //TODO
92 Efl.Pack.Linear.pack_begin;
93 Efl.Pack.Linear.pack_end;
94 Efl.Pack.Linear.pack_before;
95 Efl.Pack.Linear.pack_after;
96 Efl.Pack.Linear.pack_at;
97 Efl.Pack.Linear.pack_content_get;
98 Efl.Pack.Linear.pack_index_get;
99 Efl.Pack.Linear.pack_unpack_at; //TODO
100 }
101}
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 0000000..d01cc29
--- /dev/null
+++ b/src/lib/elementary/efl_ui_widget_pager.h
@@ -0,0 +1,69 @@
1#ifndef EFL_UI_WIDGET_PAGER_H
2#define EFL_UI_WIDGET_PAGER_H
3
4
5#include <Elementary.h>
6
7#include "efl_page_transition.h"
8
9typedef struct _Efl_Ui_Pager_Data
10{
11 Eina_List *page_infos;
12 Eina_List *content_list;
13
14 Efl_Ui_Box *page_box;
15 Eo *foreclip;
16 Eo *backclip;
17
18 Eo *page_root;
19 Eo *event;
20 Efl_Ui_Box *idbox;
21 Ecore_Job *job;
22 Ecore_Job *page_info_job;
23
24 Evas_Coord x, y, w, h;
25 Evas_Coord mouse_x, mouse_y;
26
27 struct {
28 Eina_Size2D sz;
29 Evas_Coord padding;
30 } page_spec;
31
32 struct {
33 Evas_Coord x, y;
34 int page;
35 double pos;
36 Eina_Bool enabled;
37 } down;
38
39 struct {
40 int page;
41 double pos;
42 } curr;
43
44 struct {
45 double src;
46 double delta;
47 double start_time;
48 Eina_Bool jump;
49 } change;
50
51 int cnt;
52 double mouse_up_time;
53
54 Efl_Ui_Pager_Loop loop;
55 Efl_Page_Transition *transition;
56 Efl_Page_Indicator *indicator;
57
58 Eina_Bool move_started : 1;
59 Eina_Bool prev_block : 1;
60 Eina_Bool next_block: 1;
61 Eina_Bool fill_width: 1;
62 Eina_Bool fill_height: 1;
63
64} Efl_Ui_Pager_Data;
65
66#define EFL_UI_PAGER_DATA_GET(o, sd) \
67 Efl_Ui_Pager_Data *sd = efl_data_scope_get(o, EFL_UI_PAGER_CLASS)
68
69#endif
diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h
index f131969..faf1e52 100644
--- a/src/lib/elementary/elm_priv.h
+++ b/src/lib/elementary/elm_priv.h
@@ -731,6 +731,16 @@ void *_elm_icon_signal_callback_del(Evas_Object *obj,
731/* DO NOT USE THIS this is only for performance optimization! */ 731/* DO NOT USE THIS this is only for performance optimization! */
732void _elm_widget_full_eval(Eo *obj); 732void _elm_widget_full_eval(Eo *obj);
733 733
734EOAPI void efl_page_transition_page_size_set(Eo *obj, Eina_Size2D sz);
735EOAPI void efl_page_transition_padding_size_set(Eo *obj, int padding);
736EOAPI void efl_page_transition_update(Eo *obj, double pos);
737EOAPI void efl_page_transition_curr_page_change(Eo *obj, double move);
738EOAPI void efl_page_transition_pack_end(Eo *obj, Efl_Gfx *subobj);
739EOAPI void efl_page_transition_loop_set(Eo *obj, Efl_Ui_Pager_Loop loop);
740
741EOAPI void efl_page_indicator_update(Eo *obj, double pos);
742EOAPI void efl_page_indicator_pack(Eo *obj, int index);
743
734Eina_Bool _elm_config_accel_preference_parse(const char *pref, Eina_Stringshare **accel, int *gl_depth, int *gl_stencil, int *gl_msaa); 744Eina_Bool _elm_config_accel_preference_parse(const char *pref, Eina_Stringshare **accel, int *gl_depth, int *gl_stencil, int *gl_msaa);
735 745
736extern char *_elm_appname; 746extern char *_elm_appname;