efl_ui_active_view: introduce a experimental new widget

this widget tries to replace efl.ui.stack efl.ui.flip & efl.ui.pager
In general those widgets do the same thing, they get content. And
display them with some sort of animations. The new idea here is, that
the basic widget active_view only handles the ownership etc. of the
content that gets added to this. Then there is a view_manager object. The
view_manager object gets notified over the new contents, and requests for
displaying particular contents. The transition then handles those
things.

The version here is feature complete with Efl.Ui.Stack and Efl.Ui.Pager.
Additional features can be implemented in the corresponsing transition
classes. Examples and tests will follow

Reviewed-by: Jaehyun Cho <jae_hyun.cho@samsung.com>
Reviewed-by: Cedric BAIL <cedric.bail@free.fr>
Differential Revision: https://phab.enlightenment.org/D8784
This commit is contained in:
Marcel Hollerbach 2019-04-28 12:28:55 +02:00
parent cdfcd02886
commit 79fe0121ee
28 changed files with 3596 additions and 4 deletions

View File

@ -119,6 +119,13 @@ elm_public_eolian_files = \
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_ui_active_view_container.eo \
lib/elementary/efl_ui_active_view_view_manager.eo \
lib/elementary/efl_ui_active_view_view_manager_plain.eo \
lib/elementary/efl_ui_active_view_view_manager_scroll.eo \
lib/elementary/efl_ui_active_view_view_manager_stack.eo \
lib/elementary/efl_ui_active_view_indicator.eo \
lib/elementary/efl_ui_active_view_indicator_icon.eo \
lib/elementary/efl_page_transition.eo \
lib/elementary/efl_page_transition_scroll.eo \
lib/elementary/efl_page_indicator.eo \
@ -1197,6 +1204,13 @@ lib_elementary_libelementary_la_SOURCES = \
static_libs/buildsystem/buildsystem.h \
static_libs/buildsystem/buildsystem_autotools.c \
lib/elementary/efl_ui_pager.c \
lib/elementary/efl_ui_active_view_container.c \
lib/elementary/efl_ui_active_view_view_manager.c \
lib/elementary/efl_ui_active_view_view_manager_plain.c \
lib/elementary/efl_ui_active_view_view_manager_scroll.c \
lib/elementary/efl_ui_active_view_view_manager_stack.c \
lib/elementary/efl_ui_active_view_indicator.c \
lib/elementary/efl_ui_active_view_indicator_icon.c \
lib/elementary/efl_page_transition.c \
lib/elementary/efl_page_transition_scroll.c \
lib/elementary/efl_page_indicator.c \
@ -1435,6 +1449,7 @@ bin/elementary/test_gesture_framework.c \
bin/elementary/test_ui_tab_pager.c \
bin/elementary/test_ui_pager.c \
bin/elementary/test_ui_pager_scroll.c \
bin/elementary/test_ui_active_view.c \
bin/elementary/test_ui_relative_layout.c \
bin/elementary/test.h
@ -1963,6 +1978,7 @@ tests_elementary_efl_ui_suite_SOURCES = \
tests/elementary/efl_ui_test_image_zoomable.c \
tests/elementary/efl_ui_test_layout.c \
tests/elementary/efl_ui_test_widget.c \
tests/elementary/efl_ui_test_active_view.c \
tests/elementary/efl_ui_suite.h \
tests/elementary/efl_ui_model.c

View File

@ -101,6 +101,7 @@ elementary_test_src = [
'test_ui_panel.c',
'test_ui_pager.c',
'test_ui_pager_scroll.c',
'test_ui_active_view.c',
'test_part_bg.c',
'test_part_shadow.c',
'test_photo.c',

View File

@ -387,7 +387,11 @@ void test_gesture_framework(void *data, Evas_Object *obj, void *event_info);
void test_ui_tab_pager(void *data, Evas_Object *obj, void *event_info);
void test_ui_pager(void *data, Evas_Object *obj, void *event_info);
void test_ui_pager_stack(void *data, Evas_Object *obj, void *event_info);
void test_ui_pager_scroll(void *data, Evas_Object *obj, void *event_info);
void test_ui_active_view_stack(void *data, Evas_Object *obj, void *event_info);
void test_ui_active_view_plain(void *data, Evas_Object *obj, void *event_info);
void test_ui_active_view_scroll(void *data, Evas_Object *obj, void *event_info);
void test_ui_relative_layout(void *data, Evas_Object *obj, void *event_info);
@ -1117,6 +1121,9 @@ add_tests:
ADD_TEST_EO(NULL, "Tab Pager", "Efl.Ui.Tab_Pager", test_ui_tab_pager);
ADD_TEST_EO(NULL, "Pager", "Efl.Ui.Pager", test_ui_pager);
ADD_TEST_EO(NULL, "Scroll Pager", "Efl.Ui.Pager (Scroll)", test_ui_pager_scroll);
ADD_TEST_EO(NULL, "Active View", "Efl.Ui.Active_View Plain", test_ui_active_view_plain);
ADD_TEST_EO(NULL, "Active View", "Efl.Ui.Active_View Scroll", test_ui_active_view_scroll);
ADD_TEST_EO(NULL, "Active View", "Efl.Ui.Active_View Stack", test_ui_active_view_stack);
//------------------------------//
ADD_TEST(NULL, "Popups", "Ctxpopup", test_ctxpopup);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
#include <Efl_Ui.h>
#include <Elementary.h>
static Efl_Ui_Active_View_Container *container;
static Eina_Bool play_state = EINA_FALSE;
static Efl_Loop_Timer *show_timer = NULL;
char *img_files[] = {
"logo.png",
"plant_01.jpg",
"rock_01.jpg",
"rock_02.jpg",
"sky_01.jpg",
"wood_01.jpg",
"mystrale.jpg",
"mystrale_2.jpg"
};
#define IMG_NUM 8
static void
_show_next(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
if (!show_timer) return;
efl_del(show_timer);
show_timer = NULL;
int current_index = efl_ui_active_view_active_index_get(container);
int new_index = (current_index + 1) % efl_content_count(container);
efl_ui_active_view_active_index_set(container, new_index);
}
static void
put_play(void)
{
play_state = EINA_TRUE;
show_timer = efl_add(EFL_LOOP_TIMER_CLASS, container,
efl_loop_timer_interval_set(efl_added, 2.0),
efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TIMER_TICK, _show_next, NULL));
}
static void
put_pause(void)
{
play_state = EINA_FALSE;
if (show_timer)
efl_del(show_timer);
show_timer = NULL;
}
static void
_container_end(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
if (play_state)
{
show_timer = efl_add(EFL_LOOP_TIMER_CLASS, efl_app_main_get(),
efl_loop_timer_interval_set(efl_added, 2.0),
efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TIMER_TICK, _show_next, NULL));
}
}
static void
_play_toggle(void *data EINA_UNUSED, const Efl_Event *ev)
{
if (play_state)
{
put_pause();
efl_text_set(ev->object, "Play");
}
else
{
put_play();
efl_text_set(ev->object, "Pause");
}
}
static void
efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
{
Efl_Ui_Win *win;
Efl_Ui_Table *table;
elm_app_info_set(efl_main, "elementary", "images");
win = efl_new(EFL_UI_WIN_CLASS,
efl_ui_win_autodel_set(efl_added, EINA_TRUE),
efl_text_set(efl_added, "Slideshow Example")
);
table = efl_add(EFL_UI_TABLE_CLASS, win);
efl_content_set(win, table);
container = efl_add(EFL_UI_ACTIVE_VIEW_CONTAINER_CLASS, win,
efl_event_callback_add(efl_added, EFL_UI_ACTIVE_VIEW_EVENT_TRANSITION_END, _container_end, NULL),
efl_pack_table(table, efl_added, 0, 0, 1, 1));
efl_ui_active_view_indicator_set(container, efl_new(EFL_UI_ACTIVE_VIEW_INDICATOR_ICON_CLASS));
efl_ui_active_view_manager_set(container, efl_new(EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_STACK_CLASS));
for (int i = 0; i < IMG_NUM; i++)
{
char path[PATH_MAX];
snprintf(path, PATH_MAX, "%s/images/%s", elm_app_data_dir_get(), img_files[i]);
efl_add(EFL_UI_IMAGE_CLASS, container,
efl_file_set(efl_added, path),
efl_file_load(efl_added),
efl_pack_end(container, efl_added));
}
efl_add(EFL_UI_BUTTON_CLASS, table,
efl_gfx_hint_weight_set(efl_added, 1.0, 0.0),
efl_pack_table(table, efl_added, 0, 1, 1, 1),
efl_text_set(efl_added, "Play"),
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, _play_toggle, NULL));
efl_gfx_entity_size_set(win, EINA_SIZE2D(200, 200));
}
EFL_MAIN();

View File

@ -116,7 +116,8 @@ examples = [
'efl_ui_list_view_example_3',
'efl_canvas_layout_text',
'efl_ui_theme_example_01',
'efl_ui_theme_example_02'
'efl_ui_theme_example_02',
'efl_ui_slideshow_example'
]
foreach example : examples

View File

@ -231,6 +231,18 @@ EAPI void efl_ui_focus_relation_free(Efl_Ui_Focus_Relations *rel);
# include <efl_ui_panes_eo.h>
# include <efl_ui_panes_part.eo.h>
#define _EFL_UI_ACTIVE_VIEW_VIEW_MANAGEREO_CLASS_TYPE
typedef Eo Efl_Ui_Active_View_View_Manager;
#define _EFL_UI_ACTIVE_VIEW_INDICATOR_EO_CLASS_TYPE
typedef Eo Efl_Ui_Active_View_Indicator;
# include <efl_ui_active_view_container.eo.h>
# include <efl_ui_active_view_view_manager.eo.h>
# include <efl_ui_active_view_indicator.eo.h>
# include <efl_ui_active_view_indicator_icon.eo.h>
# include <efl_ui_active_view_view_manager_scroll.eo.h>
# include <efl_ui_active_view_view_manager_stack.eo.h>
# include <efl_ui_navigation_bar.eo.h>
# include <efl_ui_navigation_bar_part.eo.h>
# include <efl_ui_navigation_bar_part_back_button.eo.h>

View File

@ -0,0 +1,647 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "elm_priv.h"
#include "efl_ui_active_view_view_manager_plain.eo.h"
typedef struct _Efl_Ui_Active_View_Container_Data
{
Eina_List *content_list;
Eo *page_root, *event;
struct {
Eina_Size2D sz;
} page_spec;
struct {
int page;
double pos;
} curr;
struct {
int from;
int to;
double last_pos;
Eina_Bool active;
} show_request;
Efl_Ui_Active_View_View_Manager *transition;
Efl_Ui_Active_View_Indicator *indicator;
double position;
Eina_Bool fill_width: 1;
Eina_Bool fill_height: 1;
Eina_Bool prevent_transition_interaction : 1;
Efl_Ui_Active_View_Container_Gravity gravity;
} Efl_Ui_Active_View_Container_Data;
#define MY_CLASS EFL_UI_ACTIVE_VIEW_CONTAINER_CLASS
static void _unpack(Eo *obj, Efl_Ui_Active_View_Container_Data *pd, Efl_Gfx_Entity *subobj, int index);
static void _unpack_all(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd, Eina_Bool clear);
static int
clamp_index(Efl_Ui_Active_View_Container_Data *pd, int index)
{
if (index < ((int)eina_list_count(pd->content_list)) * -1)
return -1;
else if (index > (int)eina_list_count(pd->content_list) - 1)
return 1;
return 0;
}
static int
index_rollover(Efl_Ui_Active_View_Container_Data *pd, int index)
{
int c = eina_list_count(pd->content_list);
if (index < c * -1)
return 0;
else if (index > c - 1)
return c - 1;
else if (index < 0)
return index + c;
return index;
}
static void
_transition_end(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd)
{
Efl_Ui_Active_View_Transition_Event ev;
if (pd->prevent_transition_interaction) return;
ev.from = pd->show_request.from;
ev.to = pd->show_request.to;
efl_event_callback_call(obj, EFL_UI_ACTIVE_VIEW_EVENT_TRANSITION_END, &ev);
pd->show_request.active = EINA_FALSE;
pd->show_request.from = -1;
pd->show_request.to = -1;
}
static void
_transition_start(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd, int from, int to, double progress)
{
Efl_Ui_Active_View_Transition_Event ev;
if (pd->prevent_transition_interaction) return;
if (pd->show_request.active)
_transition_end(obj, pd);
pd->show_request.active = EINA_TRUE;
pd->show_request.from = from;
pd->show_request.to = to;
pd->show_request.last_pos = progress;
ev.from = pd->show_request.from;
ev.to = pd->show_request.to;
efl_event_callback_call(obj, EFL_UI_ACTIVE_VIEW_EVENT_TRANSITION_START, &ev);
}
static void
_position_set(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd, double progress)
{
if (progress < -1.0) progress = -1.0;
if (progress > eina_list_count(pd->content_list)) progress = eina_list_count(pd->content_list);
if (pd->indicator)
{
efl_ui_active_view_indicator_position_update(pd->indicator, progress);
}
pd->position = progress;
}
static void
_transition_event_emission(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd)
{
if (pd->show_request.active)
{
if ((pd->show_request.to != -1 || pd->show_request.from != -1) &&
fabs(pd->show_request.last_pos - pd->show_request.to) < fabs(pd->position - pd->show_request.to))
{
//abort event here, movement is not in the direction we request
pd->show_request.to = -1;
_transition_end(obj, pd);
}
if (pd->position == pd->show_request.to)
{
//successfully there
_transition_end(obj, pd);
}
}
else
{
//the progress changed without a show_request beeing active. instaciate a new one
_transition_start(obj, pd, -1, -1, pd->position);
}
}
static void
_resize_cb(void *data, const Efl_Event *ev)
{
Efl_Ui_Active_View_Container_Data *pd = data;
Eina_Size2D sz;
sz = efl_gfx_entity_size_get(ev->object);
if (pd->fill_width) pd->page_spec.sz.w = sz.w;
if (pd->fill_height) pd->page_spec.sz.h = sz.h;
if (pd->transition)
efl_ui_active_view_view_manager_view_size_set(pd->transition, pd->page_spec.sz);
}
EOLIAN static Eo *
_efl_ui_active_view_container_efl_object_constructor(Eo *obj,
Efl_Ui_Active_View_Container_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)) == EFL_UI_THEME_APPLY_ERROR_GENERIC)
CRI("Failed to set layout!");
pd->position = -1;
pd->curr.page = -1;
pd->curr.pos = 0.0;
pd->transition = NULL;
pd->indicator = NULL;
pd->fill_width = EINA_TRUE;
pd->fill_height = EINA_TRUE;
efl_ui_active_view_size_set(obj, EINA_SIZE2D(-1, -1));
efl_ui_active_view_gravity_set(obj, EFL_UI_ACTIVE_VIEW_CONTAINER_GRAVITY_CONTENT);
elm_widget_can_focus_set(obj, EINA_FALSE);
pd->page_root = efl_add(EFL_CANVAS_GROUP_CLASS, evas_object_evas_get(obj));
efl_content_set(efl_part(obj, "efl.page_root"), pd->page_root);
efl_event_callback_add(pd->page_root, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _resize_cb, 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, "efl.event"), pd->event);
return obj;
}
EOLIAN static Efl_Object*
_efl_ui_active_view_container_efl_object_finalize(Eo *obj, Efl_Ui_Active_View_Container_Data *pd EINA_UNUSED)
{
Efl_Ui_Active_View_View_Manager *manager;
obj = efl_finalize(efl_super(obj, MY_CLASS));
manager = efl_ui_active_view_manager_get(obj);
//set a view manager in case nothing is here
if (!manager)
{
Eo *plain;
plain = efl_add(EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_PLAIN_CLASS, obj);
efl_ui_active_view_manager_set(obj, plain);
}
else
{
efl_ui_active_view_view_manager_animation_enabled_set(manager, EINA_TRUE);
}
return obj;
}
EOLIAN static void
_efl_ui_active_view_container_efl_object_invalidate(Eo *obj,
Efl_Ui_Active_View_Container_Data *pd)
{
_unpack_all(obj, pd, EINA_TRUE);
efl_invalidate(efl_super(obj, MY_CLASS));
}
EOLIAN static int
_efl_ui_active_view_container_efl_container_content_count(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd)
{
return eina_list_count(pd->content_list);
}
static void
_child_inv(void *data, const Efl_Event *ev)
{
Efl_Ui_Active_View_Container_Data *pd = efl_data_scope_get(data, MY_CLASS);
int index = eina_list_data_idx(pd->content_list, ev->object);
_unpack(data, pd, ev->object, index);
}
static Eina_Bool
_register_child(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd, Efl_Gfx_Entity *subobj)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(subobj, EINA_FALSE);
if (eina_list_data_find(pd->content_list, subobj))
{
ERR("Object %p is already part of this!", subobj);
return EINA_FALSE;
}
if (!efl_ui_widget_sub_object_add(obj, subobj))
return EINA_FALSE;
efl_event_callback_add(subobj, EFL_EVENT_INVALIDATE, _child_inv, obj);
return EINA_TRUE;
}
EOLIAN static void
_efl_ui_active_view_container_active_view_gravity_set(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd, Efl_Ui_Active_View_Container_Gravity gravity)
{
pd->gravity = gravity;
}
EOLIAN static Efl_Ui_Active_View_Container_Gravity
_efl_ui_active_view_container_active_view_gravity_get(const Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd)
{
return pd->gravity;
}
static void
_update_internals(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd, Efl_Gfx_Entity *subobj EINA_UNUSED, int index)
{
Eina_Bool curr_page_update = EINA_FALSE;
if (pd->gravity == EFL_UI_ACTIVE_VIEW_CONTAINER_GRAVITY_CONTENT && pd->curr.page >= index)
{
pd->curr.page++;
curr_page_update = EINA_TRUE;
}
pd->prevent_transition_interaction = EINA_TRUE;
if (pd->transition)
efl_ui_active_view_view_manager_content_add(pd->transition, subobj, index);
if (pd->indicator)
efl_ui_active_view_indicator_content_add(pd->indicator, subobj, index);
if (curr_page_update && !pd->transition && eina_list_count(pd->content_list) != 1)
_position_set(obj, pd, pd->curr.page);
pd->prevent_transition_interaction = EINA_FALSE;
if (eina_list_count(pd->content_list) == 1)
efl_ui_active_view_active_index_set(obj, 0);
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_linear_pack_begin(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
Efl_Gfx_Entity *subobj)
{
if (!_register_child(obj, pd, subobj)) return EINA_FALSE;
pd->content_list = eina_list_prepend(pd->content_list, subobj);
_update_internals(obj, pd, subobj, 0);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_linear_pack_end(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
Efl_Gfx_Entity *subobj)
{
if (!_register_child(obj, pd, subobj)) return EINA_FALSE;
pd->content_list = eina_list_append(pd->content_list, subobj);
_update_internals(obj, pd, subobj, eina_list_count(pd->content_list) - 1);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_linear_pack_before(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
Efl_Gfx_Entity *subobj,
const Efl_Gfx_Entity *existing)
{
if (!_register_child(obj, pd, subobj)) return EINA_FALSE;
int index = eina_list_data_idx(pd->content_list, (void *)existing);
if (index == -1) return EINA_FALSE;
pd->content_list = eina_list_prepend_relative(pd->content_list, subobj, existing);
_update_internals(obj, pd, subobj, index);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_linear_pack_after(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
Efl_Gfx_Entity *subobj,
const Efl_Gfx_Entity *existing)
{
if (!_register_child(obj, pd, subobj)) return EINA_FALSE;
int index = eina_list_data_idx(pd->content_list, (void *)existing);
if (index == -1) return EINA_FALSE;
pd->content_list = eina_list_append_relative(pd->content_list, subobj, existing);
_update_internals(obj, pd, subobj, index + 1);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_linear_pack_at(Eo *obj,
Efl_Ui_Active_View_Container_Data *pd,
Efl_Gfx_Entity *subobj,
int index)
{
Efl_Gfx_Entity *existing = NULL;
if (!_register_child(obj, pd, subobj)) return EINA_FALSE;
int clamp = clamp_index(pd, index);
int pass_index = -1;
if (clamp == 0)
{
existing = eina_list_nth(pd->content_list, index_rollover(pd, index));
pd->content_list = eina_list_prepend_relative(
pd->content_list, subobj, existing);
}
else if (clamp == 1)
{
pd->content_list = eina_list_append(pd->content_list, subobj);
pass_index = eina_list_count(pd->content_list);
}
else
{
pd->content_list = eina_list_prepend(pd->content_list, subobj);
pass_index = 0;
}
_update_internals(obj, pd, subobj, pass_index);
return EINA_TRUE;
}
EOLIAN static Efl_Gfx_Entity *
_efl_ui_active_view_container_efl_pack_linear_pack_content_get(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
int index)
{
return eina_list_nth(pd->content_list, index_rollover(pd, index));
}
EOLIAN static int
_efl_ui_active_view_container_efl_pack_linear_pack_index_get(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
const Efl_Gfx_Entity *subobj)
{
return eina_list_data_idx(pd->content_list, (void *)subobj);
}
EOLIAN static void
_efl_ui_active_view_container_active_index_set(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
int index)
{
int before;
if ((index < 0) || (index > ((int)eina_list_count(pd->content_list) - 1)))
{
ERR("index %d out of range", index);
return;
}
before = pd->curr.page;
pd->show_request.last_pos = pd->curr.page;
pd->show_request.from = pd->curr.page;
pd->show_request.to = index;
if (pd->show_request.active && pd->show_request.from == -1 && pd->show_request.to)
pd->show_request.to = index; //we just edit this here, a user animation will end when the progress is at the goal.
else
{
_transition_start(obj, pd, before, index, before);
}
int old_curr_page = pd->curr.page;
pd->curr.page = index;
efl_ui_active_view_view_manager_switch_to(pd->transition, old_curr_page, pd->curr.page);
}
EOLIAN static int
_efl_ui_active_view_container_active_index_get(const Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd)
{
return pd->curr.page;
}
EOLIAN Eina_Size2D
_efl_ui_active_view_container_active_view_size_get(const Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd)
{
return pd->page_spec.sz;
}
EOLIAN static void
_efl_ui_active_view_container_active_view_size_set(Eo *obj,
Efl_Ui_Active_View_Container_Data *pd,
Eina_Size2D sz)
{
Eina_Size2D size;
if (sz.w < -1 || sz.h < -1) return;
pd->page_spec.sz = sz;
pd->fill_width = sz.w == -1 ? EINA_TRUE : EINA_FALSE;
pd->fill_height = sz.h == -1 ? EINA_TRUE : EINA_FALSE;
size = efl_gfx_entity_size_get(obj);
if (pd->fill_height)
pd->page_spec.sz.h = size.h;
if (pd->fill_width)
pd->page_spec.sz.w = size.w;
if (pd->transition)
efl_ui_active_view_view_manager_view_size_set(pd->transition, pd->page_spec.sz);
}
static void
_unpack_all(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd,
Eina_Bool clear)
{
pd->curr.page = -1;
while(pd->content_list)
{
Eo *content = eina_list_data_get(pd->content_list);
_unpack(obj, pd, content, 0);
if (clear)
efl_del(content);
pd->content_list = eina_list_remove(pd->content_list, content);
}
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_pack_clear(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd)
{
_unpack_all(obj, pd, EINA_TRUE);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_unpack_all(Eo *obj EINA_UNUSED,
Efl_Ui_Active_View_Container_Data *pd)
{
_unpack_all(obj, pd, EINA_FALSE);
return EINA_TRUE;
}
static void
_unpack(Eo *obj,
Efl_Ui_Active_View_Container_Data *pd,
Efl_Gfx_Entity *subobj,
int index)
{
int early_curr_page = pd->curr.page;
pd->content_list = eina_list_remove(pd->content_list, subobj);
_elm_widget_sub_object_redirect_to_top(obj, subobj);
if (pd->gravity == EFL_UI_ACTIVE_VIEW_CONTAINER_GRAVITY_CONTENT && index < pd->curr.page)
pd->curr.page--;
if (pd->transition)
efl_ui_active_view_view_manager_content_del(pd->transition, subobj, index);
if (pd->indicator)
efl_ui_active_view_indicator_content_del(pd->indicator, subobj, index);
//we deleted the current index
if (pd->gravity == EFL_UI_ACTIVE_VIEW_CONTAINER_GRAVITY_CONTENT && early_curr_page == index)
{
int new_curr_page = MIN(MAX(early_curr_page, 0), (int)eina_list_count(pd->content_list) - 1);
pd->curr.page = -1;
if (eina_list_count(pd->content_list) > 0 && efl_alive_get(obj))
efl_ui_active_view_active_index_set(obj, new_curr_page);
}
//position has updated
if (early_curr_page != pd->curr.page && early_curr_page != index &&
pd->indicator && !pd->transition)
efl_ui_active_view_indicator_position_update(pd->indicator, pd->curr.page);
efl_event_callback_del(subobj, EFL_EVENT_INVALIDATE, _child_inv, obj);
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_unpack(Eo *obj,
Efl_Ui_Active_View_Container_Data *pd,
Efl_Gfx_Entity *subobj)
{
if (!subobj) return EINA_FALSE;
int index = eina_list_data_idx(pd->content_list, subobj);
if (index == -1)
{
ERR("Item %p is not part of this container", subobj);
return EINA_FALSE;
}
_unpack(obj, pd, subobj, index);
return EINA_TRUE;
}
EOLIAN static Efl_Gfx_Entity *
_efl_ui_active_view_container_efl_pack_linear_pack_unpack_at(Eo *obj,
Efl_Ui_Active_View_Container_Data *pd,
int index)
{
Efl_Gfx_Entity *subobj = eina_list_nth(pd->content_list, index_rollover(pd, index_rollover(pd, index)));
_unpack(obj, pd, subobj, index);
return subobj;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_container_efl_pack_pack(Eo *obj, Efl_Ui_Active_View_Container_Data *pd EINA_UNUSED, Efl_Gfx_Entity *subobj)
{
return efl_pack_begin(obj, subobj);
}
EOLIAN static Eina_Iterator*
_efl_ui_active_view_container_efl_container_content_iterate(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd)
{
return eina_list_iterator_new(pd->content_list);
}
static void
_pos_updated(void *data, const Efl_Event *event)
{
Efl_Ui_Active_View_Container_Data *pd = efl_data_scope_get(data, MY_CLASS);
double progress = *((double*)event->info);
//ignore this here, this could result in unintendet transition,start / end calls
if (EINA_DBL_EQ(progress, pd->position))
return;
_position_set(data, pd, progress);
_transition_event_emission(data, pd);
}
EOLIAN static void
_efl_ui_active_view_container_view_manager_set(Eo *obj, Efl_Ui_Active_View_Container_Data *pd, Efl_Ui_Active_View_View_Manager *transition)
{
if (!transition)
pd->transition = efl_add(EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_PLAIN_CLASS, obj);
else
EINA_SAFETY_ON_FALSE_RETURN(efl_isa(transition, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_CLASS));
if (pd->transition)
{
efl_ui_active_view_view_manager_bind(pd->transition, NULL, NULL);
efl_del(pd->transition);
}
pd->transition = transition;
if (pd->transition)
{
efl_parent_set(pd->transition, obj);
//disable animation when not finalized yet, this help reducing the overhead of scheduling a animation that will not be displayed
efl_ui_active_view_view_manager_animation_enabled_set(pd->transition, efl_finalized_get(obj));
efl_ui_active_view_view_manager_bind(pd->transition, obj,
pd->page_root);
efl_ui_active_view_view_manager_view_size_set(pd->transition, pd->page_spec.sz);
efl_event_callback_add(pd->transition, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_EVENT_POS_UPDATE, _pos_updated, obj);
}
}
EOLIAN static Efl_Ui_Active_View_View_Manager*
_efl_ui_active_view_container_view_manager_get(const Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd)
{
if (efl_isa(pd->transition, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_PLAIN_CLASS))
return NULL;
else
return pd->transition;
}
EOLIAN static void
_efl_ui_active_view_container_indicator_set(Eo *obj, Efl_Ui_Active_View_Container_Data *pd, Efl_Ui_Active_View_Indicator *indicator)
{
if (pd->indicator)
{
efl_ui_active_view_indicator_bind(pd->indicator, obj);
efl_del(pd->indicator);
}
pd->indicator = indicator;
if (pd->indicator)
{
efl_ui_active_view_indicator_bind(pd->indicator, obj);
if (pd->position != -1)
efl_ui_active_view_indicator_position_update(pd->indicator, pd->position);
}
}
EOLIAN static Efl_Ui_Active_View_Indicator*
_efl_ui_active_view_container_indicator_get(const Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Container_Data *pd)
{
return pd->indicator;
}
#include "efl_ui_active_view_container.eo.c"

View File

@ -0,0 +1,79 @@
struct @beta Efl.Ui.Active_View.Transition_Event {
from : int; [[The id from where the transition started, -1 if not known]]
to : int; [[The id from where the transition started, -1 if not known]]
}
enum Efl.Ui.Active_View.Container_Gravity {
content = 0, [[In case the internal list of content is changed, then the $active_index will always point to the same content]]
index = 1, [[In case the internal list of content is changed, then the $active_index will keep its value]]
}
class @beta Efl.Ui.Active_View.Container extends Efl.Ui.Layout_Base implements Efl.Pack_Linear
{
[[ The active view widget can be used to display the added content in some animated way. The details of the animation and way of displaying depends on the transition object.
The size of the displayed content can be controlled via $active_view_size. The content with the main attraction can be setted with $active_index.
Without a transition object this widget will just display the content with the id set with $active_index. On page changes,
]]
c_prefix: efl_ui_active_view;
methods {
@property view_manager {
[[The transition object which defines the animation and exact position of the content]]
values {
transition : Efl.Ui.Active_View.View_Manager @owned;
}
}
@property indicator {
[[A indicator object which can be used to display the state and position of the content in this widget
When this object here is set, the position of the indicator object is immidiatly called to the current position of the widget
]]
values {
indicator : Efl.Ui.Active_View.Indicator @owned;
}
}
@property active_index {
[[Selects which is the maincontent to display by this widget. The exact positioning depends on the $transition object]]
values {
index: int;
}
}
@property active_view_gravity {
[[active_view can be used to set the currently active viewed content.
This property can be used to switch_to the semantic of the function. If gravity is content, then newly added content will change the index, but keep the content. If the gravity is set to index, then the index will stay when new content is added, which might show new content.
]]
values {
gravity : Efl.Ui.Active_View.Container_Gravity;
}
}
@property active_view_size {
[[The size that is give to each content when displayed]]
values {
size: Eina.Size2D;
}
}
}
events {
transition,start : Efl.Ui.Active_View.Transition_Event;
transition,end : Efl.Ui.Active_View.Transition_Event;
}
implements {
Efl.Object.constructor;
Efl.Object.finalize;
Efl.Object.invalidate;
Efl.Container.content_count;
Efl.Container.content_iterate;
Efl.Pack.pack_clear;
Efl.Pack.unpack_all;
Efl.Pack.unpack;
Efl.Pack.pack;
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;
}
}

View File

@ -0,0 +1,15 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_PACK_LAYOUT_PROTECTED
#include <Elementary.h>
#include "elm_priv.h"
typedef struct {
} Efl_Ui_Active_View_Indicator_Data;
#include "efl_ui_active_view_indicator.eo.c"

View File

@ -0,0 +1,49 @@
abstract @beta Efl.Ui.Active_View.Indicator extends Efl.Object {
[[Indicator object that is used by @Efl.Ui.Active_View.Container]]
methods {
bind @pure_virtual {
[[Initial call to flush the required objects of the active view to the transition object
This call can be used to setup the indicator part of $active_view.
if there is a position of the widget, then after this call, $position_update will be called.
]]
params {
active_view : Efl.Ui.Active_View.Container;
}
}
content_add @pure_virtual {
[[Content has been added to the container passed in .bind. The $subobj is at position $index.
While in the call, the $current_page property of the active_view might change.
If such a change is happening. No animation should be displayed, and the new state should be applied.
]]
params {
subobj : Efl.Gfx.Entity;
index : int;
}
}
content_del @pure_virtual {
[[Content has been removed from the container passed in .bind. The $subobj at position $index is now removed.
While in the call, the $current_page property of the active_view might change.
If such a change is happening. No animation should be displayed, and the new state should be applied.
]]
params {
subobj : Efl.Gfx.Entity;
index : int;
}
}
position_update @pure_virtual {
[[The position between the content has been changed.
The position is absolut and ranges from [-1,x + 1] where x is the number of contents in the active_view.
Values between two actaul positions must be expected as this is the way the animation of the transition object populates to the indicator
]]
params {
position : double; [[The position the transition object is currently in]]
}
}
}
}

View File

@ -0,0 +1,114 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_PACK_LAYOUT_PROTECTED
#include <Elementary.h>
#include "elm_priv.h"
typedef struct {
Efl_Ui_Box *indicator;
Efl_Ui_Active_View_Container *container;
double last_position;
} Efl_Ui_Active_View_Indicator_Icon_Data;
static void
_flush_state(Eo *item, double val)
{
Eina_Value v = eina_value_double_init(val);
efl_layout_signal_message_send(item, 1, v);
}
static void
_add_item(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Indicator_Icon_Data *pd)
{
Efl_Canvas_Layout *item;
item = efl_add(EFL_CANVAS_LAYOUT_CLASS, pd->indicator);
elm_widget_theme_object_set(pd->indicator, item,
"pager", "indicator", "default");
efl_gfx_hint_align_set(item, 0.5, 0.5);
efl_gfx_hint_weight_set(item, 0, 0);
efl_gfx_hint_fill_set(item, 0, 0);
efl_pack_end(pd->indicator, item);
_flush_state(item, 0.0);
}
static void
_flush_position(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Indicator_Icon_Data *pd)
{
int next = -1, closer;
double closer_val;
for (int i = 0; i < efl_content_count(pd->indicator); ++i)
{
_flush_state(efl_pack_content_get(pd->indicator, i), 0.0f);
}
closer = MIN(MAX(round(pd->last_position), 0), efl_content_count(pd->container) - 1);
closer_val = fabs(1.0f - fabs(closer - pd->last_position));
_flush_state(efl_pack_content_get(pd->indicator, closer), closer_val);
if (pd->last_position > closer)
next = closer + 1;
else if (pd->last_position < closer)
next = closer - 1;
else
{
next = closer + 1;
if (next < efl_content_count(pd->container))
_flush_state(efl_pack_content_get(pd->indicator, next), fabs(1.0f - fabs((next - pd->last_position))));
next = closer - 1;
if (next >= 0)
_flush_state(efl_pack_content_get(pd->indicator, next), fabs(1.0f - fabs((next - pd->last_position))));
}
if (next >= 0 && next < efl_content_count(pd->container))
_flush_state(efl_pack_content_get(pd->indicator, next), fabs(1.0f - fabs((next - pd->last_position))));
}
EOLIAN static void
_efl_ui_active_view_indicator_icon_efl_ui_active_view_indicator_bind(Eo *obj, Efl_Ui_Active_View_Indicator_Icon_Data *pd, Efl_Ui_Active_View_Container *active_view)
{
if (active_view)
{
pd->container = active_view;
pd->indicator = efl_add(EFL_UI_BOX_CLASS, active_view);
efl_ui_widget_internal_set(pd->indicator, EINA_TRUE);
efl_content_set(efl_part(pd->container, "efl.indicator"), pd->indicator);
efl_gfx_entity_visible_set(pd->indicator, EINA_TRUE);
efl_ui_layout_orientation_set(pd->indicator, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
efl_gfx_arrangement_content_padding_set(pd->indicator, 15, 15, EINA_TRUE);
for (int i = 0; i < efl_content_count(pd->container); ++i)
{
_add_item(obj, pd);
}
}
}
EOLIAN static void
_efl_ui_active_view_indicator_icon_efl_ui_active_view_indicator_content_add(Eo *obj, Efl_Ui_Active_View_Indicator_Icon_Data *pd, Efl_Gfx_Entity *subobj EINA_UNUSED, int index EINA_UNUSED)
{
_add_item(obj, pd);
_flush_position(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_indicator_icon_efl_ui_active_view_indicator_content_del(Eo *obj, Efl_Ui_Active_View_Indicator_Icon_Data *pd, Efl_Gfx_Entity *subobj EINA_UNUSED, int index EINA_UNUSED)
{
efl_del(efl_pack_content_get(pd->indicator, 0));
_flush_position(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_indicator_icon_efl_ui_active_view_indicator_position_update(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_Indicator_Icon_Data *pd, double position)
{
pd->last_position = position;
_flush_position(obj, pd);
}
#include "efl_ui_active_view_indicator_icon.eo.c"

View File

@ -0,0 +1,8 @@
class @beta Efl.Ui.Active_View.Indicator_Icon extends Efl.Ui.Active_View.Indicator {
implements {
Efl.Ui.Active_View.Indicator.bind;
Efl.Ui.Active_View.Indicator.content_del;
Efl.Ui.Active_View.Indicator.content_add;
Efl.Ui.Active_View.Indicator.position_update;
}
}

View File

@ -0,0 +1,15 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_PACK_LAYOUT_PROTECTED
#include <Elementary.h>
#include "elm_priv.h"
typedef struct {
} Efl_Ui_Active_View_View_Manager_Data;
#include "efl_ui_active_view_view_manager.eo.c"

View File

@ -0,0 +1,65 @@
abstract @beta Efl.Ui.Active_View.View_Manager extends Efl.Object {
[[Transition object which is used by active_view.
The transition object can display changes to the active view with animations.
This object can also implement behavior user interaction in a animation manner. For example: Mouse dragging content, to get to a new $current_page. If this is the case, such a user interaction should terminate with a call to $current_page. The position of the content should be exposed by emitting pos_update.
]]
methods {
bind @pure_virtual {
[[Initial call to flush the required objects of the active view to the transition object]]
params {
active_view : Efl.Ui.Active_View.Container;
group : Efl.Canvas.Group;
}
}
content_add @pure_virtual {
[[Content has been added to the container passed in .bind. The $subobj is at position $index.
While in the call, the $current_page property of the active_view might change.
If such a change is happening. No animation should be displayed, and the new state should be applied.
]]
params {
subobj : Efl.Gfx.Entity;
index : int;
}
}
content_del @pure_virtual {
[[Content has been removed from the container passed in .bind. The $subobj at position $index is now removed.
While in the call, the $current_page property of the active_view might change.
If such a change is happening. No animation should be displayed, and the new state should be applied.
]]
params {
subobj : Efl.Gfx.Entity;
index : int;
}
}
switch_to @pure_virtual {
[[Switch from one side to another, if there has been no side before, from is -1.
This function should, if the transition object supports this, display a animation.
]]
params {
from : int;
to : int;
}
}
@property view_size @pure_virtual {
[[Will be called whenever the page size changes]]
set {
}
values {
size : Eina.Size2D; [[The size of the page, real coordiates at any time]]
}
}
@property animation_enabled @pure_virtual {
[[This flag can be used to indicate that no animations should be done]]
values {
enable : bool; [[$true if you want animations to happen, $false if otherwise]]
}
}
}
events {
pos_update : double; [[The absolut position where the state of the content currently is. So if there is a animation from 2 to 3 the event will go from 2.0 to 3.0. If there is a $switch_to from 2 to 3, then this event should go in one direction from 2 to 3. Not following this, will result in a event to abort the transition, and instanciating a new one.]]
}
}

View File

@ -0,0 +1,166 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "elm_priv.h"
#include "efl_ui_active_view_view_manager_plain.eo.h"
typedef struct {
Efl_Ui_Active_View_Container * container;
Efl_Gfx_Entity *group;
Eina_Size2D page_size;
int current_content;
Eina_Bool animation;
} Efl_Ui_Active_View_View_Manager_Plain_Data;
#define MY_CLASS EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_PLAIN_CLASS
static void
_emit_position(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Plain_Data *pd)
{
double absolut_position = pd->current_content;
efl_event_callback_call(obj, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_EVENT_POS_UPDATE, &absolut_position);
}
static void
_geom_sync(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Plain_Data *pd)
{
Efl_Gfx_Entity *entity = efl_pack_content_get(pd->container, pd->current_content);
Eina_Rect group_pos = efl_gfx_entity_geometry_get(pd->group);
Eina_Rect goal = EINA_RECT_EMPTY();
goal.size = pd->page_size;
goal.y = (group_pos.y + group_pos.h/2)-pd->page_size.h/2;
goal.x = (group_pos.x + group_pos.w/2)-pd->page_size.w/2;
efl_gfx_entity_geometry_set(entity, goal);
}
static void
_resize_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
_geom_sync(data, efl_data_scope_get(data, MY_CLASS));
}
static void
_move_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
_geom_sync(data, efl_data_scope_get(data, MY_CLASS));
}
EFL_CALLBACKS_ARRAY_DEFINE(group_callback,
{EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _resize_cb},
{EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _move_cb},
)
EOLIAN static void
_efl_ui_active_view_view_manager_plain_efl_ui_active_view_view_manager_bind(Eo *obj, Efl_Ui_Active_View_View_Manager_Plain_Data *pd, Efl_Ui_Active_View_Container *active_view, Efl_Canvas_Group *group)
{
if (active_view && group)
{
int index;
pd->container = active_view;
pd->group = group;
efl_event_callback_array_add(pd->group, group_callback(), obj);
for (int i = 0; i < efl_content_count(active_view) ; ++i) {
Efl_Gfx_Entity *elem = efl_pack_content_get(active_view, i);
efl_canvas_group_member_add(pd->group, elem);
efl_gfx_entity_visible_set(elem, EINA_FALSE);
}
index = efl_ui_active_view_active_index_get(active_view);
if (index != -1)
{
pd->current_content = index;
efl_gfx_entity_visible_set(efl_pack_content_get(pd->container, pd->current_content), EINA_TRUE);
_geom_sync(obj, pd);
_emit_position(obj, pd);
}
}
}
static void
_content_changed(Eo *obj, Efl_Ui_Active_View_View_Manager_Plain_Data *pd)
{
if (efl_ui_active_view_active_index_get(pd->container) != pd->current_content)
{
pd->current_content = efl_ui_active_view_active_index_get(pd->container);
efl_gfx_entity_visible_set(efl_pack_content_get(pd->container, pd->current_content), EINA_FALSE);
_geom_sync(obj, pd);
_emit_position(obj, pd);
}
}
EOLIAN static void
_efl_ui_active_view_view_manager_plain_efl_ui_active_view_view_manager_content_add(Eo *obj, Efl_Ui_Active_View_View_Manager_Plain_Data *pd, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
efl_canvas_group_member_add(pd->group, subobj);
efl_gfx_entity_visible_set(subobj, EINA_FALSE);
_content_changed(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_plain_efl_ui_active_view_view_manager_content_del(Eo *obj, Efl_Ui_Active_View_View_Manager_Plain_Data *pd, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
efl_canvas_group_member_remove(pd->group, subobj);
_content_changed(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_plain_efl_ui_active_view_view_manager_switch_to(Eo *obj, Efl_Ui_Active_View_View_Manager_Plain_Data *pd, int from EINA_UNUSED, int to)
{
Efl_Gfx_Entity *to_obj, *from_obj;
to_obj = efl_pack_content_get(pd->container, to);
from_obj = efl_pack_content_get(pd->container, from);
if (from_obj)
{
efl_gfx_entity_visible_set(from_obj, EINA_FALSE);
pd->current_content = -1;
}
if (to_obj)
{
efl_gfx_entity_visible_set(to_obj, EINA_TRUE);
pd->current_content = to;
}
_emit_position(obj, pd);
_geom_sync(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_plain_efl_ui_active_view_view_manager_view_size_set(Eo *obj, Efl_Ui_Active_View_View_Manager_Plain_Data *pd, Eina_Size2D size)
{
pd->page_size = size;
_geom_sync(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_plain_efl_object_destructor(Eo *obj, Efl_Ui_Active_View_View_Manager_Plain_Data *pd EINA_UNUSED)
{
efl_destructor(efl_super(obj, MY_CLASS));
efl_event_callback_array_del(pd->group, group_callback(), obj);
for (int i = 0; i < efl_content_count(pd->container); ++i)
{
Efl_Gfx_Stack *elem = efl_pack_content_get(pd->container, i);
efl_gfx_entity_visible_set(elem, EINA_TRUE);
}
}
EOLIAN static void
_efl_ui_active_view_view_manager_plain_efl_ui_active_view_view_manager_animation_enabled_set(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Plain_Data *pd, Eina_Bool animation)
{
pd->animation = animation;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_view_manager_plain_efl_ui_active_view_view_manager_animation_enabled_get(const Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Plain_Data *pd)
{
return pd->animation;
}
#include "efl_ui_active_view_view_manager_plain.eo.c"

View File

@ -0,0 +1,12 @@
class @beta Efl.Ui.Active_View.View_Manager_Plain extends Efl.Ui.Active_View.View_Manager
{
implements {
Efl.Ui.Active_View.View_Manager.bind;
Efl.Ui.Active_View.View_Manager.content_add;
Efl.Ui.Active_View.View_Manager.content_del;
Efl.Ui.Active_View.View_Manager.switch_to;
Efl.Ui.Active_View.View_Manager.view_size {set;}
Efl.Ui.Active_View.View_Manager.animation_enabled {set; get;}
Efl.Object.destructor;
}
}

View File

@ -0,0 +1,316 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "elm_priv.h"
typedef struct {
Efl_Ui_Active_View_Container * container;
Efl_Gfx_Entity *group, *foreclip, *backclip;
Eina_Size2D page_size;
struct {
Eina_Bool active;
int to;
double from, progress;
double start_time;
double max_time;
} transition;
struct {
Eina_Bool active;
int from;
Eina_Position2D mouse_start;
} mouse_move;
Eina_Bool animation;
} Efl_Ui_Active_View_View_Manager_Scroll_Data;
#define MY_CLASS EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_SCROLL_CLASS
static void _page_set_animation(void *data, const Efl_Event *event);
static void
_propagate_progress(Eo *obj, double pos)
{
efl_event_callback_call(obj, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_EVENT_POS_UPDATE, &pos);
}
static void
_apply_box_properties(Eo *obj, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd)
{
Eina_Rect geometry = EINA_RECT_EMPTY();
Eina_Rect group_pos = efl_gfx_entity_geometry_get(pd->group);
double current_pos;
if (pd->transition.active)
current_pos = pd->transition.from + ((double)pd->transition.to - pd->transition.from)*pd->transition.progress;
else
current_pos = efl_ui_active_view_active_index_get(pd->container);
efl_gfx_entity_geometry_set(pd->foreclip, group_pos);
//first calculate the size
geometry.h = pd->page_size.h;
geometry.w = (pd->page_size.w);
//calculate the position
geometry.y = (group_pos.y + group_pos.h/2)-pd->page_size.h/2;
for (int i = 0; i < efl_content_count(pd->container) ; ++i)
{
double diff = i - current_pos;
Efl_Gfx_Entity *elem = efl_pack_content_get(pd->container, i);
geometry.x = (group_pos.x + group_pos.w/2)-(pd->page_size.w/2 - diff*pd->page_size.w);
if (!eina_rectangles_intersect(&geometry.rect, &group_pos.rect))
{
efl_canvas_object_clipper_set(elem, pd->backclip);
}
else
{
efl_gfx_entity_geometry_set(elem, geometry);
efl_canvas_object_clipper_set(elem, pd->foreclip);
}
}
//Propagate progress
_propagate_progress(obj, current_pos);
}
static void
_resize_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
_apply_box_properties(data, efl_data_scope_get(data, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_SCROLL_CLASS));
}
static void
_move_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
_apply_box_properties(data, efl_data_scope_get(data, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_SCROLL_CLASS));
}
static void
_mouse_down_cb(void *data,
const Efl_Event *event)
{
Efl_Input_Pointer *ev = event->info;
Eo *obj = data;
Efl_Ui_Active_View_View_Manager_Scroll_Data *pd = efl_data_scope_get(obj, MY_CLASS);
if (efl_input_pointer_button_get(ev) != 1) return;
if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
if (efl_content_count(pd->container) == 0) return;
efl_event_callback_del(pd->container, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _page_set_animation, obj);
pd->mouse_move.active = EINA_TRUE;
pd->mouse_move.from = efl_ui_active_view_active_index_get(pd->container);
pd->mouse_move.mouse_start = efl_input_pointer_position_get(ev);
}
static void
_mouse_move_cb(void *data,
const Efl_Event *event)
{
Efl_Input_Pointer *ev = event->info;
Eo *obj = data;
Efl_Ui_Active_View_View_Manager_Scroll_Data *pd = efl_data_scope_get(obj, MY_CLASS);
Eina_Position2D pos;
int pos_y_diff;
if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
if (!pd->mouse_move.active) return;
pos = efl_input_pointer_position_get(ev);
pos_y_diff = pd->mouse_move.mouse_start.x - pos.x;
pd->transition.active = EINA_TRUE;
pd->transition.from = pd->mouse_move.from;
pd->transition.progress = (double)pos_y_diff / (double)pd->page_size.w;
pd->transition.to = pd->transition.from + 1;
_propagate_progress(data, pd->transition.from + pd->transition.progress);
_apply_box_properties(obj, pd);
}
static void
_mouse_up_cb(void *data,
const Efl_Event *event)
{
Efl_Input_Pointer *ev = event->info;
Eo *obj = data;
Efl_Ui_Active_View_View_Manager_Scroll_Data *pd = efl_data_scope_get(obj, MY_CLASS);
if (efl_input_event_flags_get(ev) & EFL_INPUT_FLAGS_PROCESSED) return;
if (!pd->mouse_move.active) return;
double absolut_current_position = (double)pd->transition.from + pd->transition.progress;
int result = round(absolut_current_position);
efl_ui_active_view_active_index_set(pd->container, MIN(MAX(result, 0), efl_content_count(pd->container) - 1));
}
EFL_CALLBACKS_ARRAY_DEFINE(mouse_listeners,
{EFL_EVENT_POINTER_DOWN, _mouse_down_cb},
{EFL_EVENT_POINTER_UP, _mouse_up_cb},
{EFL_EVENT_POINTER_MOVE, _mouse_move_cb},
);
EOLIAN static void
_efl_ui_active_view_view_manager_scroll_efl_ui_active_view_view_manager_bind(Eo *obj, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd, Efl_Ui_Active_View_Container *active_view, Efl_Canvas_Group *group)
{
if (active_view && group)
{
pd->container = active_view;
pd->group = group;
efl_event_callback_add(pd->group, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _resize_cb, obj);
efl_event_callback_add(pd->group, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _move_cb, obj);
pd->foreclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
evas_object_evas_get(group));
evas_object_static_clip_set(pd->foreclip, EINA_TRUE);
pd->backclip = efl_add(EFL_CANVAS_RECTANGLE_CLASS,
evas_object_evas_get(group));
evas_object_static_clip_set(pd->backclip, EINA_TRUE);
efl_gfx_entity_visible_set(pd->backclip, EINA_FALSE);
for (int i = 0; i < efl_content_count(active_view) ; ++i) {
Efl_Gfx_Entity *elem = efl_pack_content_get(active_view, i);
efl_canvas_object_clipper_set(elem, pd->backclip);
efl_canvas_group_member_add(pd->group, elem);
efl_gfx_entity_visible_set(elem, EINA_TRUE);
}
_apply_box_properties(obj, pd);
efl_event_callback_array_add(efl_content_get(efl_part(pd->container, "efl.event")), mouse_listeners(), obj);
}
}
EOLIAN static void
_efl_ui_active_view_view_manager_scroll_efl_ui_active_view_view_manager_content_add(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
efl_gfx_entity_visible_set(subobj, EINA_TRUE);
efl_canvas_object_clipper_set(subobj, pd->backclip);
efl_canvas_group_member_add(pd->group, subobj);
if (!pd->transition.active)
_apply_box_properties(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_scroll_efl_ui_active_view_view_manager_content_del(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
efl_canvas_object_clipper_set(subobj, NULL);
efl_canvas_group_member_remove(pd->group, subobj);
if (!pd->transition.active)
_apply_box_properties(obj, pd);
}
static void
_page_set_animation(void *data, const Efl_Event *event EINA_UNUSED)
{
Efl_Ui_Active_View_View_Manager_Scroll_Data *pd = efl_data_scope_get(data, MY_CLASS);
double p = (ecore_loop_time_get() - pd->transition.start_time) / pd->transition.max_time;
if (p >= 1.0) p = 1.0;
p = ecore_animator_pos_map(p, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
pd->transition.progress = p;
if (EINA_DBL_EQ(p, 1.0))
{
efl_event_callback_del(pd->container, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK,
_page_set_animation, data);
pd->transition.active = EINA_FALSE;
}
_apply_box_properties(data, pd);
}
static void
_animation_request_switch(Eo *obj, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd, int from, int to)
{
efl_event_callback_del(pd->container, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _page_set_animation, obj);
//if there is a ongoing transition, try to guess a better time, and try copy over the position where we are right now
if (pd->transition.active || pd->mouse_move.active)
{
pd->transition.from = MIN(pd->transition.from, pd->transition.to) + pd->transition.progress;
pd->transition.max_time = MIN(MAX(fabs(pd->transition.progress), 0.2), 0.5f);
pd->mouse_move.active = EINA_FALSE;
pd->transition.progress = 0.0f;
}
else
{
pd->transition.from = from;
pd->transition.max_time = 0.5;
}
pd->transition.start_time = ecore_loop_time_get();
pd->transition.active = EINA_TRUE;
pd->transition.to = to;
efl_event_callback_add(pd->container, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _page_set_animation, obj);
}
EOLIAN static void
_efl_ui_active_view_view_manager_scroll_efl_ui_active_view_view_manager_switch_to(Eo *obj, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd, int from, int to)
{
if (pd->animation)
{
_animation_request_switch(obj, pd, from, to);
}
else
{
pd->mouse_move.active = EINA_FALSE;
pd->transition.active = EINA_FALSE;
_apply_box_properties(obj, pd);
}
}
EOLIAN static void
_efl_ui_active_view_view_manager_scroll_efl_ui_active_view_view_manager_view_size_set(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd, Eina_Size2D size)
{
pd->page_size = size;
if (!pd->transition.active)
_apply_box_properties(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_scroll_efl_ui_active_view_view_manager_animation_enabled_set(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd, Eina_Bool animation)
{
pd->animation = animation;
if (pd->transition.active && !animation)
{
efl_event_callback_del(pd->container, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _page_set_animation, obj);
_apply_box_properties(obj, pd);
pd->transition.active = EINA_FALSE;
}
}
EOLIAN static Eina_Bool
_efl_ui_active_view_view_manager_scroll_efl_ui_active_view_view_manager_animation_enabled_get(const Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd)
{
return pd->animation;
}
EOLIAN static void
_efl_ui_active_view_view_manager_scroll_efl_object_destructor(Eo *obj, Efl_Ui_Active_View_View_Manager_Scroll_Data *pd EINA_UNUSED)
{
efl_event_callback_del(pd->group, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _resize_cb, obj);
efl_event_callback_del(pd->group, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _move_cb, obj);
efl_event_callback_array_del(efl_content_get(efl_part(pd->container, "efl.event")), mouse_listeners(), obj);
efl_del(pd->backclip);
efl_del(pd->foreclip);
for (int i = 0; i < efl_content_count(pd->container); ++i)
{
efl_canvas_object_clipper_set(efl_pack_content_get(pd->container, i), NULL);
}
efl_destructor(efl_super(obj, MY_CLASS));
}
#include "efl_ui_active_view_view_manager_scroll.eo.c"

View File

@ -0,0 +1,12 @@
class @beta Efl.Ui.Active_View.View_Manager_Scroll extends Efl.Ui.Active_View.View_Manager
{
implements {
Efl.Ui.Active_View.View_Manager.bind;
Efl.Ui.Active_View.View_Manager.content_add;
Efl.Ui.Active_View.View_Manager.content_del;
Efl.Ui.Active_View.View_Manager.switch_to;
Efl.Ui.Active_View.View_Manager.view_size {set;}
Efl.Ui.Active_View.View_Manager.animation_enabled {set; get;}
Efl.Object.destructor;
}
}

View File

@ -0,0 +1,265 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "elm_priv.h"
typedef struct {
Efl_Ui_Active_View_Container * container;
Efl_Gfx_Entity *group;
Efl_Canvas_Animation_Player *hide, *show;
int from, to;
Efl_Gfx_Entity *content;
Eina_Size2D page_size;
Eina_Bool animation;
} Efl_Ui_Active_View_View_Manager_Stack_Data;
#define MY_CLASS EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_STACK_CLASS
static void
_geom_sync(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Stack_Data *pd)
{
Eina_Array *array = eina_array_new(2);
Eina_Rect group_pos = efl_gfx_entity_geometry_get(pd->group);
if (efl_player_play_get(pd->hide))
{
//we are currently in animation, sync the geometry of the targets
eina_array_push(array, efl_animation_player_target_get(pd->hide));
eina_array_push(array, efl_animation_player_target_get(pd->show));
}
else
{
//we only have our content right now, or nothing
eina_array_push(array, pd->content);
}
Eina_Rect goal = EINA_RECT_EMPTY();
goal.size = pd->page_size;
goal.y = (group_pos.y + group_pos.h/2)-pd->page_size.h/2;
goal.x = (group_pos.x + group_pos.w/2)-pd->page_size.w/2;
while (eina_array_count(array) > 0)
{
Efl_Gfx_Entity *subobj = eina_array_pop(array);
efl_gfx_entity_geometry_set(subobj, goal);
}
eina_array_free(array);
}
static void
_resize_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
_geom_sync(data, efl_data_scope_get(data, MY_CLASS));
}
static void
_move_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
_geom_sync(data, efl_data_scope_get(data, MY_CLASS));
}
static void
_running_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
Efl_Ui_Active_View_View_Manager_Stack_Data *pd = efl_data_scope_safe_get(data, MY_CLASS);
//calculate absolut position, multiply pos with 2.0 because duration is only 0.5)
double absolut_position = pd->from + (pd->to - pd->from)*(efl_player_pos_get(pd->show)*2.0);
efl_event_callback_call(data, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_EVENT_POS_UPDATE, &absolut_position);
}
static void
_anim_started_cb(void *data EINA_UNUSED, const Efl_Event *event)
{
Efl_Canvas_Object *content;
content = efl_animation_player_target_get(event->object);
efl_gfx_entity_visible_set(content, EINA_TRUE);
}
static void
_hide_anim_ended_cb(void *data, const Efl_Event *event EINA_UNUSED)
{
Efl_Ui_Active_View_View_Manager_Stack_Data *pd = efl_data_scope_safe_get(data, MY_CLASS);
Efl_Canvas_Object *content;
EINA_SAFETY_ON_NULL_RETURN(pd);
content = efl_animation_player_target_get(pd->hide);
efl_gfx_entity_visible_set(content, EINA_FALSE);
}
static void
_show_anim_ended_cb(void *data, const Efl_Event *event EINA_UNUSED)
{
Efl_Ui_Active_View_View_Manager_Stack_Data *pd = efl_data_scope_safe_get(data, MY_CLASS);
Efl_Canvas_Object *content;
EINA_SAFETY_ON_NULL_RETURN(pd);
content = efl_animation_player_target_get(pd->show);
efl_gfx_entity_visible_set(content, EINA_TRUE);
pd->content = content;
}
EFL_CALLBACKS_ARRAY_DEFINE(_anim_show_event_cb,
{EFL_ANIMATION_PLAYER_EVENT_RUNNING, _running_cb},
{EFL_ANIMATION_PLAYER_EVENT_STARTED, _anim_started_cb},
{EFL_ANIMATION_PLAYER_EVENT_ENDED, _show_anim_ended_cb},
)
EFL_CALLBACKS_ARRAY_DEFINE(_anim_hide_event_cb,
{EFL_ANIMATION_PLAYER_EVENT_STARTED, _anim_started_cb},
{EFL_ANIMATION_PLAYER_EVENT_ENDED, _hide_anim_ended_cb},
)
EOLIAN static void
_efl_ui_active_view_view_manager_stack_efl_ui_active_view_view_manager_bind(Eo *obj, Efl_Ui_Active_View_View_Manager_Stack_Data *pd, Efl_Ui_Active_View_Container *active_view, Efl_Canvas_Group *group)
{
if (active_view && group)
{
Efl_Canvas_Animation_Alpha *show_anim, *hide_anim;
pd->container = active_view;
pd->group = group;
efl_event_callback_add(pd->group, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _resize_cb, obj);
efl_event_callback_add(pd->group, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _move_cb, obj);
show_anim = efl_add(EFL_CANVAS_ANIMATION_ALPHA_CLASS, obj);
efl_animation_alpha_set(show_anim, 0.0, 1.0);
efl_animation_duration_set(show_anim, 0.5);
efl_animation_final_state_keep_set(show_anim, EINA_TRUE);
pd->show = efl_add(EFL_CANVAS_ANIMATION_PLAYER_CLASS, obj);
efl_animation_player_animation_set(pd->show, show_anim);
efl_player_play_set(pd->show, EINA_FALSE);
efl_event_callback_array_add(pd->show, _anim_show_event_cb(), obj);
//Default Hide Animation
hide_anim = efl_add(EFL_CANVAS_ANIMATION_ALPHA_CLASS, obj);
efl_animation_alpha_set(hide_anim, 1.0, 0.0);
efl_animation_duration_set(hide_anim, 0.5);
efl_animation_final_state_keep_set(hide_anim, EINA_TRUE);
pd->hide = efl_add(EFL_CANVAS_ANIMATION_PLAYER_CLASS, obj);
efl_animation_player_animation_set(pd->hide, hide_anim);
efl_player_play_set(pd->hide, EINA_FALSE);
efl_event_callback_array_add(pd->hide, _anim_hide_event_cb(), obj);
for (int i = 0; i < efl_content_count(active_view) ; ++i) {
Efl_Gfx_Entity *elem = efl_pack_content_get(active_view, i);
efl_canvas_group_member_add(pd->group, elem);
efl_gfx_entity_visible_set(elem, EINA_FALSE);
}
if (efl_ui_active_view_active_index_get(active_view) != -1)
{
pd->content = efl_pack_content_get(pd->container, efl_ui_active_view_active_index_get(active_view));
efl_gfx_entity_visible_set(pd->content, EINA_TRUE);
_geom_sync(obj, pd);
}
}
}
EOLIAN static void
_efl_ui_active_view_view_manager_stack_efl_ui_active_view_view_manager_content_add(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Stack_Data *pd, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
efl_canvas_group_member_add(pd->group, subobj);
efl_gfx_entity_visible_set(subobj, EINA_FALSE);
}
EOLIAN static void
_efl_ui_active_view_view_manager_stack_efl_ui_active_view_view_manager_content_del(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Stack_Data *pd, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
efl_canvas_group_member_remove(pd->group, subobj);
}
static void
_setup_anim(Efl_Animation_Player *player, Efl_Gfx_Entity *entity)
{
efl_player_stop(player);
efl_animation_player_target_set(player, entity);
efl_player_start(player);
}
EOLIAN static void
_efl_ui_active_view_view_manager_stack_efl_ui_active_view_view_manager_switch_to(Eo *obj, Efl_Ui_Active_View_View_Manager_Stack_Data *pd, int from, int to)
{
if (from != -1)
{
if (pd->animation)
{
pd->from = from;
pd->to = to;
pd->content = NULL;
_setup_anim(pd->hide, efl_pack_content_get(pd->container, from));
_setup_anim(pd->show, efl_pack_content_get(pd->container, to));
}
else
{
efl_gfx_entity_visible_set(efl_pack_content_get(pd->container, from), EINA_FALSE);
pd->content = efl_pack_content_get(pd->container, to);
efl_gfx_entity_visible_set(pd->content, EINA_TRUE);
}
}
else
{
double pos = to;
pd->content = efl_pack_content_get(pd->container, to);
efl_gfx_entity_visible_set(pd->content, EINA_TRUE);
efl_event_callback_call(obj, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_EVENT_POS_UPDATE, &pos);
}
_geom_sync(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_stack_efl_ui_active_view_view_manager_view_size_set(Eo *obj, Efl_Ui_Active_View_View_Manager_Stack_Data *pd, Eina_Size2D size)
{
pd->page_size = size;
_geom_sync(obj, pd);
}
EOLIAN static void
_efl_ui_active_view_view_manager_stack_efl_object_destructor(Eo *obj, Efl_Ui_Active_View_View_Manager_Stack_Data *pd EINA_UNUSED)
{
efl_event_callback_del(pd->group, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _resize_cb, obj);
efl_event_callback_del(pd->group, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _move_cb, obj);
efl_destructor(efl_super(obj, MY_CLASS));
for (int i = 0; i < efl_content_count(pd->container); ++i)
{
Efl_Gfx_Stack *elem = efl_pack_content_get(pd->container, i);
for (int d = 0; d < 4; d++)
{
efl_gfx_mapping_color_set(elem, d, 255, 255, 255, 255);
}
}
}
static void
_reset_player(Efl_Animation_Player *player, Eina_Bool vis)
{
Efl_Gfx_Entity *obj;
obj = efl_animation_player_target_get(player);
efl_player_stop(player);
efl_animation_player_target_set(player, NULL);
efl_gfx_entity_visible_set(obj, vis);
}
EOLIAN static void
_efl_ui_active_view_view_manager_stack_efl_ui_active_view_view_manager_animation_enabled_set(Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Stack_Data *pd, Eina_Bool animation)
{
_reset_player(pd->hide, EINA_FALSE);
_reset_player(pd->show, EINA_TRUE);
pd->animation = animation;
}
EOLIAN static Eina_Bool
_efl_ui_active_view_view_manager_stack_efl_ui_active_view_view_manager_animation_enabled_get(const Eo *obj EINA_UNUSED, Efl_Ui_Active_View_View_Manager_Stack_Data *pd)
{
return pd->animation;
}
#include "efl_ui_active_view_view_manager_stack.eo.c"

View File

@ -0,0 +1,12 @@
class @beta Efl.Ui.Active_View.View_Manager_Stack extends Efl.Ui.Active_View.View_Manager
{
implements {
Efl.Ui.Active_View.View_Manager.bind;
Efl.Ui.Active_View.View_Manager.content_add;
Efl.Ui.Active_View.View_Manager.content_del;
Efl.Ui.Active_View.View_Manager.switch_to;
Efl.Ui.Active_View.View_Manager.view_size {set;}
Efl.Ui.Active_View.View_Manager.animation_enabled {set; get;}
Efl.Object.destructor;
}
}

View File

@ -154,6 +154,12 @@ pub_eo_files = [
'efl_ui_dnd_container.eo',
'efl_ui_focus_manager_window_root.eo',
'efl_ui_pager.eo',
'efl_ui_active_view_container.eo',
'efl_ui_active_view_view_manager.eo',
'efl_ui_active_view_view_manager_scroll.eo',
'efl_ui_active_view_view_manager_stack.eo',
'efl_ui_active_view_indicator.eo',
'efl_ui_active_view_indicator_icon.eo',
'efl_page_transition.eo',
'efl_page_transition_scroll.eo',
'efl_page_indicator.eo',
@ -230,6 +236,7 @@ priv_eo_files = [
'efl_ui_homogeneous_model.eo',
'efl_ui_exact_model.eo',
'efl_ui_average_model.eo',
'efl_ui_active_view_view_manager_plain.eo',
]
priv_eo_file_target = []
@ -917,6 +924,13 @@ elementary_src = [
'efl_ui_dnd.c',
'elm_focus_legacy.c',
'efl_ui_pager.c',
'efl_ui_active_view_container.c',
'efl_ui_active_view_view_manager.c',
'efl_ui_active_view_view_manager_plain.c',
'efl_ui_active_view_view_manager_scroll.c',
'efl_ui_active_view_view_manager_stack.c',
'efl_ui_active_view_indicator.c',
'efl_ui_active_view_indicator_icon.c',
'efl_page_transition.c',
'efl_page_transition_scroll.c',
'efl_page_indicator.c',

View File

@ -4,6 +4,7 @@
#include "efl_ui_suite.h"
#include "suite_helpers.h"
#include "eo_internal.h"
static const Efl_Test_Case etc[] = {
//{ "elm_focus", elm_test_focus},
@ -24,9 +25,12 @@ static const Efl_Test_Case etc[] = {
{ "efl_ui_layout", efl_ui_test_layout},
{ "Efl_Ui_Model", efl_ui_model },
{ "efl_ui_widget", efl_ui_test_widget },
{ "efl_ui_active_view", efl_ui_test_active_view},
{ NULL, NULL }
};
EFL_CLASS_SIMPLE_CLASS(efl_ui_widget, "efl_ui_widget", EFL_UI_WIDGET_CLASS);
int
main(int argc, char **argv)
{

View File

@ -36,11 +36,15 @@ void efl_ui_test_focus_sub(TCase *tc);
void efl_ui_model(TCase *tc);
void efl_ui_test_widget(TCase *tc);
void efl_ui_test_active_view(TCase *tc);
void loop_timer_interval_set(Eo *obj, double in);
#define efl_loop_timer_interval_set loop_timer_interval_set
const Efl_Class* efl_ui_widget_realized_class_get(void);
#define WIDGET_CLASS efl_ui_widget_realized_class_get()
Eo *win_add();
Eo *win_add_focused();
#endif

View File

@ -0,0 +1,571 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "efl_ui_suite.h"
#include "eo_internal.h"
EFL_CLASS_SIMPLE_CLASS(efl_ui_active_view_view_manager, "efl_ui_active_view_view_manager", EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_CLASS);
EFL_CLASS_SIMPLE_CLASS(efl_ui_active_view_indicator, "efl_ui_active_view_indicator", EFL_UI_ACTIVE_VIEW_INDICATOR_CLASS);
static Efl_Ui_Win *win;
static Efl_Ui_Active_View_Container *container;
static int tree_abort;
static int tree_abort_level;
static void
_shutdown(void)
{
eina_log_abort_on_critical_set(tree_abort);
eina_log_abort_on_critical_level_set(tree_abort_level);
}
static void
_setup(void)
{
tree_abort = eina_log_abort_on_critical_get();
tree_abort_level = eina_log_abort_on_critical_level_get();
eina_log_abort_on_critical_level_set(2);
eina_log_abort_on_critical_set(1);
}
static void
active_view_setup()
{
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
efl_ui_win_type_set(efl_added, EFL_UI_WIN_TYPE_BASIC));
container = efl_add(EFL_UI_ACTIVE_VIEW_CONTAINER_CLASS, win,
efl_content_set(win, efl_added));
efl_gfx_entity_size_set(win, EINA_SIZE2D(200, 200));
}
static void
active_view_teardown()
{
if (win)
{
efl_del(win);
win = NULL;
}
}
typedef struct {
struct {
int called;
double position;
} position_update;
struct {
int called;
Efl_Gfx_Entity *subobj;
int index;
int current_page_at_call;
} content_del;
struct {
int called;
Efl_Gfx_Entity *subobj;
int index;
int current_page_at_call;
} content_add;
struct {
int called;
Efl_Ui_Active_View_Container *active_view;
} active_view;
} Indicator_Calls;
Indicator_Calls indicator_calls = { 0 };
static void
_indicator_content_del(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
indicator_calls.content_del.called ++;
indicator_calls.content_del.subobj = subobj;
indicator_calls.content_del.index = index;
indicator_calls.content_del.current_page_at_call = efl_ui_active_view_active_index_get(container);
}
static void
_indicator_content_add(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
indicator_calls.content_add.called ++;
indicator_calls.content_add.subobj = subobj;
indicator_calls.content_add.index = index;
indicator_calls.content_add.current_page_at_call = efl_ui_active_view_active_index_get(container);
}
static void
_indicator_position_update(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, double position)
{
indicator_calls.position_update.called ++;
indicator_calls.position_update.position = position;
}
static void
_indicator_bind(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Ui_Active_View_Container *active_view)
{
indicator_calls.active_view.called++;
indicator_calls.active_view.active_view = active_view;
}
EFL_OPS_DEFINE(indicator_tracker,
EFL_OBJECT_OP_FUNC(efl_ui_active_view_indicator_content_add, _indicator_content_add),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_indicator_content_del, _indicator_content_del),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_indicator_position_update, _indicator_position_update),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_indicator_bind, _indicator_bind),
);
static Efl_Ui_Active_View_View_Manager*
_create_indicator(void)
{
Eo *obj;
obj = efl_add(efl_ui_active_view_indicator_realized_class_get(), win);
efl_object_override(obj, &indicator_tracker);
return obj;
}
typedef struct {
struct {
int called;
Efl_Gfx_Entity *subobj;
int index;
int current_page_at_call;
} content_del;
struct {
int called;
Efl_Gfx_Entity *subobj;
int index;
int current_page_at_call;
} content_add;
struct {
int called;
int from;
int to;
} request_switch;
struct {
int called;
Eina_Size2D size;
} page_size;
struct {
int called;
Efl_Ui_Active_View_Container *active_view;
Efl_Canvas_Group *group;
} active_view;
struct {
int called;
} animation;
double last_position;
} Transition_Calls;
Transition_Calls transition_calls = { 0 };
static void
_emit_pos(Eo *obj, double d)
{
if (d == transition_calls.last_position) return;
efl_event_callback_call(obj, EFL_UI_ACTIVE_VIEW_VIEW_MANAGER_EVENT_POS_UPDATE, &d);
transition_calls.last_position = d;
}
static void
_transition_content_add(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
transition_calls.content_add.called ++;
transition_calls.content_add.subobj = subobj;
transition_calls.content_add.index = index;
transition_calls.content_add.current_page_at_call = efl_ui_active_view_active_index_get(container);
int i = efl_ui_active_view_active_index_get(container);
if (i != -1)
_emit_pos(obj, i);
}
static void
_transition_content_del(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Gfx_Entity *subobj, int index EINA_UNUSED)
{
transition_calls.content_del.called ++;
transition_calls.content_del.subobj = subobj;
transition_calls.content_del.index = index;
transition_calls.content_del.current_page_at_call = efl_ui_active_view_active_index_get(container);
int i = efl_ui_active_view_active_index_get(container);
if (i != -1)
_emit_pos(obj, i);
}
static void
_transition_request_switch(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, int from, int to)
{
transition_calls.request_switch.called++;
transition_calls.request_switch.from = from;
transition_calls.request_switch.to = to;
_emit_pos(obj, to);
}
static void
_transition_page_size_set(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Eina_Size2D size)
{
transition_calls.page_size.called++;
transition_calls.page_size.size = size;
}
static void
_transition_bind(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Ui_Active_View_Container *active_view, Efl_Canvas_Group *group)
{
transition_calls.active_view.called++;
transition_calls.active_view.active_view = active_view;
transition_calls.active_view.group = group;
}
static void
_transition_animation_set(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Eina_Bool animation)
{
transition_calls.animation.called++;
ck_assert_int_eq(animation, EINA_TRUE);
}
static Eina_Bool
_transition_animation_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
{
return EINA_TRUE;
}
EFL_OPS_DEFINE(transition_tracker,
EFL_OBJECT_OP_FUNC(efl_ui_active_view_view_manager_animation_enabled_set, _transition_animation_set),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_view_manager_animation_enabled_get, _transition_animation_get),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_view_manager_content_add, _transition_content_add),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_view_manager_content_del, _transition_content_del),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_view_manager_switch_to, _transition_request_switch),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_view_manager_view_size_set, _transition_page_size_set),
EFL_OBJECT_OP_FUNC(efl_ui_active_view_view_manager_bind, _transition_bind),
);
static Efl_Ui_Active_View_View_Manager*
_create_transition(void)
{
Eo *obj;
obj = efl_add(efl_ui_active_view_view_manager_realized_class_get(), win);
efl_object_override(obj, &transition_tracker);
return obj;
}
EFL_START_TEST (efl_ui_active_view_init)
{
ck_assert_ptr_ne(container, NULL);
ck_assert_ptr_ne(win, NULL);
ck_assert_ptr_eq(efl_ui_active_view_indicator_get(container), NULL);
ck_assert_ptr_eq(efl_ui_active_view_manager_get(container), NULL);
Eina_Size2D s = efl_ui_active_view_size_get(container);
ck_assert_int_eq(s.w, 0); //FIXME
ck_assert_int_eq(s.h, 0); //FIXME
ck_assert_int_eq(efl_ui_active_view_active_index_get(container), -1);
}
EFL_END_TEST
EFL_START_TEST (efl_ui_active_view_active_index)
{
Efl_Ui_Widget *w = efl_add(WIDGET_CLASS, win);
efl_pack(container, w);
ck_assert_int_eq(efl_ui_active_view_active_index_get(container), 0);
for (int i = -20; i < 20; ++i)
{
if (i == 0) continue;
EXPECT_ERROR_START;
efl_ui_active_view_active_index_set(container, i);
EXPECT_ERROR_END;
}
efl_del(w);
ck_assert_int_eq(efl_ui_active_view_active_index_get(container), -1);
}
EFL_END_TEST
EFL_START_TEST (efl_ui_smart_transition_calls)
{
Efl_Ui_Widget *w, *w1, *w2;
Efl_Ui_Active_View_View_Manager*t = _create_transition();
w = efl_add(WIDGET_CLASS, win);
w1 = efl_add(WIDGET_CLASS, win);
w2 = efl_add(WIDGET_CLASS, win);
efl_ui_active_view_manager_set(container, t);
transition_calls.last_position = -2.0;
ck_assert_int_eq(transition_calls.animation.called, 1);
ck_assert_int_eq(transition_calls.active_view.called, 1);
ck_assert_ptr_eq(transition_calls.active_view.active_view, container);
//We cannot verify group
ck_assert_int_eq(transition_calls.page_size.called, 1);
ck_assert_int_eq(transition_calls.page_size.size.w, 0); //FIXME
ck_assert_int_eq(transition_calls.page_size.size.h, 0); //FIXME
ck_assert_int_eq(transition_calls.request_switch.called, 0);
ck_assert_int_eq(transition_calls.content_add.called, 0);
ck_assert_int_eq(transition_calls.content_del.called, 0);
transition_calls.active_view.called = 0;
transition_calls.page_size.called = 0;
//must update content, and request a switch from -1 to 1
efl_pack(container, w);
ck_assert_int_eq(transition_calls.active_view.called, 0);
ck_assert_int_eq(transition_calls.page_size.called, 0);
ck_assert_int_eq(transition_calls.request_switch.called, 1);
ck_assert_int_eq(transition_calls.request_switch.from, -1);
ck_assert_int_eq(transition_calls.request_switch.to, 0);
ck_assert_int_eq(transition_calls.content_add.called, 1);
ck_assert_int_eq(transition_calls.content_add.index, 0);
ck_assert_ptr_eq(transition_calls.content_add.subobj, w);
ck_assert_int_eq(transition_calls.content_add.current_page_at_call, -1);
ck_assert_int_eq(transition_calls.content_del.called, 0);
transition_calls.content_add.called = 0;
transition_calls.request_switch.called = 0;
//this must update content and a updated current page, but no other call
efl_pack_begin(container, w1);
ck_assert_int_eq(transition_calls.active_view.called, 0);
ck_assert_int_eq(transition_calls.page_size.called, 0);
ck_assert_int_eq(transition_calls.request_switch.called, 0);
ck_assert_int_eq(transition_calls.content_add.called, 1);
ck_assert_int_eq(transition_calls.content_add.index, 0);
ck_assert_ptr_eq(transition_calls.content_add.subobj, w1);
ck_assert_int_eq(transition_calls.content_add.current_page_at_call, 1);
ck_assert_int_eq(transition_calls.content_del.called, 0);
transition_calls.content_add.called = 0;
transition_calls.request_switch.called = 0;
ck_assert_int_eq(efl_ui_active_view_active_index_get(container), 1);
//new object, must update the content and a not update current page
efl_pack_end(container, w2);
ck_assert_int_eq(transition_calls.active_view.called, 0);
ck_assert_int_eq(transition_calls.page_size.called, 0);
ck_assert_int_eq(transition_calls.request_switch.called, 0);
ck_assert_int_eq(transition_calls.content_add.called, 1);
ck_assert_int_eq(transition_calls.content_add.index, 2);
ck_assert_ptr_eq(transition_calls.content_add.subobj, w2);
ck_assert_int_eq(transition_calls.content_add.current_page_at_call, 1);
ck_assert_int_eq(transition_calls.content_del.called, 0);
transition_calls.content_add.called = 0;
ck_assert_int_eq(efl_ui_active_view_active_index_get(container), 1);
//page change must result in a call to request a switch
efl_ui_active_view_active_index_set(container, 2);
ck_assert_int_eq(transition_calls.active_view.called, 0);
ck_assert_int_eq(transition_calls.page_size.called, 0);
ck_assert_int_eq(transition_calls.request_switch.called, 1);
ck_assert_int_eq(transition_calls.request_switch.from, 1);
ck_assert_int_eq(transition_calls.request_switch.to, 2);
ck_assert_int_eq(transition_calls.content_add.called, 0);
ck_assert_int_eq(transition_calls.content_del.called, 0);
transition_calls.request_switch.called = 0;
//deletion of object must result in a content update
efl_del(w);
ck_assert_int_eq(transition_calls.active_view.called, 0);
ck_assert_int_eq(transition_calls.page_size.called, 0);
ck_assert_int_eq(transition_calls.request_switch.called, 0);
ck_assert_int_eq(transition_calls.content_add.called, 0);
ck_assert_int_eq(transition_calls.content_del.called, 1);
ck_assert_int_eq(transition_calls.content_del.index, 1);
ck_assert_ptr_eq(transition_calls.content_del.subobj, w);
ck_assert_int_eq(transition_calls.content_del.current_page_at_call, 1);
transition_calls.content_del.called = 0;
}
EFL_END_TEST
EFL_START_TEST (efl_ui_smart_transition_lifetime)
{
Efl_Ui_Active_View_View_Manager*t, *t1;
t = _create_transition();
efl_wref_add(t, &t);
t1 = _create_transition();
efl_wref_add(t1, &t1);
efl_ui_active_view_manager_set(container, t);
efl_ui_active_view_manager_set(container, t1);
ck_assert_ptr_eq(t, NULL);
}
EFL_END_TEST
static void
_verify_indicator_calls(void)
{
Efl_Ui_Widget *w, *w1, *w2;
w = efl_add(WIDGET_CLASS, win);
w1 = efl_add(WIDGET_CLASS, win);
w2 = efl_add(WIDGET_CLASS, win);
ck_assert_int_eq(indicator_calls.active_view.called, 1);
ck_assert_ptr_eq(indicator_calls.active_view.active_view, container);
ck_assert_int_eq(indicator_calls.content_add.called, 0);
ck_assert_int_eq(indicator_calls.content_del.called, 0);
ck_assert_int_eq(indicator_calls.position_update.called, 0);
indicator_calls.active_view.called = 0;
efl_pack(container, w);
ck_assert_int_eq(indicator_calls.active_view.called, 0);
ck_assert_int_eq(indicator_calls.content_add.called, 1);
ck_assert_int_eq(indicator_calls.content_add.index, 0);
ck_assert_ptr_eq(indicator_calls.content_add.subobj, w);
ck_assert_int_eq(indicator_calls.content_del.called, 0);
ck_assert_int_eq(indicator_calls.position_update.called, 1);
ck_assert(indicator_calls.position_update.position == 0.0);
indicator_calls.content_add.called = 0;
indicator_calls.position_update.called = 0;
efl_pack_begin(container, w1);
ck_assert_int_eq(indicator_calls.active_view.called, 0);
ck_assert_int_eq(indicator_calls.content_add.called, 1);
ck_assert_int_eq(indicator_calls.content_add.index, 0);
ck_assert_ptr_eq(indicator_calls.content_add.subobj, w1);
ck_assert_int_eq(indicator_calls.content_del.called, 0);
ck_assert_int_eq(indicator_calls.position_update.called, 1);
ck_assert(indicator_calls.position_update.position == 1.0);
indicator_calls.content_add.called = 0;
indicator_calls.position_update.called = 0;
efl_pack_end(container, w2);
ck_assert_int_eq(indicator_calls.active_view.called, 0);
ck_assert_int_eq(indicator_calls.content_add.called, 1);
ck_assert_int_eq(indicator_calls.content_add.index, 2);
ck_assert_ptr_eq(indicator_calls.content_add.subobj, w2);
ck_assert_int_eq(indicator_calls.content_del.called, 0);
ck_assert_int_eq(indicator_calls.position_update.called, 0);
indicator_calls.content_add.called = 0;
indicator_calls.position_update.called = 0;
efl_del(w1);
ck_assert_int_eq(indicator_calls.active_view.called, 0);
ck_assert_int_eq(indicator_calls.content_add.called, 0);
ck_assert_int_eq(indicator_calls.content_del.called, 1);
ck_assert_int_eq(indicator_calls.content_del.index, 0);
ck_assert_ptr_eq(indicator_calls.content_del.subobj, w1);
ck_assert_int_eq(indicator_calls.position_update.called, 1);
ck_assert(indicator_calls.position_update.position == 0.0);
indicator_calls.content_del.called = 0;
indicator_calls.position_update.called = 0;
}
EFL_START_TEST (efl_ui_smart_indicator_calls)
{
Efl_Ui_Active_View_View_Manager*i = _create_indicator();
efl_ui_active_view_indicator_set(container, i);
_verify_indicator_calls();
}
EFL_END_TEST
EFL_START_TEST (efl_ui_smart_indicator_transition_calls)
{
Efl_Ui_Active_View_View_Manager *i = _create_indicator();
Efl_Ui_Active_View_View_Manager *t = _create_transition();
transition_calls.last_position = -2.0;
efl_ui_active_view_indicator_set(container, i);
efl_ui_active_view_manager_set(container, t);
_verify_indicator_calls();
}
EFL_END_TEST
Efl_Ui_Active_View_Transition_Event start;
Efl_Ui_Active_View_Transition_Event end;
static void
_start(void *data EINA_UNUSED, const Efl_Event *ev)
{
Efl_Ui_Active_View_Transition_Event *e = ev->info;
memcpy(&start, e, sizeof(Efl_Ui_Active_View_Transition_Event));
}
static void
_end(void *data EINA_UNUSED, const Efl_Event *ev)
{
Efl_Ui_Active_View_Transition_Event *e = ev->info;
memcpy(&end, e, sizeof(Efl_Ui_Active_View_Transition_Event));
}
#define EV_RESET \
start.from = -8; \
start.to = -8; \
end.from = -8; \
end.to = -8;
static void
_verify_transition_start_end_events(void)
{
Efl_Ui_Widget *w, *w1, *w2;
w = efl_add(WIDGET_CLASS, win);
w1 = efl_add(WIDGET_CLASS, win);
w2 = efl_add(WIDGET_CLASS, win);
efl_event_callback_add(container, EFL_UI_ACTIVE_VIEW_EVENT_TRANSITION_START, _start, NULL);
efl_event_callback_add(container, EFL_UI_ACTIVE_VIEW_EVENT_TRANSITION_END, _end, NULL);
EV_RESET
efl_pack_end(container, w);
ck_assert_int_eq(start.to, 0);
ck_assert_int_eq(end.to, 0);
ck_assert_int_eq(start.from, -1);
ck_assert_int_eq(end.from, -1);
EV_RESET
efl_pack_begin(container, w1);
efl_pack_end(container, w2);
ck_assert_int_eq(start.to, -8);
ck_assert_int_eq(end.to, -8);
ck_assert_int_eq(start.from, -8);
ck_assert_int_eq(end.from, -8);
EV_RESET
efl_ui_active_view_active_index_set(container, 2);
ck_assert_int_eq(start.to, 2);
ck_assert_int_eq(end.to, 2);
ck_assert_int_eq(start.from, 1);
ck_assert_int_eq(end.from, 1);
}
EFL_START_TEST (efl_ui_active_view_view_manager_start_end)
{
transition_calls.last_position = -2.0;
_verify_transition_start_end_events();
}
EFL_END_TEST
EFL_START_TEST (efl_ui_active_view_active_index_not_update)
{
efl_ui_active_view_gravity_set(container, EFL_UI_ACTIVE_VIEW_CONTAINER_GRAVITY_INDEX);
for (int i = 0; i < 5; ++i)
{
Efl_Ui_Widget *w = efl_add(WIDGET_CLASS, win);
efl_pack(container, w);
ck_assert_int_eq(efl_ui_active_view_active_index_get(container), 0);
}
efl_del(efl_pack_content_get(container, 0));
ck_assert_int_eq(efl_ui_active_view_active_index_get(container), 0);
}
EFL_END_TEST
void efl_ui_test_active_view(TCase *tc)
{
tcase_add_checked_fixture(tc, _setup, _shutdown);
tcase_add_checked_fixture(tc, active_view_setup, active_view_teardown);
tcase_add_test(tc, efl_ui_active_view_init);
tcase_add_test(tc, efl_ui_active_view_active_index);
tcase_add_test(tc, efl_ui_smart_transition_calls);
tcase_add_test(tc, efl_ui_smart_transition_lifetime);
tcase_add_test(tc, efl_ui_smart_indicator_calls);
tcase_add_test(tc, efl_ui_smart_indicator_transition_calls);
tcase_add_test(tc, efl_ui_active_view_view_manager_start_end);
tcase_add_test(tc, efl_ui_active_view_active_index_not_update);
}

View File

@ -9,8 +9,6 @@
#include "eo_internal.h"
#include "suite_helpers.h"
EFL_CLASS_SIMPLE_CLASS(efl_ui_widget, "efl_ui_widget", EFL_UI_WIDGET_CLASS)
typedef struct {
Efl_Ui_Widget *btn1, *btn2;
Efl_Ui_Widget *box;

View File

@ -138,6 +138,7 @@ efl_ui_suite_src = [
'efl_ui_suite.h',
'efl_ui_model.c',
'efl_ui_test_widget.c',
'efl_ui_test_active_view.c',
]
efl_ui_suite = executable('efl_ui_suite',

View File

@ -9,7 +9,7 @@
/* spec-meta-start
{"test-interface":"Efl.Pack_Linear",
"test-widgets": ["Efl.Ui.Box", "Efl.Ui.Grid", "Efl.Ui.Pager"],
"test-widgets": ["Efl.Ui.Box", "Efl.Ui.Grid", "Efl.Ui.Pager", "Efl.Ui.Active_View.Container"],
"custom-mapping" : {
"Efl.Ui.Grid" : "EFL_UI_GRID_DEFAULT_ITEM_CLASS"
}