elementary: introduce a new widget - elm_animation_view

Elm_Animation_View is designed to display Efl_Canvas_Vg Animation (Lottie),

has a set of animation control functions.

@feature
This commit is contained in:
Hermet Park 2019-01-10 15:32:07 +09:00
parent bcdc48b326
commit d4abf223bd
8 changed files with 876 additions and 0 deletions

View File

@ -196,6 +196,7 @@ elm_legacy_eolian_files = \
lib/elementary/efl_ui_win_socket_legacy.eo \
lib/elementary/efl_ui_win_inlined_legacy.eo \
lib/elementary/elm_interface_fileselector.eo \
lib/elementary/elm_animation_view.eo \
lib/elementary/elm_calendar.eo \
lib/elementary/elm_calendar_item.eo \
lib/elementary/elm_clock.eo \
@ -331,6 +332,7 @@ lib/elementary/Elementary_Cursor.h
includesdir = $(includedir)/elementary-@VMAJ@
includesunstable_HEADERS = \
lib/elementary/elm_widget_animation_view.h \
lib/elementary/elm_gen_common.h \
lib/elementary/elm_atspi_bridge.h \
lib/elementary/efl_access_object.h \
@ -485,6 +487,8 @@ includesub_HEADERS = \
lib/elementary/elm_access.h \
lib/elementary/elm_actionslider.h \
lib/elementary/elm_actionslider_legacy.h \
lib/elementary/elm_animation_view.h \
lib/elementary/elm_animation_view_legacy.h \
lib/elementary/elm_app.h \
lib/elementary/elm_atspi_app_object.h \
lib/elementary/elm_authors.h \
@ -692,6 +696,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/elc_scrolled_entry.c \
lib/elementary/elm_access.c \
lib/elementary/elm_actionslider.c \
lib/elementary/elm_animation_view.c \
lib/elementary/elm_atspi_app_object.c \
lib/elementary/elm_atspi_bridge.c \
lib/elementary/efl_ui_legacy.c \

View File

@ -223,6 +223,7 @@ typedef Eo Efl_Ui_Focus_Manager;
#include <elm_diskselector.h>
//#include <elm_factory.h>
#include <elm_animation_view.h>
#include <elm_finger.h>
#include <elm_flip.h>
#include <elm_flipselector.h>

View File

@ -0,0 +1,570 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_ACCESS_OBJECT_PROTECTED
#include <Elementary.h>
#include "elm_priv.h"
#include "elm_widget_animation_view.h"
#define MY_CLASS ELM_ANIMATION_VIEW_CLASS
#define MY_CLASS_NAME "Elm_Animation_View"
#define MY_CLASS_NAME_LEGACY "elm_animation_view"
static const char SIG_FOCUSED[] = "focused";
static const char SIG_UNFOCUSED[] = "unfocused";
static const char SIG_PLAY_START[] = "play,start";
static const char SIG_PLAY_REPEAT[] = "play,repeat";
static const char SIG_PLAY_DONE[] = "play,done";
static const char SIG_PLAY_PAUSE[] = "play,pause";
static const char SIG_PLAY_RESUME[] = "play,resume";
static const char SIG_PLAY_STOP[] = "play,stop";
static const char SIG_PLAY_UPDATE[] = "play,update";
/* smart callbacks coming from Elm_Animation_View objects: */
static const Evas_Smart_Cb_Description _smart_callbacks[] = {
{SIG_FOCUSED, ""},
{SIG_UNFOCUSED, ""},
{SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
{SIG_PLAY_START, ""},
{SIG_PLAY_REPEAT, ""},
{SIG_PLAY_DONE, ""},
{SIG_PLAY_PAUSE, ""},
{SIG_PLAY_RESUME, ""},
{SIG_PLAY_STOP, ""},
{NULL, NULL}
};
static void
_sizing_eval(void *data)
{
Elm_Animation_View_Data *pd = data;
if (!pd->file) return;
double hw,hh;
efl_gfx_size_hint_weight_get(pd->obj, &hw, &hh);
Eina_Size2D size = efl_canvas_vg_object_default_size_get(pd->vg);
Eina_Size2D min = {-1, -1};
if (hw == 0) min.w = size.w;
if (hh == 0) min.h = size.h;
efl_gfx_size_hint_min_set(pd->obj, min);
}
static void
_size_hint_event_cb(void *data, const Efl_Event *event EINA_UNUSED)
{
_sizing_eval(data);
}
static void
_transit_go_facade(Elm_Animation_View_Data *pd)
{
pd->repeat_times = 0;
elm_transit_go(pd->transit);
evas_object_smart_callback_call(pd->obj, SIG_PLAY_START, NULL);
}
static Eina_Bool
_visible_check(Eo *obj)
{
if (!efl_gfx_entity_visible_get(obj)) return EINA_FALSE;
//TODO: Check Smart parents visibilities?
Eina_Size2D size = efl_gfx_entity_size_get(obj);
if (size.w == 0 || size.h == 0) return EINA_FALSE;
Evas_Coord output_w, output_h;
evas_output_size_get(evas_object_evas_get(obj), &output_w, &output_h);
Eina_Position2D pos = efl_gfx_entity_position_get(obj);
//Outside viewport
if ((pos.x + size.w < 0) || (pos.x > output_w) ||
(pos.y + size.h < 0) || (pos.y > output_h))
return EINA_FALSE;
//Inside viewport
return EINA_TRUE;
}
static void
_auto_play(Elm_Animation_View_Data *pd, Eina_Bool vis)
{
if (!pd->auto_play || !pd->transit) return;
//Resume Animation
if (vis)
{
if (pd->state == ELM_ANIMATION_VIEW_STATE_PAUSE && pd->auto_play_pause)
{
elm_transit_paused_set(pd->transit, EINA_FALSE);
if (pd->play_back)
pd->state = ELM_ANIMATION_VIEW_STATE_PLAY_BACK;
else
pd->state = ELM_ANIMATION_VIEW_STATE_PLAY;
pd->auto_play_pause = EINA_FALSE;
evas_object_smart_callback_call(pd->obj, SIG_PLAY_RESUME, NULL);
}
}
//Pause Animation
else
{
if ((pd->state == ELM_ANIMATION_VIEW_STATE_PLAY) ||
(pd->state == ELM_ANIMATION_VIEW_STATE_PLAY_BACK))
{
elm_transit_paused_set(pd->transit, EINA_TRUE);
pd->state = ELM_ANIMATION_VIEW_STATE_PAUSE;
pd->auto_play_pause = EINA_TRUE;
evas_object_smart_callback_call(pd->obj, SIG_PLAY_PAUSE, NULL);
}
}
}
static void
_transit_del_cb(Elm_Transit_Effect *effect, Elm_Transit *transit)
{
Elm_Animation_View_Data *pd = (Elm_Animation_View_Data *) effect;
if ((pd->state == ELM_ANIMATION_VIEW_STATE_PLAY && pd->keyframe == 1) ||
(pd->state == ELM_ANIMATION_VIEW_STATE_PLAY_BACK && pd->keyframe == 0))
evas_object_smart_callback_call(pd->obj, SIG_PLAY_DONE, NULL);
if (pd->transit != transit) return;
Elm_Animation_View_State prev_state = pd->state;
pd->state = ELM_ANIMATION_VIEW_STATE_STOP;
pd->transit = NULL;
pd->auto_play_pause = EINA_FALSE;
if (prev_state != ELM_ANIMATION_VIEW_STATE_STOP)
{
evas_object_smart_callback_call(pd->obj, SIG_PLAY_STOP, NULL);
pd->keyframe = 0;
}
}
static void
_transit_cb(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
{
Elm_Animation_View_Data *pd = (Elm_Animation_View_Data *) effect;
if (!pd->vg)
{
ERR("Vector Object is removed in wrong way!, Elm_Animation_View = %p", pd->obj);
elm_transit_del(transit);
return;
}
if (pd->play_back)
{
pd->state = ELM_ANIMATION_VIEW_STATE_PLAY_BACK;
progress = 1 - progress;
}
else pd->state = ELM_ANIMATION_VIEW_STATE_PLAY;
pd->keyframe = progress;
evas_object_vg_animated_frame_set(pd->vg, (int) (pd->frame_cnt * progress));
if (pd->auto_repeat)
{
int repeat_times = elm_transit_current_repeat_times_get(pd->transit);
if (pd->repeat_times != repeat_times)
{
evas_object_smart_callback_call(pd->obj, SIG_PLAY_REPEAT, NULL);
pd->repeat_times = repeat_times;
}
}
evas_object_smart_callback_call(pd->obj, SIG_PLAY_UPDATE, NULL);
}
EOLIAN static void
_elm_animation_view_efl_canvas_group_group_add(Eo *obj, Elm_Animation_View_Data *priv)
{
efl_canvas_group_add(efl_super(obj, MY_CLASS));
elm_widget_sub_object_parent_add(obj);
// Create vg to render vector animation
Eo *vg = evas_object_vg_add(evas_object_evas_get(obj));
elm_widget_resize_object_set(obj, vg);
efl_event_callback_add(obj, EFL_GFX_ENTITY_EVENT_CHANGE_SIZE_HINTS, _size_hint_event_cb, priv);
priv->vg = vg;
priv->speed = 1;
priv->frame_duration = 0;
}
EOLIAN static void
_elm_animation_view_efl_canvas_group_group_del(Eo *obj, Elm_Animation_View_Data *pd EINA_UNUSED)
{
if (pd->file) eina_stringshare_del(pd->file);
if (pd->transit)
{
pd->transit = NULL; //Skip perform transit_del_cb()
elm_transit_del(pd->transit);
}
pd->state = ELM_ANIMATION_VIEW_STATE_NOT_READY;
efl_canvas_group_del(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_elm_animation_view_efl_object_destructor(Eo *obj,
Elm_Animation_View_Data *pd EINA_UNUSED)
{
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static Eo *
_elm_animation_view_efl_object_constructor(Eo *obj,
Elm_Animation_View_Data *pd)
{
pd->obj = obj = efl_constructor(efl_super(obj, MY_CLASS));
efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
return obj;
}
static Eina_Bool
_ready_play(Elm_Animation_View_Data *pd)
{
pd->auto_play_pause = EINA_FALSE;
pd->state = ELM_ANIMATION_VIEW_STATE_STOP;
if (pd->transit) elm_transit_del(pd->transit);
pd->frame_cnt = (double) evas_object_vg_animated_frame_count_get(pd->vg);
pd->frame_duration = evas_object_vg_animated_frame_duration_get(pd->vg, 0, 0);
evas_object_vg_animated_frame_set(pd->vg, 0);
if (pd->frame_duration > 0)
{
Elm_Transit *transit = elm_transit_add();
elm_transit_object_add(transit, pd->vg);
if (pd->auto_repeat) elm_transit_repeat_times_set(transit, -1);
elm_transit_duration_set(transit, pd->frame_duration * (1/pd->speed));
elm_transit_effect_add(transit, _transit_cb, pd, _transit_del_cb);
elm_transit_progress_value_set(transit, pd->keyframe);
elm_transit_objects_final_state_keep_set(transit, EINA_TRUE);
pd->transit = transit;
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_elm_animation_view_efl_file_file_set(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd, const char *file, const char *key)
{
if (!evas_object_vg_file_set(pd->vg, file, key)) return EINA_FALSE;
if (pd->file) eina_stringshare_del(pd->file);
pd->file = eina_stringshare_add(file);
pd->keyframe = 0;
_sizing_eval(pd);
if (!pd->file)
{
pd->state = ELM_ANIMATION_VIEW_STATE_NOT_READY;
pd->frame_cnt = 0;
pd->frame_duration = 0;
if (pd->transit) elm_transit_del(pd->transit);
return EINA_FALSE;
}
if (!_ready_play(pd)) return EINA_TRUE;
if (pd->auto_play)
{
_transit_go_facade(pd);
if (!_visible_check(obj))
{
elm_transit_paused_set(pd->transit, EINA_TRUE);
pd->state = ELM_ANIMATION_VIEW_STATE_PAUSE;
pd->auto_play_pause = EINA_TRUE;
evas_object_smart_callback_call(pd->obj, SIG_PLAY_PAUSE, NULL);
}
}
return EINA_TRUE;
}
EOLIAN static void
_elm_animation_view_efl_gfx_entity_position_set(Eo *obj,
Elm_Animation_View_Data *pd,
Eina_Position2D pos EINA_UNUSED)
{
if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
return;
efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
_auto_play(pd, _visible_check(obj));
}
EOLIAN static void
_elm_animation_view_efl_gfx_entity_size_set(Eo *obj,
Elm_Animation_View_Data *pd,
Eina_Size2D size)
{
if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, size.w, size.h))
return;
efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), size);
_sizing_eval(pd);
_auto_play(pd, _visible_check(obj));
}
EOLIAN static void
_elm_animation_view_efl_gfx_entity_visible_set(Eo *obj,
Elm_Animation_View_Data *pd,
Eina_Bool vis)
{
if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
return;
efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
_auto_play(pd, _visible_check(obj));
}
EOLIAN static void
_elm_animation_view_auto_repeat_set(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd, Eina_Bool auto_repeat)
{
if (pd->auto_repeat == auto_repeat) return;
pd->auto_repeat = auto_repeat;
if (pd->transit)
{
if (auto_repeat) elm_transit_repeat_times_set(pd->transit, -1);
else elm_transit_repeat_times_set(pd->transit, 0);
}
}
EOLIAN static Eina_Bool
_elm_animation_view_auto_repeat_get(const Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
return pd->auto_repeat;
}
EOLIAN static void
_elm_animation_view_auto_play_set(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd,
Eina_Bool auto_play)
{
pd->auto_play = auto_play;
if (!auto_play) pd->auto_play_pause = EINA_FALSE;
}
EOLIAN static Eina_Bool
_elm_animation_view_auto_play_get(const Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
return pd->auto_play;
}
EOLIAN static Eina_Bool
_elm_animation_view_play(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
if (pd->state == ELM_ANIMATION_VIEW_STATE_PLAY) return EINA_FALSE;
Eina_Bool rewind = EINA_FALSE;
if (pd->state == ELM_ANIMATION_VIEW_STATE_PLAY_BACK) rewind = EINA_TRUE;
pd->play_back = EINA_FALSE;
pd->auto_play_pause = EINA_FALSE;
if (!pd->file) return EINA_FALSE;
if (!pd->transit && !_ready_play(pd)) return EINA_FALSE;
if (pd->state == ELM_ANIMATION_VIEW_STATE_STOP)
_transit_go_facade(pd);
else if (rewind)
elm_transit_progress_value_set(pd->transit, pd->keyframe);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_elm_animation_view_stop(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
if (!pd->transit) return EINA_FALSE;
if ((pd->state == ELM_ANIMATION_VIEW_STATE_NOT_READY) ||
(pd->state == ELM_ANIMATION_VIEW_STATE_STOP))
return EINA_FALSE;
evas_object_vg_animated_frame_set(pd->vg, 0);
pd->keyframe = 0;
pd->state = ELM_ANIMATION_VIEW_STATE_STOP;
evas_object_smart_callback_call(pd->obj, SIG_PLAY_STOP, NULL);
elm_transit_del(pd->transit);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_elm_animation_view_pause(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
if (!pd->transit) return EINA_FALSE;
if ((pd->state == ELM_ANIMATION_VIEW_STATE_PLAY) ||
(pd->state == ELM_ANIMATION_VIEW_STATE_PLAY_BACK))
{
elm_transit_paused_set(pd->transit, EINA_TRUE);
pd->state = ELM_ANIMATION_VIEW_STATE_PAUSE;
pd->auto_play_pause = EINA_FALSE;
evas_object_smart_callback_call(pd->obj, SIG_PLAY_PAUSE, NULL);
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_elm_animation_view_resume(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
if (!pd->transit) return EINA_FALSE;
if (pd->state == ELM_ANIMATION_VIEW_STATE_PAUSE)
{
elm_transit_paused_set(pd->transit, EINA_FALSE);
if (pd->play_back)
pd->state = ELM_ANIMATION_VIEW_STATE_PLAY_BACK;
else
pd->state = ELM_ANIMATION_VIEW_STATE_PLAY;
pd->auto_play_pause = EINA_FALSE;
evas_object_smart_callback_call(pd->obj, SIG_PLAY_RESUME, NULL);
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_elm_animation_view_play_back(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
if (pd->state == ELM_ANIMATION_VIEW_STATE_PLAY_BACK) return EINA_FALSE;
Eina_Bool rewind = EINA_FALSE;
if (pd->state == ELM_ANIMATION_VIEW_STATE_PLAY) rewind = EINA_TRUE;
pd->play_back = EINA_TRUE;
pd->auto_play_pause = EINA_FALSE;
if (!pd->file) return EINA_FALSE;
if (!pd->transit && !_ready_play(pd)) return EINA_FALSE;
if (pd->state == ELM_ANIMATION_VIEW_STATE_STOP)
_transit_go_facade(pd);
else if (rewind)
elm_transit_progress_value_set(pd->transit, 1 - pd->keyframe);
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_elm_animation_view_speed_set(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd, double speed)
{
if (speed <= 0) return EINA_FALSE;
pd->speed = speed;
if (pd->transit)
elm_transit_duration_set(pd->transit, pd->frame_duration * (1/pd->speed));
return EINA_TRUE;
}
EOLIAN static void
_elm_animation_view_keyframe_set(Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd, double keyframe)
{
if (keyframe < 0) keyframe = 0;
else if (keyframe > 1) keyframe = 1;
if (pd->keyframe == keyframe) return;
pd->keyframe = keyframe;
if (pd->frame_cnt > 0)
evas_object_vg_animated_frame_set(pd->vg, (int) (pd->frame_cnt * keyframe));
if (pd->transit)
{
if (pd->play_back)
elm_transit_progress_value_set(pd->transit, 1 - keyframe);
else
elm_transit_progress_value_set(pd->transit, keyframe);
}
}
EOLIAN static double
_elm_animation_view_keyframe_get(const Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
return pd->keyframe;
}
EOLIAN static double
_elm_animation_view_speed_get(const Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
return pd->speed;
}
EOLIAN static double
_elm_animation_view_duration_time_get(const Eo *obj EINA_UNUSED, Elm_Animation_View_Data *pd)
{
return pd->frame_duration;
}
EOLIAN static Eina_Size2D
_elm_animation_view_default_size_get(const Eo *obj EINA_UNUSED,
Elm_Animation_View_Data *pd EINA_UNUSED)
{
return efl_canvas_vg_object_default_size_get(pd->vg);
}
EAPI Elm_Animation_View*
elm_animation_view_add(Evas_Object *parent)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
return elm_legacy_add(MY_CLASS, parent);
}
EAPI Eina_Bool
elm_animation_view_file_set(Elm_Animation_View *obj, const char *file, const char *key)
{
return efl_file_set(obj, file, key);
}
EAPI Elm_Animation_View_State
elm_animation_view_state_get(const Elm_Animation_View *obj)
{
ELM_ANIMATION_VIEW_DATA_GET(obj, pd);
if (!pd) return ELM_ANIMATION_VIEW_STATE_NOT_READY;
return pd->state;
}
EAPI Eina_Bool
elm_animation_view_is_playing_back(const Elm_Animation_View *obj)
{
ELM_ANIMATION_VIEW_DATA_GET(obj, pd);
if (!pd) return EINA_FALSE;
return pd->play_back;
}
/* Internal EO APIs and hidden overrides */
#define ELM_ANIMATION_VIEW_EXTRA_OPS \
EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_animation_view)
#include "elm_animation_view.eo.c"

View File

@ -0,0 +1,148 @@
class Elm.Animation_View (Efl.Ui.Widget, Efl.Gfx.View, Efl.Ui.Legacy, Efl.File)
{
[[Elementary Animation View class]]
legacy_prefix: elm_animation_view;
eo_prefix: elm_obj_animation_view;
event_prefix: elm_animation_view;
methods {
@property auto_play {
[[Animation will be started automatically when it's possible.
If $auto_play is $true, animation will be started when it's readied.
The condition of auto play is when animation view opened file successfully,
yet to play it plus when the object is visible.
If animation view is disabled, invisible,
it turns to pause state then resume animation when it's visible again.
Warning: This auto play will be only affected to the next animation source.
So must be called before elm_animation_view_file_set().]]
set {
}
get {
}
values {
auto_play: bool; [[$true Enable auto play mode, disable otherwise]]
}
}
@property auto_repeat {
[[Turn on/off animation looping.
If $auto_repeat is $true, it repeats animation when animation frame is reached to
end. This auto repeat mode is valid to both play and play_back cases.]]
set {
}
get {
}
values {
auto_repeat: bool; [[Enable loop mode if $true, disable otherwise]]
}
}
@property speed {
[[Control animation speed.
Control animation speed by multiplying $speed value. If you want to play
animation double-time faster, you can give $speed 2. If you want to play
animation double-time slower, you can give $speed 0.5.
Warning: speed must be greater than zero.]]
set {
return: bool; [[$true when it's successful. $false otherwise.]]
}
get {
}
values {
speed: double; [[ Speed factor. Default value is 1]]
}
}
@property duration_time {
[[Get the duration of animation in seconds.
This API returns total duration time of current animation in the seconds.
If current animation source isn't animatable, it returns zero.]]
get {
}
values {
frame_duration: double; [[duration time in the seconds]]
}
}
@property keyframe {
[[Set current keyframe position of animation view.
When you required to jump on a certain frame instantly,
you can change current keyframe by using this API.
Warning: The range of keyframe is 0 ~ 1.]]
set {
}
get {
}
values {
keyframe: double; [[Keyframe position. Value must be 0 ~ 1.]]
}
}
play {
[[Play animation one time instantly when it's available.
If current keyframe is on a certain position by playing back, this will
play forward from there.
Warning: Play request will be ignored if animation source is not set yet or
animation is paused state or it's already on playing.]]
return: bool; [[$true when it's successful. $false otherwise.]]
}
play_back {
[[Play back animation one time instantly when it's available.
If current keyframe is on a certain position by playing, this will
play backward from there.
Warning: Play back request will be ignored if animation source is not set yet or
animation is paused state or it's already on playing back.]]
return: bool; [[$true when it's successful. $false otherwise.]]
}
pause {
[[Pause current animation instantly.
Once animation is paused, animation view must get resume to play continue again.
Warning: Animation must be on playing or playing back status.]]
return: bool; [[$true when it's successful. $false otherwise.]]
}
resume {
[[Resume paused animation to continue animation.
Warning: This resume must be called on animation paused status. ]]
return: bool; [[$true when it's successful. $false otherwise.]]
}
stop {
[[Stop playing animation.
Stop animation instatly regardless of it's status and reset to
show first frame of animation. Even though current animation is paused,
the animation status will be stopped.]]
return: bool; [[$true when it's successful. $false otherwise.]]
}
@property default_size {
get {
[[Get the default view size that specified from vector resource.
@since 1.22]]
}
values {
size: Eina.Size2D;
}
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.File.file { set; }
Efl.Gfx.Entity.visible { set; }
Efl.Gfx.Entity.position { set; }
Efl.Gfx.Entity.size { set; }
}
}

View File

@ -0,0 +1,36 @@
/**
* @defgroup Elm_Animation_View Animation_View
* @ingroup Elementary
*
* Animation_View widget is designed to show and play animation of
* vector graphics based content. It hides all efl_canvas_vg details
* but just open an API to read vector data from file. Also, it implements
* details of animation control methods of Vector.
*
* Vector data could contain static or animatable vector elements including
* animation infomation. Currently approved vector data file format is svg, json and eet.
* Only json(known for Lottie file as well) and eet could contains animation infomation,
* currently Animation_View is supporting.
*
* This widget emits the following signals, besides the ones sent from
* @ref Animation_View:
* @li "play,start": animation is just started.
* @li "play,repeat": animation is just repeated.
* @li "play,done": animation is just finished.
* @li "play,pause": animation is just paused.
* @li "play,resume": animation is just resumed.
* @li "play,stop": animation is just stopped.
* @li "play,update": animation is updated to the next frame.
*
*/
/**
* @ingroup Elm_Animation_View
*/
#ifndef EFL_NOLEGACY_API_SUPPORT
#include "elm_animation_view_legacy.h"
#endif
/**
* @}
*/

View File

@ -0,0 +1,71 @@
typedef Eo Elm_Animation_View;
typedef enum
{
ELM_ANIMATION_VIEW_STATE_NOT_READY, /*< Animation is not ready to play. (Probably, it didn't file set yet or failed to read file. @since 1.22 @ingroup Elm_Animation_View */
ELM_ANIMATION_VIEW_STATE_PLAY, /*< Animation is on playing. @see elm_animation_play() @since 1.22 @ingroup Elm_Animation_View */
ELM_ANIMATION_VIEW_STATE_PLAY_BACK, /*< Animation is on playing back (rewinding). @see elm_animation_back() @since 1.22 @ingroup Elm_Animation_View */
ELM_ANIMATION_VIEW_STATE_PAUSE, /*< Animation has been paused. To continue animation, call elm_animation_view_resume(). @see elm_animation_pause() @since 1.22 @ingroup Elm_Animation_View */
ELM_ANIMATION_VIEW_STATE_STOP /*< Animation view successfully loaded a file then readied for playing. Otherwise after finished animation or stopped forcely by request. @see elm_animation_stop() @since 1.22 @ingroup Elm_Animation_View */
} Elm_Animation_View_State;
/**
* Add a new animation view widget to the parent's canvas
*
* @param parent The parent object
* @return The new animation view object or @c NULL if it failed to create.
*
* @ingroup Elm_Animation_View
*
* @since 1.22
*/
EAPI Elm_Animation_View *elm_animation_view_add(Evas_Object *parent);
/**
*
* Set the source file from where an vector object must fetch the real
* vector data (it may be one of json, svg, eet files).
*
* If the file supports multiple data stored in it (as Eet files do),
* you can specify the key to be used as the index of the vector in
* this file.
*
* @param[in] file The vector file path.
* @param[in] key The vector key in @p file (if its an Eet one), or @c
NULL, otherwise.
*
* @return @c EINA_TRUE if it's succeed to read file, @c EINA_FALSE otherwise.
*
* @ingroup Elm_Animation_View
*
* @since 1.22
*/
EAPI Eina_Bool elm_animation_view_file_set(Elm_Animation_View *obj, const char *file, const char *key);
/**
* @brief Get current animation view state.
*
* @return Current animation view state
*
* @see Elm_Animation_View_State
*
* @ingroup Elm_Animation_View
*
* @since 1.22
*/
EAPI Elm_Animation_View_State elm_animation_view_state_get(const Elm_Animation_View *obj);
/**
* @brief Returns the status whether current animation is on playing forward or backward.
*
* @return @c EINA_TRUE, if animation on playing back, @c EINA_FALSE otherwise.
*
* @ingroup Elm_Animation_View
*
* @warning If animation view is not on playing, it will return @c EINA_FALSE.
*
* @since 1.22
*/
EAPI Eina_Bool elm_animation_view_is_playing_back(const Elm_Animation_View *obj);
#include "elm_animation_view.eo.legacy.h"

View File

@ -0,0 +1,40 @@
#ifndef ELM_WIDGET_ANIMATION_VIEW_H
#define ELM_WIDGET_ANIMATION_VIEW_H
#include "Elementary.h"
#include "elm_animation_view.eo.h"
typedef struct _Elm_Animation_View_Data Elm_Animation_View_Data;
struct _Elm_Animation_View_Data
{
Eo* obj; //Elm_Animation_View Object
Eo* vg; //Evas_Object_Vg
Elm_Animation_View_State state;
Elm_Transit *transit;
Eina_Stringshare *file;
double speed;
double keyframe;
double frame_cnt;
int repeat_times;
double frame_duration;
Eina_Bool play_back : 1;
Eina_Bool auto_play : 1;
Eina_Bool auto_play_pause: 1;
Eina_Bool auto_repeat : 1;
};
#define ELM_ANIMATION_VIEW_DATA_GET(o, sd) \
Elm_Animation_View_Data * sd = efl_data_scope_get(o, ELM_ANIMATION_VIEW_CLASS)
#define ELM_ANIMATION_VIEW_DATA_GET_OR_RETURN(o, ptr) \
ELM_ANIMATION_VIEW_DATA_GET(o, ptr); \
if (EINA_UNLIKELY(!ptr)) \
{ \
ERR("No widget data for object %p (%s)", \
o, evas_object_type_get(o)); \
return; \
}
#endif

View File

@ -17,6 +17,7 @@ pub_legacy_eo_files = [
'efl_ui_win_socket_legacy.eo',
'efl_ui_win_inlined_legacy.eo',
'elm_interface_fileselector.eo',
'elm_animation_view.eo',
'elm_calendar.eo',
'elm_calendar_item.eo',
'elm_clock.eo',
@ -391,6 +392,7 @@ elementary_headers_unstable = [
'elm_widget_flipselector.h',
'efl_ui_widget_frame.h',
'efl_ui_stack_private.h',
'elm_widget_animation_view.h',
'elm_widget_gengrid.h',
'elm_widget_genlist.h',
'elm_widget_glview.h',
@ -504,6 +506,8 @@ elementary_pub_headers = [
'elc_naviframe_common.h',
'elc_popup.h',
'elc_popup_legacy.h',
'elm_animation_view.h',
'elm_animation_view_legacy.h',
'elm_access.h',
'elm_actionslider.h',
'elm_actionslider_legacy.h',
@ -714,6 +718,7 @@ elementary_src = [
'elc_popup.c',
'elc_scrolled_entry.c',
'elm_access.c',
'elm_animation_view.c',
'elm_actionslider.c',
'elm_atspi_app_object.c',
'elm_atspi_bridge.c',