forked from enlightenment/efl
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.
This commit is contained in:
parent
ea84f4450c
commit
e74ebca670
|
@ -1040,7 +1040,8 @@ elementary/themes/edc/efl/textpath.edc \
|
|||
elementary/themes/edc/efl/tooltip.edc \
|
||||
elementary/themes/edc/efl/video.edc \
|
||||
elementary/themes/edc/efl/list.edc \
|
||||
elementary/themes/edc/efl/win.edc
|
||||
elementary/themes/edc/efl/win.edc \
|
||||
elementary/themes/edc/efl/pager.edc
|
||||
|
||||
elementary_fdo_actions_128_files = \
|
||||
elementary/themes/fdo/actions/128/address-book-new.png \
|
||||
|
|
|
@ -196,4 +196,5 @@ collections {
|
|||
#include "edc/efl/textpath.edc"
|
||||
#include "edc/efl/win.edc"
|
||||
#include "edc/efl/uiclock.edc"
|
||||
#include "edc/efl/pager.edc"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
group { "efl/pager";
|
||||
parts {
|
||||
spacer { "base";
|
||||
scale;
|
||||
desc { "default";
|
||||
}
|
||||
}
|
||||
swallow { "elm.swallow.background";
|
||||
scale;
|
||||
desc { "default";
|
||||
}
|
||||
}
|
||||
swallow { "page_root";
|
||||
scale;
|
||||
desc { "default";
|
||||
rel1.relative: 0.0 1.0;
|
||||
rel1.to: "indicator";
|
||||
}
|
||||
}
|
||||
swallow { "indicator";
|
||||
scale;
|
||||
desc { "default";
|
||||
rel2.relative: 1.0 0.0;
|
||||
align: 0.5 0.0;
|
||||
min: 0 50;
|
||||
}
|
||||
}
|
||||
swallow { "event";
|
||||
scale;
|
||||
repeat_events: 1;
|
||||
desc { "default";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group { "efl/pager/indicator";
|
||||
images {
|
||||
image: "ring_white_middle.png" COMP;
|
||||
}
|
||||
parts {
|
||||
spacer { "base";
|
||||
scale;
|
||||
desc { "default";
|
||||
}
|
||||
}
|
||||
image { "icon";
|
||||
scale;
|
||||
desc { "default";
|
||||
image.normal: "ring_white_middle.png";
|
||||
color: 0 0 0 255;
|
||||
min: 6 6;
|
||||
}
|
||||
desc { "selected";
|
||||
inherit: "default";
|
||||
color: 255 0 0 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
script {
|
||||
public message(Msg_Type:type, id, ...) {
|
||||
set_tween_state(PART:"icon", getfarg(2),
|
||||
"default", 0.0, "selected", 0.0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,6 +105,11 @@ 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 \
|
||||
lib/elementary/efl_page_indicator.eo \
|
||||
lib/elementary/efl_page_indicator_icon.eo \
|
||||
$(NULL)
|
||||
|
||||
# More public files -- FIXME
|
||||
|
@ -400,7 +405,12 @@ includesunstable_HEADERS = \
|
|||
lib/elementary/efl_ui_widget_scroll_manager.h \
|
||||
lib/elementary/efl_ui_widget_pan.h \
|
||||
lib/elementary/efl_ui_nstate_private.h \
|
||||
lib/elementary/Efl_Ui.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 \
|
||||
lib/elementary/efl_page_indicator.h \
|
||||
lib/elementary/efl_page_indicator_icon.h
|
||||
includesunstabledir = $(includedir)/elementary-@VMAJ@
|
||||
|
||||
nodist_includesunstable_HEADERS = \
|
||||
|
@ -805,6 +815,11 @@ 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 \
|
||||
lib/elementary/efl_page_indicator.c \
|
||||
lib/elementary/efl_page_indicator_icon.c \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
|
|
@ -341,6 +341,17 @@ 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>
|
||||
|
||||
# ifndef _EFL_UI_PAGER_EO_CLASS_TYPE
|
||||
# define _EFL_UI_PAGER_EO_CLASS_TYPE
|
||||
typedef Eo Efl_Ui_Pager;
|
||||
# endif
|
||||
|
||||
# include <efl_page_transition.eo.h>
|
||||
# include <efl_page_transition_scroll.eo.h>
|
||||
# include <efl_page_indicator.eo.h>
|
||||
# include <efl_page_indicator_icon.eo.h>
|
||||
# include <efl_ui_pager.eo.h>
|
||||
#endif
|
||||
|
||||
/* include deprecated calls last of all */
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "elementary_config.h"
|
||||
#endif
|
||||
|
||||
#include <Elementary.h>
|
||||
#include "elm_priv.h"
|
||||
|
||||
#include "efl_page_indicator.h"
|
||||
#include "efl_ui_widget_pager.h"
|
||||
|
||||
#define MY_CLASS EFL_PAGE_INDICATOR_CLASS
|
||||
|
||||
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_indicator_update(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Indicator_Data *pd EINA_UNUSED,
|
||||
double pos EINA_UNUSED)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_indicator_pack(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Indicator_Data *pd,
|
||||
int index EINA_UNUSED)
|
||||
{
|
||||
pd->cnt++;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_indicator_bind(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Indicator_Data *pd,
|
||||
Eo *pager,
|
||||
Efl_Canvas_Group *idbox)
|
||||
{
|
||||
if (pd->pager.obj == pager) return;
|
||||
|
||||
pd->pager.obj = pager;
|
||||
pd->idbox = idbox;
|
||||
|
||||
if (pager)
|
||||
pd->cnt = efl_content_count(pd->pager.obj);
|
||||
}
|
||||
|
||||
|
||||
EOAPI EFL_VOID_FUNC_BODYV(efl_page_indicator_update,
|
||||
EFL_FUNC_CALL(pos), double pos)
|
||||
EOAPI EFL_VOID_FUNC_BODYV(efl_page_indicator_pack,
|
||||
EFL_FUNC_CALL(index), int index)
|
||||
|
||||
#define EFL_PAGE_INDICATOR_EXTRA_OPS \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_indicator_update, \
|
||||
_efl_page_indicator_update), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_indicator_pack, \
|
||||
_efl_page_indicator_pack)
|
||||
|
||||
#include "efl_page_indicator.eo.c"
|
|
@ -0,0 +1,18 @@
|
|||
class Efl.Page.Indicator (Efl.Object)
|
||||
{
|
||||
[[Page indicator
|
||||
|
||||
Page indicator is used with @Efl.Ui.Pager.
|
||||
It is located on the top layer of pager widget and helps users to know
|
||||
the number of pages and the current page's index without scrolling.
|
||||
]]
|
||||
methods {
|
||||
bind {
|
||||
[[set object]]
|
||||
params {
|
||||
@in pager: Efl.Ui.Pager; [[pager object]]
|
||||
@in group: Efl.Canvas.Group; [[a dummy object for layer adjustment]]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef EFL_PAGE_INDICATOR_H
|
||||
#define EFL_PAGE_INDICATOR_H
|
||||
|
||||
typedef struct _Efl_Page_Indicator_Data Efl_Page_Indicator_Data;
|
||||
|
||||
struct _Efl_Page_Indicator_Data
|
||||
{
|
||||
struct {
|
||||
Efl_Object *obj;
|
||||
Efl_Object *group;
|
||||
Evas_Coord x, y, w, h;
|
||||
} pager;
|
||||
|
||||
Efl_Ui_Box *idbox;
|
||||
|
||||
int cnt;
|
||||
};
|
||||
|
||||
#define EFL_PAGE_INDICATOR_DATA_GET(o, pd) \
|
||||
Efl_Page_Indicator_Data *pd = \
|
||||
efl_data_scope_get(o, EFL_PAGE_INDICATOR_CLASS)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,152 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "elementary_config.h"
|
||||
#endif
|
||||
|
||||
#include <Elementary.h>
|
||||
#include "elm_priv.h"
|
||||
|
||||
#include "efl_page_indicator_icon.h"
|
||||
#include "efl_page_indicator.h"
|
||||
#include "efl_ui_widget_pager.h"
|
||||
|
||||
#define MY_CLASS EFL_PAGE_INDICATOR_ICON_CLASS
|
||||
|
||||
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_indicator_icon_update(Eo *obj,
|
||||
Efl_Page_Indicator_Icon_Data *pd,
|
||||
double pos)
|
||||
{
|
||||
EFL_PAGE_INDICATOR_DATA_GET(obj, spd);
|
||||
Eo *item;
|
||||
int page = efl_ui_pager_current_page_get(spd->pager.obj);
|
||||
double delta = fabs(pos);
|
||||
|
||||
if (pd->curr)
|
||||
{
|
||||
eina_value_set(pd->v, 0.0);
|
||||
efl_layout_signal_message_send(pd->curr, 1, *(pd->v));
|
||||
if (pd->adj) efl_layout_signal_message_send(pd->adj, 1, *(pd->v));
|
||||
}
|
||||
|
||||
item = eina_list_nth(pd->items, page);
|
||||
eina_value_set(pd->v, (1.0 - delta));
|
||||
efl_layout_signal_message_send(item, 1, *(pd->v));
|
||||
pd->curr = item;
|
||||
|
||||
if (pos < 0)
|
||||
item = eina_list_nth(pd->items, (page - 1 + spd->cnt) % spd->cnt);
|
||||
else
|
||||
item = eina_list_nth(pd->items, (page + 1 + spd->cnt) % spd->cnt);
|
||||
|
||||
eina_value_set(pd->v, delta);
|
||||
efl_layout_signal_message_send(item, 1, *(pd->v));
|
||||
pd->adj = item;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_indicator_icon_pack(Eo *obj,
|
||||
Efl_Page_Indicator_Icon_Data *pd,
|
||||
int index)
|
||||
{
|
||||
EFL_PAGE_INDICATOR_DATA_GET(obj, spd);
|
||||
Eo *item, *existing;
|
||||
|
||||
efl_page_indicator_pack(efl_super(obj, MY_CLASS), index);
|
||||
|
||||
item = efl_add(EFL_CANVAS_LAYOUT_CLASS, spd->idbox);
|
||||
elm_widget_theme_object_set(spd->idbox, item,
|
||||
"pager", "indicator", "default");
|
||||
efl_gfx_size_hint_align_set(item, 0.5, 0.5);
|
||||
efl_gfx_size_hint_weight_set(item, 0, 0);
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
pd->items = eina_list_prepend(pd->items, item);
|
||||
efl_pack_begin(spd->idbox, item);
|
||||
}
|
||||
else if (index == (spd->cnt - 1))
|
||||
{
|
||||
pd->items = eina_list_append(pd->items, item);
|
||||
efl_pack_end(spd->idbox, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
existing = eina_list_nth(pd->items, index);
|
||||
pd->items = eina_list_prepend_relative(pd->items, item, existing);
|
||||
efl_pack_before(spd->idbox, item, existing);
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_indicator_icon_efl_page_indicator_bind(Eo *obj,
|
||||
Efl_Page_Indicator_Icon_Data *pd,
|
||||
Eo *pager,
|
||||
Efl_Canvas_Group *idbox)
|
||||
{
|
||||
EFL_PAGE_INDICATOR_DATA_GET(obj, spd);
|
||||
Eo *item;
|
||||
int i, page;
|
||||
|
||||
if (spd->pager.obj)
|
||||
{
|
||||
EINA_LIST_FREE(pd->items, item)
|
||||
{
|
||||
efl_del(item);
|
||||
}
|
||||
}
|
||||
|
||||
efl_page_indicator_bind(efl_super(obj, MY_CLASS), pager, idbox);
|
||||
|
||||
if (spd->pager.obj)
|
||||
{
|
||||
efl_ui_direction_set(spd->idbox, EFL_UI_DIR_HORIZONTAL);
|
||||
efl_pack_padding_set(spd->idbox, 15, 15, EINA_TRUE);
|
||||
|
||||
pd->v = eina_value_float_new(0.0);
|
||||
|
||||
if (spd->cnt != 0)
|
||||
{
|
||||
for (i = 0; i < spd->cnt; i++)
|
||||
{
|
||||
item = efl_add(EFL_CANVAS_LAYOUT_CLASS, spd->idbox);
|
||||
pd->items = eina_list_append(pd->items, item);
|
||||
|
||||
elm_widget_theme_object_set(spd->idbox, item,
|
||||
"pager", "indicator", "default");
|
||||
efl_gfx_size_hint_align_set(item, 0.5, 0.5);
|
||||
efl_gfx_size_hint_weight_set(item, 0, 0);
|
||||
efl_pack_end(spd->idbox, item);
|
||||
}
|
||||
|
||||
page = efl_ui_pager_current_page_get(spd->pager.obj);
|
||||
item = eina_list_nth(pd->items, page);
|
||||
eina_value_set(pd->v, 1.0);
|
||||
efl_layout_signal_message_send(item, 1, *(pd->v));
|
||||
|
||||
pd->curr = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_indicator_icon_efl_object_invalidate(Eo *obj,
|
||||
Efl_Page_Indicator_Icon_Data *pd)
|
||||
{
|
||||
Eo *item;
|
||||
|
||||
EINA_LIST_FREE(pd->items, item)
|
||||
efl_del(item);
|
||||
|
||||
efl_invalidate(efl_super(obj, MY_CLASS));
|
||||
}
|
||||
|
||||
|
||||
#define EFL_PAGE_INDICATOR_ICON_EXTRA_OPS \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_indicator_update, \
|
||||
_efl_page_indicator_icon_update), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_indicator_pack, \
|
||||
_efl_page_indicator_icon_pack)
|
||||
|
||||
#include "efl_page_indicator_icon.eo.c"
|
|
@ -0,0 +1,13 @@
|
|||
class Efl.Page.Indicator.Icon (Efl.Page.Indicator)
|
||||
{
|
||||
[[Icon type page indicator
|
||||
|
||||
This class offers icon type indicator for @Efl.Ui.Pager.
|
||||
This type of page indicator creates the same number of icons as pages and
|
||||
arrange them in a linear order. An icon has two states: default and selected.
|
||||
]]
|
||||
implements {
|
||||
Efl.Object.invalidate;
|
||||
Efl.Page.Indicator.bind;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef EFL_PAGE_INDICATOR_ICON_H
|
||||
#define EFL_PAGE_INDICATOR_ICON_H
|
||||
|
||||
typedef struct _Efl_Page_Indicator_Icon_Data Efl_Page_Indicator_Icon_Data;
|
||||
|
||||
struct _Efl_Page_Indicator_Icon_Data
|
||||
{
|
||||
Eo *curr, *adj;
|
||||
|
||||
Eina_List *items;
|
||||
Eina_Value *v;
|
||||
};
|
||||
|
||||
|
||||
#define EFL_PAGE_INDICATOR_ICON_DATA_GET(o, pd) \
|
||||
Efl_Page_Indicator_Icon_Data *pd = \
|
||||
efl_data_scope_get(o, EFL_PAGE_INDICATOR_ICON_CLASS)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,107 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "elementary_config.h"
|
||||
#endif
|
||||
|
||||
#include <Elementary.h>
|
||||
#include "elm_priv.h"
|
||||
|
||||
#include "efl_page_transition.h"
|
||||
#include "efl_ui_widget_pager.h"
|
||||
|
||||
#define MY_CLASS EFL_PAGE_TRANSITION_CLASS
|
||||
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_page_size_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Data *pd,
|
||||
Eina_Size2D sz)
|
||||
{
|
||||
pd->page_spec.sz = sz;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_padding_size_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Data *pd,
|
||||
int padding)
|
||||
{
|
||||
pd->page_spec.padding = padding;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_bind(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Data *pd,
|
||||
Eo *pager,
|
||||
Efl_Canvas_Group *group)
|
||||
{
|
||||
Eina_Rect group_rect;
|
||||
|
||||
if (pd->pager.obj == pager) return;
|
||||
|
||||
pd->pager.obj = pager;
|
||||
pd->pager.group = group;
|
||||
|
||||
if (pager)
|
||||
{
|
||||
group_rect = efl_gfx_geometry_get(group);
|
||||
|
||||
pd->pager.x = group_rect.x;
|
||||
pd->pager.y = group_rect.y;
|
||||
pd->pager.w = group_rect.w;
|
||||
pd->pager.h = group_rect.h;
|
||||
|
||||
pd->page_spec.sz = efl_ui_pager_page_size_get(pager);
|
||||
pd->page_spec.padding = efl_ui_pager_padding_get(pager);
|
||||
pd->loop = efl_ui_pager_loop_mode_get(pager);
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_update(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Data *pd EINA_UNUSED,
|
||||
double move EINA_UNUSED)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_curr_page_change(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Data *pd EINA_UNUSED,
|
||||
int diff EINA_UNUSED)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_loop_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Data *pd,
|
||||
Efl_Ui_Pager_Loop loop)
|
||||
{
|
||||
pd->loop = loop;
|
||||
}
|
||||
|
||||
|
||||
EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_update,
|
||||
EFL_FUNC_CALL(move), double move)
|
||||
EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_curr_page_change,
|
||||
EFL_FUNC_CALL(move), double move)
|
||||
EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_page_size_set,
|
||||
EFL_FUNC_CALL(sz), Eina_Size2D sz)
|
||||
EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_padding_size_set,
|
||||
EFL_FUNC_CALL(padding), int padding)
|
||||
EOAPI EFL_VOID_FUNC_BODYV(efl_page_transition_loop_set,
|
||||
EFL_FUNC_CALL(loop), Efl_Ui_Pager_Loop loop)
|
||||
|
||||
|
||||
#define EFL_PAGE_TRANSITION_EXTRA_OPS \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_update, \
|
||||
_efl_page_transition_update), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_curr_page_change, \
|
||||
_efl_page_transition_curr_page_change), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_page_size_set, \
|
||||
_efl_page_transition_page_size_set), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_padding_size_set, \
|
||||
_efl_page_transition_padding_size_set), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_loop_set, \
|
||||
_efl_page_transition_loop_set)
|
||||
|
||||
#include "efl_page_transition.eo.c"
|
|
@ -0,0 +1,17 @@
|
|||
class Efl.Page.Transition (Efl.Object)
|
||||
{
|
||||
[[Page transition for @Efl.Ui.Pager
|
||||
|
||||
A page transition is essential to @Efl.Ui.Pager object and invoked whenever
|
||||
pages are rearranged or scrolled (see @Efl.Ui.Pager).
|
||||
]]
|
||||
methods {
|
||||
bind {
|
||||
[[set object]]
|
||||
params {
|
||||
@in pager: Efl.Ui.Pager; [[pager object]]
|
||||
@in group: Efl.Canvas.Group; [[a dummy object for layer adjustment]]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#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
|
||||
{
|
||||
struct {
|
||||
Efl_Object *obj;
|
||||
Efl_Canvas_Group *group;
|
||||
Evas_Coord x, y, w, h;
|
||||
} pager;
|
||||
|
||||
struct {
|
||||
Eina_Size2D sz;
|
||||
Evas_Coord padding;
|
||||
} page_spec;
|
||||
|
||||
Efl_Ui_Pager_Loop loop;
|
||||
};
|
||||
|
||||
#define EFL_PAGE_TRANSITION_DATA_GET(o, pd) \
|
||||
Efl_Page_Transition_Data *pd = \
|
||||
efl_data_scope_get(o, EFL_PAGE_TRANSITION_CLASS)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,606 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "elementary_config.h"
|
||||
#endif
|
||||
|
||||
#include <Elementary.h>
|
||||
#include "elm_priv.h"
|
||||
|
||||
#include "efl_page_transition_scroll.h"
|
||||
#include "efl_page_transition.h"
|
||||
#include "efl_ui_widget_pager.h"
|
||||
|
||||
#define MY_CLASS EFL_PAGE_TRANSITION_SCROLL_CLASS
|
||||
|
||||
|
||||
|
||||
static void
|
||||
_page_info_deallocate(Efl_Page_Transition_Scroll_Data *pd)
|
||||
{
|
||||
Page_Info *pi;
|
||||
|
||||
EINA_LIST_FREE(pd->page_infos, pi)
|
||||
{
|
||||
if (pi->content)
|
||||
efl_pack_unpack(pi->obj, pi->content);
|
||||
|
||||
efl_del(pi->obj);
|
||||
free(pi);
|
||||
}
|
||||
|
||||
pd->head = NULL;
|
||||
pd->tail = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_page_info_allocate(Efl_Page_Transition_Scroll_Data *pd,
|
||||
Efl_Page_Transition_Data *spd)
|
||||
{
|
||||
Page_Info *pi, *prev = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pd->page_info_num; i++)
|
||||
{
|
||||
pi = calloc(1, sizeof(*pi));
|
||||
if (i == 0) pd->head = pi;
|
||||
else if (i == (pd->page_info_num - 1)) 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, spd->pager.obj);
|
||||
efl_canvas_group_member_add(spd->pager.group, pi->obj);
|
||||
pd->page_infos = eina_list_append(pd->page_infos, pi);
|
||||
|
||||
if (prev)
|
||||
{
|
||||
pi->prev = prev;
|
||||
prev->next = pi;
|
||||
}
|
||||
prev = pi;
|
||||
}
|
||||
|
||||
pd->head->prev = pd->tail;
|
||||
pd->tail->next = pd->head;
|
||||
}
|
||||
|
||||
static void
|
||||
_content_show(Efl_Page_Transition_Scroll_Data *pd,
|
||||
Efl_Page_Transition_Data *spd)
|
||||
{
|
||||
Eina_List *list;
|
||||
Page_Info *pi;
|
||||
int tmp_id;
|
||||
Eo *tmp;
|
||||
int curr_page, cnt;
|
||||
|
||||
curr_page = efl_ui_pager_current_page_get(spd->pager.obj);
|
||||
cnt = efl_content_count(spd->pager.obj);
|
||||
|
||||
// at this point, the number of visible pages might have been changed,
|
||||
// so empty all boxes and refill them with the right contents.
|
||||
// FIXME make logic efficient: don't have to empty all and fill all the time
|
||||
EINA_LIST_FOREACH(pd->page_infos, list, pi)
|
||||
{
|
||||
if (pi->content)
|
||||
{
|
||||
efl_pack_unpack(pi->obj, pi->content);
|
||||
efl_canvas_object_clip_set(pi->content, pd->backclip);
|
||||
|
||||
pi->content_num = -1;
|
||||
pi->content = NULL;
|
||||
pi->visible = EINA_FALSE;
|
||||
}
|
||||
efl_canvas_object_clip_set(pi->obj, pd->backclip);
|
||||
}
|
||||
|
||||
EINA_LIST_FOREACH(pd->page_infos, list, pi)
|
||||
{
|
||||
if (pi->vis_page)
|
||||
{
|
||||
tmp_id = (curr_page + pi->pos + cnt) % cnt;
|
||||
|
||||
if ((spd->loop == EFL_UI_PAGER_LOOP_DISABLED)
|
||||
&& ((pi->pos) * (tmp_id - curr_page) < 0)) continue;
|
||||
|
||||
tmp = efl_pack_content_get(spd->pager.obj, tmp_id);
|
||||
if (tmp)
|
||||
{
|
||||
efl_canvas_object_clip_set(pi->obj, pd->foreclip);
|
||||
|
||||
efl_pack(pi->obj, tmp);
|
||||
efl_canvas_object_clip_set(tmp, pd->foreclip);
|
||||
|
||||
pi->content_num = tmp_id;
|
||||
pi->content = tmp;
|
||||
pi->visible = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME use ecore_job
|
||||
static void
|
||||
_page_info_geometry_change(Efl_Page_Transition_Scroll_Data *pd,
|
||||
Efl_Page_Transition_Data *spd)
|
||||
{
|
||||
Eina_List *list;
|
||||
Page_Info *pi;
|
||||
int content_w;
|
||||
|
||||
content_w = spd->page_spec.sz.w
|
||||
+ ((spd->page_spec.sz.w + spd->page_spec.padding) * pd->side_page_num * 2);
|
||||
|
||||
if (content_w < spd->pager.w)
|
||||
{
|
||||
EINA_RECTANGLE_SET(&pd->viewport,
|
||||
spd->pager.x + ((spd->pager.w - content_w) / 2),
|
||||
spd->pager.y,
|
||||
content_w,
|
||||
spd->pager.h);
|
||||
}
|
||||
else
|
||||
{
|
||||
EINA_RECTANGLE_SET(&pd->viewport,
|
||||
spd->pager.x,
|
||||
spd->pager.y,
|
||||
spd->pager.w,
|
||||
spd->pager.h);
|
||||
}
|
||||
|
||||
efl_gfx_geometry_set(pd->foreclip, (Eina_Rect) pd->viewport);
|
||||
|
||||
// this loop resets the geometry of each page based on the geometry of
|
||||
// the pager object, the page size, and the padding size.
|
||||
EINA_LIST_FOREACH(pd->page_infos, list, pi)
|
||||
{
|
||||
EINA_RECTANGLE_SET(&pi->geometry,
|
||||
spd->pager.x + (spd->pager.w / 2)
|
||||
+ pi->pos * (spd->page_spec.sz.w + spd->page_spec.padding)
|
||||
- (spd->page_spec.sz.w / 2),
|
||||
spd->pager.y + (spd->pager.h / 2) - (spd->page_spec.sz.h / 2),
|
||||
spd->page_spec.sz.w,
|
||||
spd->page_spec.sz.h);
|
||||
|
||||
if (eina_rectangles_intersect(&pi->geometry, &pd->viewport) &&
|
||||
((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->foreclip);
|
||||
}
|
||||
else
|
||||
{
|
||||
pi->vis_page = EINA_FALSE;
|
||||
pi->visible = EINA_FALSE;
|
||||
efl_canvas_object_clip_set(pi->obj, pd->backclip);
|
||||
}
|
||||
|
||||
efl_gfx_geometry_set(pi->obj, (Eina_Rect) pi->geometry);
|
||||
}
|
||||
|
||||
if (efl_content_count(spd->pager.obj) > 0) _content_show(pd, spd);
|
||||
}
|
||||
|
||||
static void
|
||||
_resize_cb(void *data, const Efl_Event *ev)
|
||||
{
|
||||
Efl_Page_Transition_Scroll *obj = data;
|
||||
EFL_PAGE_TRANSITION_SCROLL_DATA_GET(obj, pd);
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
|
||||
Eina_Size2D sz;
|
||||
|
||||
Efl_Ui_Pager *pager = ev->object;
|
||||
|
||||
sz = efl_gfx_size_get(pager);
|
||||
|
||||
spd->pager.w = sz.w;
|
||||
spd->pager.h = sz.h;
|
||||
|
||||
_page_info_geometry_change(pd, spd);
|
||||
}
|
||||
|
||||
static void
|
||||
_move_cb(void *data, const Efl_Event *ev)
|
||||
{
|
||||
Efl_Page_Transition_Scroll *obj = data;
|
||||
EFL_PAGE_TRANSITION_SCROLL_DATA_GET(obj, pd);
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
|
||||
Eina_Position2D pos;
|
||||
|
||||
Efl_Ui_Pager *pager = ev->object;
|
||||
|
||||
pos = efl_gfx_position_get(pager);
|
||||
|
||||
spd->pager.x = pos.x;
|
||||
spd->pager.y = pos.y;
|
||||
|
||||
_page_info_geometry_change(pd, spd);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_efl_page_transition_bind(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd,
|
||||
Eo *pager,
|
||||
Efl_Canvas_Group *group)
|
||||
{
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
|
||||
if (spd->pager.obj == pager) return;
|
||||
|
||||
if (spd->pager.obj)
|
||||
{
|
||||
efl_event_callback_del(spd->pager.group, EFL_GFX_EVENT_RESIZE, _resize_cb, obj);
|
||||
efl_event_callback_del(spd->pager.group, EFL_GFX_EVENT_MOVE, _move_cb, obj);
|
||||
|
||||
_page_info_deallocate(pd);
|
||||
efl_del(pd->foreclip);
|
||||
efl_del(pd->backclip);
|
||||
}
|
||||
|
||||
efl_page_transition_bind(efl_super(obj, MY_CLASS), pager, group);
|
||||
|
||||
if (spd->pager.obj)
|
||||
{
|
||||
int cnt, i;
|
||||
Eo *item;
|
||||
|
||||
efl_event_callback_add(spd->pager.group, EFL_GFX_EVENT_RESIZE, _resize_cb, obj);
|
||||
efl_event_callback_add(spd->pager.group, EFL_GFX_EVENT_MOVE, _move_cb, obj);
|
||||
|
||||
pd->foreclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
|
||||
evas_object_evas_get(spd->pager.obj));
|
||||
evas_object_static_clip_set(pd->foreclip, EINA_TRUE);
|
||||
|
||||
pd->backclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
|
||||
evas_object_evas_get(spd->pager.obj));
|
||||
evas_object_static_clip_set(pd->backclip, EINA_TRUE);
|
||||
efl_gfx_visible_set(pd->backclip, EINA_FALSE);
|
||||
|
||||
cnt = efl_content_count(spd->pager.obj);
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
item = efl_pack_content_get(spd->pager.obj, i);
|
||||
efl_canvas_object_clip_set(item, pd->backclip);
|
||||
}
|
||||
_page_info_allocate(pd, spd);
|
||||
_page_info_geometry_change(pd, spd);
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_page_size_set(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd,
|
||||
Eina_Size2D sz)
|
||||
{
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
|
||||
efl_page_transition_page_size_set(efl_super(obj, MY_CLASS), sz);
|
||||
_page_info_geometry_change(pd, spd);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_padding_size_set(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd,
|
||||
int padding)
|
||||
{
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
|
||||
efl_page_transition_padding_size_set(efl_super(obj, MY_CLASS), padding);
|
||||
_page_info_geometry_change(pd, spd);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_update(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd,
|
||||
double pos)
|
||||
{
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
|
||||
double t;
|
||||
int tmp_id, curr_page, cnt;
|
||||
Eo *tmp;
|
||||
Eina_List *list;
|
||||
Page_Info *pi, *tpi;
|
||||
|
||||
t = pos;
|
||||
if (t < 0) t *= (-1);
|
||||
|
||||
curr_page = efl_ui_pager_current_page_get(spd->pager.obj);
|
||||
cnt = efl_content_count(spd->pager.obj);
|
||||
|
||||
// while pages are scrolled,
|
||||
// 1. the geometry of each page needs to be changed
|
||||
// 2. if a page gets out of the viewport, it needs to be hidden
|
||||
// 3. if a page gets into the viewport, it needs to be shown
|
||||
EINA_LIST_FOREACH(pd->page_infos, list, pi)
|
||||
{
|
||||
if (pos < 0) // if scrolled right, each page takes next page's position
|
||||
tpi = pi->next;
|
||||
else // else if scrolled left, each page takes prev page's position
|
||||
tpi = pi->prev;
|
||||
|
||||
EINA_RECTANGLE_SET(&pi->temp,
|
||||
tpi->geometry.x * t + pi->geometry.x * (1 - t),
|
||||
tpi->geometry.y,
|
||||
tpi->geometry.w,
|
||||
tpi->geometry.h);
|
||||
|
||||
efl_gfx_geometry_set(pi->obj, (Eina_Rect) pi->temp);
|
||||
|
||||
if (!pi->vis_page && !tpi->vis_page) continue;
|
||||
|
||||
if (!eina_rectangles_intersect(&pi->temp, &pd->viewport))
|
||||
{
|
||||
if (pi->content)
|
||||
{
|
||||
efl_canvas_object_clip_set(pi->obj, pd->backclip);
|
||||
|
||||
efl_pack_unpack(pi->obj, pi->content);
|
||||
efl_canvas_object_clip_set(pi->content, pd->backclip);
|
||||
|
||||
pi->content_num = -1;
|
||||
pi->content = NULL;
|
||||
pi->visible = EINA_FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_id = (curr_page + pi->pos + cnt) % cnt;
|
||||
if (pi->content_num != tmp_id)
|
||||
{
|
||||
if (pi->content) //FIXME if the content num is the same, do nothing
|
||||
{
|
||||
efl_pack_unpack(pi->obj, pi->content);
|
||||
efl_canvas_object_clip_set(pi->content, pd->backclip);
|
||||
|
||||
pi->content_num = -1;
|
||||
pi->content = NULL;
|
||||
}
|
||||
|
||||
if ((spd->loop == EFL_UI_PAGER_LOOP_DISABLED)
|
||||
&& ((pi->pos) * (tmp_id - curr_page) < 0)) continue;
|
||||
tmp = efl_pack_content_get(spd->pager.obj, tmp_id);
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
efl_canvas_object_clip_set(pi->obj, pd->foreclip);
|
||||
|
||||
efl_pack(pi->obj, tmp);
|
||||
efl_canvas_object_clip_set(tmp, pd->foreclip);
|
||||
|
||||
pi->content_num = tmp_id;
|
||||
pi->content = tmp;
|
||||
pi->visible = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_curr_page_change(Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Scroll_Data *pd,
|
||||
double pos)
|
||||
{
|
||||
Eina_List *list;
|
||||
Page_Info *pi, *target;
|
||||
|
||||
// after the current page is changed, page infos need to be updated
|
||||
// with a new id based on the new geometry of the boxes.
|
||||
EINA_LIST_FOREACH(pd->page_infos, list, pi)
|
||||
{
|
||||
if (EINA_DBL_EQ(pos, 1.0))
|
||||
{
|
||||
pi->id = (pi->id - 1 + pd->page_info_num) % pd->page_info_num;
|
||||
target = pi->prev;
|
||||
}
|
||||
else if (EINA_DBL_EQ(pos, -1.0))
|
||||
{
|
||||
pi->id = (pi->id + 1) % pd->page_info_num;
|
||||
target = pi->next;
|
||||
}
|
||||
pi->pos = pi->id - (pd->side_page_num + 1);
|
||||
|
||||
EINA_RECTANGLE_SET(&pi->temp,
|
||||
target->geometry.x,
|
||||
target->geometry.y,
|
||||
target->geometry.w,
|
||||
target->geometry.h);
|
||||
|
||||
if (eina_rectangles_intersect(&pi->temp, &pd->viewport) &&
|
||||
(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->foreclip);
|
||||
}
|
||||
else
|
||||
{
|
||||
pi->vis_page = EINA_FALSE;
|
||||
pi->visible = EINA_FALSE;
|
||||
efl_canvas_object_clip_set(pi->obj, pd->backclip);
|
||||
if (pi->content)
|
||||
{
|
||||
efl_pack_unpack(pi->obj, pi->content);
|
||||
efl_canvas_object_clip_set(pi->content, pd->backclip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EINA_DBL_EQ(pos, 1.0))
|
||||
{
|
||||
pd->head = pd->head->next;
|
||||
pd->tail = pd->tail->next;
|
||||
}
|
||||
else if (EINA_DBL_EQ(pos, -1.0))
|
||||
{
|
||||
pd->head = pd->head->prev;
|
||||
pd->tail = pd->tail->prev;
|
||||
}
|
||||
|
||||
EINA_LIST_FOREACH(pd->page_infos, list, pi)
|
||||
{
|
||||
EINA_RECTANGLE_SET(&pi->geometry,
|
||||
pi->temp.x,
|
||||
pi->temp.y,
|
||||
pi->temp.w,
|
||||
pi->temp.h);
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static int
|
||||
_efl_page_transition_scroll_side_page_num_get(const Eo *obj EINA_UNUSED,
|
||||
Efl_Page_Transition_Scroll_Data *pd)
|
||||
{
|
||||
return pd->side_page_num;
|
||||
}
|
||||
|
||||
static Page_Info *
|
||||
_add_item(Efl_Page_Transition_Scroll_Data *pd, Efl_Page_Transition_Data *spd)
|
||||
{
|
||||
Page_Info *pi;
|
||||
|
||||
pi = calloc(1, sizeof(*pi));
|
||||
pi->obj = efl_add(EFL_UI_BOX_CLASS, spd->pager.obj);
|
||||
efl_canvas_group_member_add(spd->pager.group, pi->obj);
|
||||
pi->content_num = -1;
|
||||
pi->content = NULL;
|
||||
|
||||
pi->next = pd->head;
|
||||
pd->head->prev = pi;
|
||||
pi->prev = pd->tail;
|
||||
pd->tail->next = pi;
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
static void
|
||||
_remove_item(Page_Info *pi, Efl_Page_Transition_Scroll_Data *pd)
|
||||
{
|
||||
efl_canvas_object_clip_set(pi->content, pd->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);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_side_page_num_set(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd,
|
||||
int side_page_num)
|
||||
{
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
Page_Info *pi;
|
||||
int delta, i;
|
||||
|
||||
if (pd->side_page_num == side_page_num) return;
|
||||
|
||||
delta = side_page_num - pd->side_page_num;
|
||||
pd->side_page_num = side_page_num;
|
||||
pd->page_info_num = (side_page_num * 2) + 3;
|
||||
|
||||
if (!spd->pager.obj) return;
|
||||
|
||||
if (delta > 0)
|
||||
{
|
||||
// side_page_num is increased, so add boxes at both ends by the diff
|
||||
for (i = 0; i < delta; i++)
|
||||
{
|
||||
pi = _add_item(pd, spd);
|
||||
pd->page_infos = eina_list_prepend_relative(pd->page_infos, pi, pd->head);
|
||||
pd->head = pi;
|
||||
efl_gfx_stack_below(pi->obj, pi->next->obj);
|
||||
|
||||
pi = _add_item(pd, spd);
|
||||
pd->page_infos = eina_list_append_relative(pd->page_infos, pi, pd->tail);
|
||||
pd->tail = pi;
|
||||
efl_gfx_stack_above(pi->obj, pi->prev->obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// side_page_num is decreased, so remove boxes at both ends by the diff
|
||||
for (i = 0; i > delta; i--)
|
||||
{
|
||||
pi = pd->head;
|
||||
pd->head = pi->next;
|
||||
_remove_item(pi, pd);
|
||||
|
||||
pi = pd->tail;
|
||||
pd->tail = pi->prev;
|
||||
_remove_item(pi, pd);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
_page_info_geometry_change(pd, spd);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_loop_set(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd,
|
||||
Efl_Ui_Pager_Loop loop)
|
||||
{
|
||||
EFL_PAGE_TRANSITION_DATA_GET(obj, spd);
|
||||
|
||||
if (spd->loop == loop) return;
|
||||
|
||||
efl_page_transition_loop_set(efl_super(obj, MY_CLASS), loop);
|
||||
|
||||
_content_show(pd, spd);
|
||||
}
|
||||
|
||||
EOLIAN static Eo *
|
||||
_efl_page_transition_scroll_efl_object_constructor(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd)
|
||||
{
|
||||
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
||||
|
||||
pd->side_page_num = 1;
|
||||
pd->page_info_num = pd->side_page_num * 2 + 3;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_page_transition_scroll_efl_object_invalidate(Eo *obj,
|
||||
Efl_Page_Transition_Scroll_Data *pd)
|
||||
{
|
||||
Page_Info *pi;
|
||||
|
||||
EINA_LIST_FREE(pd->page_infos, pi)
|
||||
{
|
||||
efl_del(pi->obj);
|
||||
free(pi);
|
||||
}
|
||||
|
||||
efl_invalidate(efl_super(obj, MY_CLASS));
|
||||
}
|
||||
|
||||
|
||||
#define EFL_PAGE_TRANSITION_SCROLL_EXTRA_OPS \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_update, \
|
||||
_efl_page_transition_scroll_update), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_curr_page_change, \
|
||||
_efl_page_transition_scroll_curr_page_change), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_page_size_set, \
|
||||
_efl_page_transition_scroll_page_size_set), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_padding_size_set, \
|
||||
_efl_page_transition_scroll_padding_size_set), \
|
||||
EFL_OBJECT_OP_FUNC(efl_page_transition_loop_set, \
|
||||
_efl_page_transition_scroll_loop_set)
|
||||
|
||||
#include "efl_page_transition_scroll.eo.c"
|
|
@ -0,0 +1,22 @@
|
|||
class Efl.Page.Transition.Scroll (Efl.Page.Transition)
|
||||
{
|
||||
[[Page transition for @Efl.Ui.Pager
|
||||
|
||||
With this type of transition, pages are arranged linearly and move parallel
|
||||
to the screen by scrolling. The current page is displayed at center, and
|
||||
previous and next pages might be displayed optionally.
|
||||
]]
|
||||
methods {
|
||||
@property side_page_num {
|
||||
[[The number of pages displayed on each side of the current page]]
|
||||
values {
|
||||
side_page_num: int;
|
||||
}
|
||||
}
|
||||
}
|
||||
implements {
|
||||
Efl.Object.constructor;
|
||||
Efl.Object.invalidate;
|
||||
Efl.Page.Transition.bind;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef EFL_PAGE_TRANSITION_SCROLL_H
|
||||
#define EFL_PAGE_TRANSITION_SCROLL_H
|
||||
|
||||
//#include "efl_ui_widget_pager.h"
|
||||
|
||||
|
||||
/**
|
||||
* This is a description on how scroll transition works.
|
||||
*
|
||||
* Regardless of the number of pages, scroll transition maintains a fixed number
|
||||
* of boxes which can contain pages. The boxes move along with scrolling and
|
||||
* some of them are emptied or filled as they come in or out of screen area.
|
||||
* When pager is scrolled left or right, each box takes the position of its
|
||||
* previous or next box. Since the leftmost and rightmost boxes might move in
|
||||
* reverse direction, they shouldn't be visible. This is why there are dummy
|
||||
* boxes at both ends.
|
||||
*
|
||||
* Here is an example of box arrangement change by scrolling.
|
||||
* The pager has 10 pages, numbered from 1 to 10.
|
||||
* The current page is page5, and side_page_num equals 1.
|
||||
*
|
||||
* head |----- screen area ----| tail
|
||||
* (dummy) | | (dummy)
|
||||
* ---------- ---------- ---------- ---------- ----------
|
||||
* | BOX1 | | BOX2 | | BOX3 | | BOX4 | | BOX5 |
|
||||
* | | | | | | | | | |
|
||||
* | (empty)| | page4 | | page5 | | page6 | | (empty)|
|
||||
* | | | | | | | | | |
|
||||
* | | | | | | | | | |
|
||||
* | | | | | | | | | |
|
||||
* ---------- ---------- ---------- ---------- ----------
|
||||
* | |
|
||||
* |----------------------|
|
||||
*
|
||||
* After scrolling left,
|
||||
* 1. each box takes the position of it's previous box.
|
||||
* 2. head and tail is changed.
|
||||
* 3. The box moved to the end is emptied.
|
||||
* 4. The box moved from the end is filled with content.
|
||||
*
|
||||
* head tail
|
||||
* ---------- ---------- ---------- ---------- ----------
|
||||
* | BOX2 | | BOX3 | | BOX4 | | BOX5 | | BOX1 |
|
||||
* | | | | | | | | | |
|
||||
* | (empty)| | page5 | | page6 | | page7 | | (empty)|
|
||||
* |*emptied| | | | | |*filled | | |
|
||||
* | | | | | | | | | |
|
||||
* | | | | | | | | | |
|
||||
* ---------- ---------- ---------- ---------- ----------
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
typedef struct _Page_Info
|
||||
{
|
||||
Evas_Map *map;
|
||||
int id;
|
||||
int pos;
|
||||
int content_num;
|
||||
Eo *obj;
|
||||
Eo *content;
|
||||
|
||||
Eina_Rectangle geometry;
|
||||
Eina_Rectangle temp;
|
||||
|
||||
struct _Page_Info *prev, *next;
|
||||
|
||||
Eina_Bool visible;
|
||||
Eina_Bool vis_page;
|
||||
|
||||
} Page_Info;
|
||||
|
||||
typedef struct _Efl_Page_Transition_Scroll_Data Efl_Page_Transition_Scroll_Data;
|
||||
|
||||
struct _Efl_Page_Transition_Scroll_Data
|
||||
{
|
||||
Eina_List *page_infos;
|
||||
|
||||
Page_Info *head, *tail;
|
||||
|
||||
int page_info_num;
|
||||
int side_page_num;
|
||||
|
||||
Eo *foreclip;
|
||||
Eo *backclip;
|
||||
Eina_Rectangle viewport;
|
||||
};
|
||||
|
||||
#define EFL_PAGE_TRANSITION_SCROLL_DATA_GET(o, pd) \
|
||||
Efl_Page_Transition_Scroll_Data *pd = \
|
||||
efl_data_scope_get(o, EFL_PAGE_TRANSITION_SCROLL_CLASS)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,811 @@
|
|||
#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
|
||||
|
||||
|
||||
static void
|
||||
_efl_ui_pager_update(Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
if (pd->cnt == 0) return;
|
||||
|
||||
efl_page_transition_update(pd->transition, pd->curr.pos);
|
||||
if (pd->indicator)
|
||||
efl_page_indicator_update(pd->indicator, pd->curr.pos);
|
||||
}
|
||||
|
||||
static void
|
||||
_job(void *data)
|
||||
{
|
||||
Evas_Object *obj = data;
|
||||
EFL_UI_PAGER_DATA_GET(obj, pd);
|
||||
|
||||
int prev_page, page_diff;
|
||||
double prev_pos, pos_diff;
|
||||
|
||||
prev_page = pd->curr.page;
|
||||
prev_pos = pd->curr.pos;
|
||||
|
||||
pd->job = NULL;
|
||||
|
||||
pos_diff = ((double) pd->down.x - (double) pd->mouse_x) / (double) pd->w;
|
||||
pd->curr.pos = pd->down.pos + pos_diff;
|
||||
page_diff = (int) pd->curr.pos;
|
||||
|
||||
//FIXME what if (prev_pos != 0.0)
|
||||
if ((pd->loop == EFL_UI_PAGER_LOOP_DISABLED) &&
|
||||
(((prev_page == 0) && (pd->curr.pos < 0)) ||
|
||||
((prev_page == (pd->cnt - 1)) && (pd->curr.pos > 0))))
|
||||
{
|
||||
pd->curr.page = prev_page;
|
||||
pd->curr.pos = prev_pos;
|
||||
return;
|
||||
}
|
||||
|
||||
pd->curr.page = (pd->down.page + page_diff + pd->cnt) % pd->cnt;
|
||||
pd->curr.pos -= page_diff;
|
||||
|
||||
//FIXME what if (page_diff >= 2 || page_diff <= -2)
|
||||
if (page_diff != 0)
|
||||
{
|
||||
pd->down.x = pd->mouse_x;
|
||||
pd->down.y = pd->mouse_y;
|
||||
pd->down.page = pd->curr.page;
|
||||
pd->down.pos = pd->curr.pos;
|
||||
|
||||
efl_page_transition_curr_page_change(pd->transition, page_diff);
|
||||
}
|
||||
|
||||
_efl_ui_pager_update(pd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
_page_set_animation(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Ui_Pager_Data *pd = data;
|
||||
double p = ecore_loop_time_get() - pd->change.start_time;
|
||||
double d, temp_pos;
|
||||
int temp_page;
|
||||
|
||||
if (p >= 1.0) p = 1.0;
|
||||
p = ecore_animator_pos_map(p, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
|
||||
|
||||
d = pd->change.src + pd->change.delta * p;
|
||||
temp_page = d;
|
||||
temp_pos = d - temp_page;
|
||||
|
||||
if ((temp_page < pd->curr.page) && (fabs(pd->curr.page - d) < 1.0))
|
||||
{
|
||||
temp_page += 1;
|
||||
temp_pos -= 1.0;
|
||||
}
|
||||
|
||||
if (pd->curr.page != temp_page)
|
||||
{
|
||||
if (pd->change.delta < 0)
|
||||
efl_page_transition_curr_page_change(pd->transition, -1.0);
|
||||
else
|
||||
efl_page_transition_curr_page_change(pd->transition, 1.0);
|
||||
temp_pos = 0.0;
|
||||
}
|
||||
|
||||
pd->curr.page = temp_page;
|
||||
pd->curr.pos = temp_pos;
|
||||
|
||||
ERR("page %d pos %lf", pd->curr.page, pd->curr.pos);
|
||||
|
||||
_efl_ui_pager_update(pd);
|
||||
|
||||
if (EINA_DBL_EQ(p, 1.0))
|
||||
efl_event_callback_del(event->object, EFL_EVENT_ANIMATOR_TICK,
|
||||
_page_set_animation, pd);
|
||||
}
|
||||
|
||||
static void
|
||||
_mouse_up_animation(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Ui_Pager_Data *pd = data;
|
||||
double p = ecore_loop_time_get() - pd->mouse_up_time;
|
||||
|
||||
if (p >= 1.0) p = 1.0;
|
||||
p = ecore_animator_pos_map(p, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
|
||||
|
||||
if (pd->curr.pos < 0.0)
|
||||
{
|
||||
if (pd->curr.pos > -0.5)
|
||||
pd->curr.pos = pd->curr.pos * (1 - p);
|
||||
else
|
||||
pd->curr.pos = (-1) - (-1 - pd->curr.pos) * (1 - p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pd->curr.pos < 0.5)
|
||||
pd->curr.pos = pd->curr.pos * (1 - p);
|
||||
else
|
||||
pd->curr.pos = 1 - (1 - pd->curr.pos) * (1 - p);
|
||||
}
|
||||
|
||||
if (EINA_DBL_EQ(pd->curr.pos, 1.0))
|
||||
{
|
||||
efl_page_transition_curr_page_change(pd->transition, 1.0);
|
||||
pd->curr.page = (pd->curr.page + 1 + pd->cnt) % pd->cnt;
|
||||
pd->curr.pos = 0.0;
|
||||
}
|
||||
else if (EINA_DBL_EQ(pd->curr.pos, -1.0))
|
||||
{
|
||||
efl_page_transition_curr_page_change(pd->transition, -1.0);
|
||||
pd->curr.page = (pd->curr.page - 1 + pd->cnt) % pd->cnt;
|
||||
pd->curr.pos = 0.0;
|
||||
}
|
||||
|
||||
_efl_ui_pager_update(pd);
|
||||
|
||||
if (EINA_DBL_EQ(p, 1.0))
|
||||
efl_event_callback_del(event->object, EFL_EVENT_ANIMATOR_TICK,
|
||||
_mouse_up_animation, pd);
|
||||
}
|
||||
|
||||
static void
|
||||
_mouse_down_cb(void *data,
|
||||
const Efl_Event *event)
|
||||
{
|
||||
Efl_Input_Pointer *ev = event->info;
|
||||
Eo *obj = data;
|
||||
EFL_UI_PAGER_DATA_GET(obj, pd);
|
||||
Eina_Position2D pos;
|
||||
|
||||
if (efl_input_pointer_button_get(ev) != 1) return;
|
||||
if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
|
||||
|
||||
efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _mouse_up_animation, pd);
|
||||
efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _page_set_animation, pd);
|
||||
|
||||
pd->move_started = EINA_FALSE;
|
||||
|
||||
pos = efl_input_pointer_position_get(ev);
|
||||
pd->mouse_x = pos.x - pd->x;
|
||||
pd->mouse_y = pos.y - pd->y;
|
||||
|
||||
pd->down.enabled = EINA_TRUE;
|
||||
pd->down.x = pd->mouse_x;
|
||||
pd->down.y = pd->mouse_y;
|
||||
pd->down.page = pd->curr.page;
|
||||
pd->down.pos = pd->curr.pos;
|
||||
}
|
||||
|
||||
static void
|
||||
_mouse_move_cb(void *data,
|
||||
const Efl_Event *event)
|
||||
{
|
||||
Efl_Input_Pointer *ev = event->info;
|
||||
Eo *obj = data;
|
||||
EFL_UI_PAGER_DATA_GET(obj, pd);
|
||||
Eina_Position2D pos;
|
||||
|
||||
if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
|
||||
if (!pd->down.enabled) return;
|
||||
|
||||
pos = efl_input_pointer_position_get(ev);
|
||||
|
||||
if (pd->prev_block && (pd->mouse_x < (pos.x - pd->x))) return;
|
||||
if (pd->next_block && (pd->mouse_x > (pos.x - pd->x))) return;
|
||||
|
||||
pd->mouse_x = pos.x - pd->x;
|
||||
pd->mouse_y = pos.y - pd->y;
|
||||
|
||||
if (!pd->move_started)
|
||||
{
|
||||
Evas_Coord dx, dy;
|
||||
dx = pd->mouse_x - pd->down.x;
|
||||
dy = pd->mouse_y - pd->down.y;
|
||||
|
||||
if (((dx * dx) + (dy * dy)) <=
|
||||
(_elm_config->finger_size * _elm_config->finger_size / 4))
|
||||
return;
|
||||
|
||||
pd->move_started = EINA_TRUE;
|
||||
}
|
||||
|
||||
ecore_job_del(pd->job);
|
||||
pd->job = ecore_job_add(_job, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
_mouse_up_cb(void *data,
|
||||
const Efl_Event *event)
|
||||
{
|
||||
Efl_Input_Pointer *ev = event->info;
|
||||
Eo *obj = data;
|
||||
EFL_UI_PAGER_DATA_GET(obj, pd);
|
||||
|
||||
if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
|
||||
if (!pd->down.enabled) return;
|
||||
|
||||
pd->down.enabled = EINA_FALSE;
|
||||
|
||||
ELM_SAFE_FREE(pd->job, ecore_job_del);
|
||||
|
||||
if (EINA_DBL_EQ(pd->curr.pos, 0.0)) return;
|
||||
|
||||
pd->mouse_up_time = ecore_loop_time_get();
|
||||
|
||||
efl_event_callback_add(obj, EFL_EVENT_ANIMATOR_TICK, _mouse_up_animation, pd);
|
||||
}
|
||||
|
||||
//FIXME sub_object_parent_add? destruction
|
||||
static void
|
||||
_event_handler_create(Eo *obj, Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
pd->event = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
|
||||
evas_object_evas_get(obj));
|
||||
evas_object_color_set(pd->event, 0, 0, 0, 0);
|
||||
evas_object_repeat_events_set(pd->event, EINA_TRUE);
|
||||
|
||||
efl_content_set(efl_part(obj, "event"), pd->event);
|
||||
|
||||
efl_event_callback_add(pd->event, EFL_EVENT_POINTER_DOWN,
|
||||
_mouse_down_cb, obj);
|
||||
efl_event_callback_add(pd->event, EFL_EVENT_POINTER_UP,
|
||||
_mouse_up_cb, obj);
|
||||
efl_event_callback_add(pd->event, EFL_EVENT_POINTER_MOVE,
|
||||
_mouse_move_cb, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
_event_handler_del(Eo *obj, Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
efl_content_unset(efl_part(obj, "event"));
|
||||
efl_del(pd->event);
|
||||
pd->event = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_resize_cb(void *data, const Efl_Event *ev)
|
||||
{
|
||||
Efl_Ui_Pager_Data *pd = data;
|
||||
Eina_Size2D sz;
|
||||
|
||||
sz = efl_gfx_size_get(ev->object);
|
||||
|
||||
pd->w = sz.w;
|
||||
pd->h = sz.h;
|
||||
|
||||
if (pd->fill_width) pd->page_spec.sz.w = pd->w;
|
||||
if (pd->fill_height) pd->page_spec.sz.h = pd->h;
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_page_size_set(pd->transition, pd->page_spec.sz);
|
||||
else
|
||||
{
|
||||
efl_gfx_size_set(pd->foreclip, sz);
|
||||
efl_gfx_size_set(pd->page_box, pd->page_spec.sz);
|
||||
efl_gfx_position_set(pd->page_box,
|
||||
EINA_POSITION2D(pd->x + (pd->w / 2) - (pd->page_spec.sz.w / 2),
|
||||
pd->y + (pd->h / 2) - (pd->page_spec.sz.h / 2)));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_move_cb(void *data, const Efl_Event *ev)
|
||||
{
|
||||
Efl_Ui_Pager_Data *pd = data;
|
||||
Eina_Position2D pos;
|
||||
|
||||
pos = efl_gfx_position_get(ev->object);
|
||||
|
||||
pd->x = pos.x;
|
||||
pd->y = pos.y;
|
||||
|
||||
if (!pd->transition)
|
||||
{
|
||||
efl_gfx_position_set(pd->foreclip, pos);
|
||||
efl_gfx_position_set(pd->page_box,
|
||||
EINA_POSITION2D(pd->x + (pd->w / 2) - (pd->page_spec.sz.w / 2),
|
||||
pd->y + (pd->h / 2) - (pd->page_spec.sz.h / 2)));
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static Eo *
|
||||
_efl_ui_pager_efl_object_constructor(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
|
||||
|
||||
if (!elm_widget_theme_klass_get(obj))
|
||||
elm_widget_theme_klass_set(obj, "pager");
|
||||
|
||||
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
||||
|
||||
if (!elm_widget_theme_object_set(obj, wd->resize_obj,
|
||||
elm_widget_theme_klass_get(obj),
|
||||
elm_widget_theme_element_get(obj),
|
||||
elm_widget_theme_style_get(obj)))
|
||||
CRI("Failed to set layout!");
|
||||
|
||||
elm_widget_sub_object_parent_add(obj);
|
||||
|
||||
pd->cnt = 0;
|
||||
pd->loop = EFL_UI_PAGER_LOOP_DISABLED;
|
||||
|
||||
pd->curr.page = 0;
|
||||
pd->curr.pos = 0.0;
|
||||
|
||||
pd->transition = NULL;
|
||||
pd->indicator = NULL;
|
||||
|
||||
pd->fill_width = EINA_TRUE;
|
||||
pd->fill_height = EINA_TRUE;
|
||||
|
||||
pd->page_spec.sz.w = -1;
|
||||
pd->page_spec.sz.h = -1;
|
||||
|
||||
elm_widget_can_focus_set(obj, EINA_TRUE);
|
||||
|
||||
pd->page_root = efl_add(EFL_CANVAS_GROUP_CLASS, evas_object_evas_get(obj));
|
||||
efl_content_set(efl_part(obj, "page_root"), pd->page_root);
|
||||
|
||||
efl_event_callback_add(pd->page_root, EFL_GFX_EVENT_RESIZE, _resize_cb, pd);
|
||||
efl_event_callback_add(pd->page_root, EFL_GFX_EVENT_MOVE, _move_cb, pd);
|
||||
|
||||
pd->page_box = efl_add(EFL_UI_BOX_CLASS, obj);
|
||||
efl_canvas_group_member_add(pd->page_root, pd->page_box);
|
||||
|
||||
pd->foreclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
|
||||
evas_object_evas_get(obj));
|
||||
efl_canvas_group_member_add(pd->page_root, pd->foreclip);
|
||||
evas_object_static_clip_set(pd->foreclip, EINA_TRUE);
|
||||
efl_canvas_object_clip_set(pd->page_box, pd->foreclip);
|
||||
|
||||
pd->backclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
|
||||
evas_object_evas_get(obj));
|
||||
efl_canvas_group_member_add(pd->page_root, pd->backclip);
|
||||
evas_object_static_clip_set(pd->backclip, EINA_TRUE);
|
||||
efl_gfx_visible_set(pd->backclip, EINA_FALSE);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
EOLIAN static int
|
||||
_efl_ui_pager_efl_container_content_count(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
return pd->cnt;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_linear_pack_begin(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Gfx *subobj)
|
||||
{
|
||||
efl_parent_set(subobj, obj);
|
||||
elm_widget_sub_object_add(obj, subobj);
|
||||
|
||||
pd->content_list = eina_list_prepend(pd->content_list, subobj);
|
||||
|
||||
pd->cnt += 1;
|
||||
pd->curr.page += 1;
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_update(pd->transition, pd->curr.pos);
|
||||
else
|
||||
{
|
||||
if (pd->cnt == 1)
|
||||
efl_pack(pd->page_box, subobj);
|
||||
else efl_canvas_object_clip_set(subobj, pd->backclip);
|
||||
}
|
||||
|
||||
if (pd->indicator)
|
||||
{
|
||||
efl_page_indicator_pack(pd->indicator, 0);
|
||||
efl_page_indicator_update(pd->indicator, pd->curr.pos);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_linear_pack_end(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Gfx *subobj)
|
||||
{
|
||||
efl_parent_set(subobj, obj);
|
||||
elm_widget_sub_object_add(obj, subobj);
|
||||
|
||||
pd->content_list = eina_list_append(pd->content_list, subobj);
|
||||
|
||||
pd->cnt += 1;
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_update(pd->transition, pd->curr.pos);
|
||||
else
|
||||
{
|
||||
if (pd->cnt == 1)
|
||||
efl_pack(pd->page_box, subobj);
|
||||
else efl_canvas_object_clip_set(subobj, pd->backclip);
|
||||
}
|
||||
|
||||
if (pd->indicator)
|
||||
{
|
||||
efl_page_indicator_pack(pd->indicator, (pd->cnt - 1));
|
||||
efl_page_indicator_update(pd->indicator, pd->curr.pos);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_linear_pack_before(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Gfx *subobj,
|
||||
const Efl_Gfx *existing)
|
||||
{
|
||||
int index;
|
||||
|
||||
efl_parent_set(subobj, obj);
|
||||
elm_widget_sub_object_add(obj, subobj);
|
||||
|
||||
index = eina_list_data_idx(pd->content_list, (void *)existing);
|
||||
pd->content_list = eina_list_prepend_relative(pd->content_list, subobj, existing);
|
||||
|
||||
pd->cnt += 1;
|
||||
if (pd->curr.page >= index) pd->curr.page += 1;
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_update(pd->transition, pd->curr.pos);
|
||||
else efl_canvas_object_clip_set(subobj, pd->backclip);
|
||||
|
||||
if (pd->indicator)
|
||||
{
|
||||
efl_page_indicator_pack(pd->indicator, index);
|
||||
efl_page_indicator_update(pd->indicator, pd->curr.pos);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_linear_pack_after(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Gfx *subobj,
|
||||
const Efl_Gfx *existing)
|
||||
{
|
||||
int index;
|
||||
|
||||
efl_parent_set(subobj, obj);
|
||||
elm_widget_sub_object_add(obj, subobj);
|
||||
|
||||
index = eina_list_data_idx(pd->content_list, (void *)existing);
|
||||
pd->content_list = eina_list_append_relative(pd->content_list, subobj, existing);
|
||||
|
||||
pd->cnt += 1;
|
||||
if (pd->curr.page > index) pd->curr.page += 1;
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_update(pd->transition, pd->curr.pos);
|
||||
else efl_canvas_object_clip_set(subobj, pd->backclip);
|
||||
|
||||
if (pd->indicator)
|
||||
{
|
||||
efl_page_indicator_pack(pd->indicator, (index + 1));
|
||||
efl_page_indicator_update(pd->indicator, pd->curr.pos);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_linear_pack_at(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Gfx *subobj,
|
||||
int index)
|
||||
{
|
||||
Efl_Gfx *existing = NULL;
|
||||
|
||||
efl_parent_set(subobj, obj);
|
||||
elm_widget_sub_object_add(obj, subobj);
|
||||
|
||||
existing = eina_list_nth(pd->content_list, index);
|
||||
pd->content_list = eina_list_prepend_relative(pd->content_list, subobj, existing);
|
||||
|
||||
pd->cnt += 1;
|
||||
if (pd->curr.page >= index) pd->curr.page += 1;
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_update(pd->transition, pd->curr.pos);
|
||||
else efl_canvas_object_clip_set(subobj, pd->backclip);
|
||||
|
||||
if (pd->indicator)
|
||||
{
|
||||
efl_page_indicator_pack(pd->indicator, index);
|
||||
efl_page_indicator_update(pd->indicator, pd->curr.pos);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_current_page_set(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
int index)
|
||||
{
|
||||
if (index == pd->curr.page) return;
|
||||
|
||||
efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _mouse_up_animation, pd);
|
||||
efl_event_callback_del(obj, EFL_EVENT_ANIMATOR_TICK, _page_set_animation, pd);
|
||||
|
||||
if (index >= pd->cnt)
|
||||
{
|
||||
ERR("page set fail");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pd->transition)
|
||||
{
|
||||
Eo *curr;
|
||||
|
||||
curr = eina_list_nth(pd->content_list, pd->curr.page);
|
||||
efl_pack_unpack(pd->page_box, curr);
|
||||
efl_canvas_object_clip_set(curr, pd->backclip);
|
||||
|
||||
pd->curr.page = index;
|
||||
curr = eina_list_nth(pd->content_list, pd->curr.page);
|
||||
efl_pack(pd->page_box, curr);
|
||||
|
||||
if (pd->indicator)
|
||||
efl_page_indicator_update(pd->indicator, pd->curr.pos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pd->change.src = pd->curr.page + pd->curr.pos;
|
||||
pd->change.delta = index - pd->change.src;
|
||||
|
||||
if (pd->change.delta == 0) return;
|
||||
|
||||
pd->change.start_time = ecore_loop_time_get();
|
||||
efl_event_callback_add(obj, EFL_EVENT_ANIMATOR_TICK, _page_set_animation, pd);
|
||||
}
|
||||
|
||||
EOLIAN static int
|
||||
_efl_ui_pager_current_page_get(const Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
return pd->curr.page;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_transition_set(Eo *obj,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Page_Transition *transition)
|
||||
{
|
||||
if (pd->transition == transition) return;
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_bind(pd->transition, NULL, NULL);
|
||||
else
|
||||
{
|
||||
Eo *curr;
|
||||
|
||||
curr = eina_list_nth(pd->content_list, pd->curr.page);
|
||||
efl_pack_unpack(pd->page_box, curr);
|
||||
efl_canvas_object_clip_set(pd->page_box, pd->backclip);
|
||||
}
|
||||
|
||||
pd->transition = transition;
|
||||
|
||||
if (pd->transition)
|
||||
{
|
||||
if (!pd->event) _event_handler_create(obj, pd);
|
||||
efl_page_transition_bind(pd->transition, obj, pd->page_root);
|
||||
}
|
||||
else
|
||||
{
|
||||
Eina_List *list;
|
||||
Eo *curr;
|
||||
|
||||
_event_handler_del(obj, pd);
|
||||
|
||||
efl_canvas_object_clip_set(pd->page_box, pd->foreclip);
|
||||
|
||||
EINA_LIST_FOREACH(pd->content_list, list, curr)
|
||||
{
|
||||
efl_canvas_object_clip_set(curr, pd->backclip);
|
||||
}
|
||||
|
||||
curr = eina_list_nth(pd->content_list, pd->curr.page);
|
||||
efl_pack(pd->page_box, curr);
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_indicator_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Page_Indicator *indicator)
|
||||
{
|
||||
if (pd->indicator == indicator) return;
|
||||
|
||||
if (pd->indicator)
|
||||
{
|
||||
efl_page_indicator_bind(pd->indicator, NULL, NULL);
|
||||
pd->indicator = NULL;
|
||||
}
|
||||
|
||||
pd->indicator = indicator;
|
||||
|
||||
if (!pd->indicator)
|
||||
{
|
||||
if (pd->idbox)
|
||||
{
|
||||
efl_del(pd->idbox);
|
||||
pd->idbox = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pd->idbox)
|
||||
{
|
||||
pd->idbox = efl_add(EFL_UI_BOX_CLASS, obj);
|
||||
efl_content_set(efl_part(obj, "indicator"), pd->idbox);
|
||||
}
|
||||
|
||||
efl_page_indicator_bind(pd->indicator, obj, pd->idbox);
|
||||
}
|
||||
|
||||
EOLIAN Eina_Size2D
|
||||
_efl_ui_pager_page_size_get(const Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
return pd->page_spec.sz;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_page_size_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Eina_Size2D sz)
|
||||
{
|
||||
if (sz.w < -1 || sz.h < -1) return;
|
||||
|
||||
if (sz.w == -1)
|
||||
{
|
||||
pd->fill_width = EINA_TRUE;
|
||||
pd->page_spec.sz.w = pd->w;
|
||||
}
|
||||
else
|
||||
{
|
||||
pd->fill_width = EINA_FALSE;
|
||||
pd->page_spec.sz.w = sz.w;
|
||||
}
|
||||
if (sz.h == -1)
|
||||
{
|
||||
pd->fill_height = EINA_TRUE;
|
||||
pd->page_spec.sz.h = pd->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
pd->fill_height = EINA_FALSE;
|
||||
pd->page_spec.sz.h = sz.h;
|
||||
}
|
||||
|
||||
if (pd->transition)
|
||||
efl_page_transition_page_size_set(pd->transition, pd->page_spec.sz);
|
||||
else
|
||||
efl_gfx_size_set(pd->page_box, pd->page_spec.sz);
|
||||
}
|
||||
|
||||
EOLIAN static int
|
||||
_efl_ui_pager_padding_get(const Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
return pd->page_spec.padding;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_padding_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
int padding)
|
||||
{
|
||||
pd->page_spec.padding = padding;
|
||||
|
||||
efl_page_transition_padding_size_set(pd->transition, padding);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_scroll_block_get(const Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Eina_Bool *prev,
|
||||
Eina_Bool *next)
|
||||
{
|
||||
if (prev) *prev = pd->prev_block;
|
||||
if (next) *next = pd->next_block;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_scroll_block_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Eina_Bool prev,
|
||||
Eina_Bool next)
|
||||
{
|
||||
pd->prev_block = prev;
|
||||
pd->next_block = next;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_ui_pager_loop_mode_set(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd,
|
||||
Efl_Ui_Pager_Loop loop)
|
||||
{
|
||||
pd->loop = loop;
|
||||
|
||||
efl_page_transition_loop_set(pd->transition, loop);
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Ui_Pager_Loop
|
||||
_efl_ui_pager_loop_mode_get(const Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd)
|
||||
{
|
||||
return pd->loop;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_pack_clear(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd EINA_UNUSED)
|
||||
{
|
||||
ERR("Soon to be implemented");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_unpack_all(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd EINA_UNUSED)
|
||||
{
|
||||
ERR("Soon to be implemented");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_ui_pager_efl_pack_unpack(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd EINA_UNUSED,
|
||||
Efl_Gfx *subobj EINA_UNUSED)
|
||||
{
|
||||
ERR("Soon to be implemented");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Gfx *
|
||||
_efl_ui_pager_efl_pack_linear_pack_unpack_at(Eo *obj EINA_UNUSED,
|
||||
Efl_Ui_Pager_Data *pd EINA_UNUSED,
|
||||
int index EINA_UNUSED)
|
||||
{
|
||||
ERR("Soon to be implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "efl_ui_pager.eo.c"
|
|
@ -0,0 +1,101 @@
|
|||
enum Efl.Ui.Pager.Loop
|
||||
{
|
||||
[[Efl ui pager loop mode]]
|
||||
disabled,
|
||||
enabled
|
||||
}
|
||||
|
||||
class Efl.Ui.Pager (Efl.Ui.Layout, Efl.Pack.Linear)
|
||||
{
|
||||
[[Pager widget
|
||||
|
||||
A pager contains many pages in a linear fashion and allows users to scroll
|
||||
through pages. Each page is numbered according to linear order and
|
||||
one of the pages is marked as 'current page' and displayed in the middle.
|
||||
The way each page is displayed is defined by @Efl.Page.Transition object,
|
||||
allowing users to adopt different types of transition.
|
||||
The most common use case of this widget is the home screen of mobile devices.
|
||||
]]
|
||||
methods {
|
||||
@property transition {
|
||||
[[Page transition effect
|
||||
|
||||
Page transition is in charge of displaying pages in a specific way and
|
||||
invoked every time page layout needs to be updated.
|
||||
]]
|
||||
set {
|
||||
[[Set a page transition effect]]
|
||||
}
|
||||
values {
|
||||
transition: Efl.Page.Transition @nullable; [[transition effect]]
|
||||
}
|
||||
}
|
||||
@property indicator {
|
||||
[[Page indicator
|
||||
|
||||
Page indicator, located on the top layer of pager widget, helps users
|
||||
to know the number of pages and the current page's index without scrolling.
|
||||
]]
|
||||
set {
|
||||
[[Set a page indicator]]
|
||||
}
|
||||
values {
|
||||
indicator: Efl.Page.Indicator @nullable; [[indicator class]]
|
||||
}
|
||||
}
|
||||
@property current_page {
|
||||
[[One page is selected as the current page and mainly displayed.]]
|
||||
set {
|
||||
[[Set one page as current page]]
|
||||
}
|
||||
get {
|
||||
[[Get the current page]]
|
||||
}
|
||||
values {
|
||||
index: int;
|
||||
}
|
||||
}
|
||||
@property scroll_block {
|
||||
[[Pages can be scrolled back and forth by default. This property allows
|
||||
limiting the direction of scrolling, or blocking scroll gesture at all.
|
||||
]]
|
||||
values {
|
||||
prev: bool;
|
||||
next: bool;
|
||||
}
|
||||
}
|
||||
@property loop_mode {
|
||||
[[Pager is not scrolled after it's scrolled to the end by default.
|
||||
This property gives the option to make a loop through pages.
|
||||
]]
|
||||
values {
|
||||
loop: Efl.Ui.Pager.Loop;
|
||||
}
|
||||
}
|
||||
@property page_size {
|
||||
values {
|
||||
size: Eina.Size2D;
|
||||
}
|
||||
}
|
||||
@property padding {
|
||||
values {
|
||||
padding: int;
|
||||
}
|
||||
}
|
||||
}
|
||||
implements {
|
||||
Efl.Object.constructor;
|
||||
Efl.Container.content_count;
|
||||
Efl.Pack.pack_clear; //TODO
|
||||
Efl.Pack.unpack_all; //TODO
|
||||
Efl.Pack.unpack; //TODO
|
||||
Efl.Pack.Linear.pack_begin;
|
||||
Efl.Pack.Linear.pack_end;
|
||||
Efl.Pack.Linear.pack_before;
|
||||
Efl.Pack.Linear.pack_after;
|
||||
Efl.Pack.Linear.pack_at;
|
||||
Efl.Pack.Linear.pack_content_get;
|
||||
Efl.Pack.Linear.pack_index_get;
|
||||
Efl.Pack.Linear.pack_unpack_at; //TODO
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef EFL_UI_WIDGET_PAGER_H
|
||||
#define EFL_UI_WIDGET_PAGER_H
|
||||
|
||||
|
||||
#include <Elementary.h>
|
||||
|
||||
#include "efl_page_transition.h"
|
||||
|
||||
typedef struct _Efl_Ui_Pager_Data
|
||||
{
|
||||
Eina_List *page_infos;
|
||||
Eina_List *content_list;
|
||||
|
||||
Efl_Ui_Box *page_box;
|
||||
Eo *foreclip;
|
||||
Eo *backclip;
|
||||
|
||||
Eo *page_root;
|
||||
Eo *event;
|
||||
Efl_Ui_Box *idbox;
|
||||
Ecore_Job *job;
|
||||
Ecore_Job *page_info_job;
|
||||
|
||||
Evas_Coord x, y, w, h;
|
||||
Evas_Coord mouse_x, mouse_y;
|
||||
|
||||
struct {
|
||||
Eina_Size2D sz;
|
||||
Evas_Coord padding;
|
||||
} page_spec;
|
||||
|
||||
struct {
|
||||
Evas_Coord x, y;
|
||||
int page;
|
||||
double pos;
|
||||
Eina_Bool enabled;
|
||||
} down;
|
||||
|
||||
struct {
|
||||
int page;
|
||||
double pos;
|
||||
} curr;
|
||||
|
||||
struct {
|
||||
double src;
|
||||
double delta;
|
||||
double start_time;
|
||||
Eina_Bool jump;
|
||||
} change;
|
||||
|
||||
int cnt;
|
||||
double mouse_up_time;
|
||||
|
||||
Efl_Ui_Pager_Loop loop;
|
||||
Efl_Page_Transition *transition;
|
||||
Efl_Page_Indicator *indicator;
|
||||
|
||||
Eina_Bool move_started : 1;
|
||||
Eina_Bool prev_block : 1;
|
||||
Eina_Bool next_block: 1;
|
||||
Eina_Bool fill_width: 1;
|
||||
Eina_Bool fill_height: 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
|
|
@ -731,6 +731,16 @@ void *_elm_icon_signal_callback_del(Evas_Object *obj,
|
|||
/* DO NOT USE THIS this is only for performance optimization! */
|
||||
void _elm_widget_full_eval(Eo *obj);
|
||||
|
||||
EOAPI void efl_page_transition_page_size_set(Eo *obj, Eina_Size2D sz);
|
||||
EOAPI void efl_page_transition_padding_size_set(Eo *obj, int padding);
|
||||
EOAPI void efl_page_transition_update(Eo *obj, double pos);
|
||||
EOAPI void efl_page_transition_curr_page_change(Eo *obj, double move);
|
||||
EOAPI void efl_page_transition_pack_end(Eo *obj, Efl_Gfx *subobj);
|
||||
EOAPI void efl_page_transition_loop_set(Eo *obj, Efl_Ui_Pager_Loop loop);
|
||||
|
||||
EOAPI void efl_page_indicator_update(Eo *obj, double pos);
|
||||
EOAPI void efl_page_indicator_pack(Eo *obj, int index);
|
||||
|
||||
Eina_Bool _elm_config_accel_preference_parse(const char *pref, Eina_Stringshare **accel, int *gl_depth, int *gl_stencil, int *gl_msaa);
|
||||
|
||||
extern char *_elm_appname;
|
||||
|
|
Loading…
Reference in New Issue