/*
* Copyright(c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace Tizen.NUI
{
using System;
using System.Runtime.InteropServices;
using Tizen.NUI.BaseComponents;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml;
using Tizen.NUI.Binding.Internals;
using Tizen.NUI.Binding;
using System.Globalization;
using Tizen.NUI.Xaml.Internals;
///
/// Animation can be used to animate the properties of any number of objects, typically view.
/// If the "Finished" event is connected to a member function of an object, it must be disconnected before the object is destroyed.
/// This is typically done in the object destructor, and requires either the animation handle to be stored.
/// The overall animation time is superseded by the values given in the animation time used when calling the AnimateTo(), AnimateBy(), AnimateBetween() and AnimatePath() methods.
/// If any of the individual calls to those functions exceeds the overall animation time (Duration), then the overall animation time is automatically extended.
///
/// 3
public class Animation : BaseHandle
{
private global::System.Runtime.InteropServices.HandleRef swigCPtr;
internal Animation(global::System.IntPtr cPtr, bool cMemoryOwn) : base(NDalicPINVOKE.Animation_SWIGUpcast(cPtr), cMemoryOwn)
{
swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
_animationFinishedEventCallback = OnFinished;
_finishedCallbackOfNative = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(_animationFinishedEventCallback);
}
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Animation obj)
{
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
}
///
/// To make animation instance be disposed.
///
/// 3
protected override void Dispose(DisposeTypes type)
{
if (this != null)
{
if (_animationFinishedEventCallback != null)
{
FinishedSignal().Disconnect(_finishedCallbackOfNative);
}
if (_animationProgressReachedEventCallback != null)
{
ProgressReachedSignal().Disconnect(_animationProgressReachedEventCallback);
}
}
if(disposed)
{
return;
}
if(type == DisposeTypes.Explicit)
{
//Called by User
//Release your own managed resources here.
//You should release all of your own disposable objects here.
}
else if(type == DisposeTypes.Implicit)
{
}
if (this != null)
{
this.Clear();
}
//Release your own unmanaged resources here.
//You should not access any managed member here except static instance.
//because the execution order of Finalizes is non-deterministic.
if (swigCPtr.Handle != global::System.IntPtr.Zero)
{
if (swigCMemOwn)
{
swigCMemOwn = false;
NDalicPINVOKE.delete_Animation(swigCPtr);
}
swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
base.Dispose(type);
}
///
/// Creates an initialized animation.
/// The animation will not loop.
/// The default end action is "Cancel".
/// The default alpha function is linear.
///
/// DurationmSeconds must be greater than zero.
/// The duration in milliseconds.
/// 3
public Animation(int durationMilliSeconds) : this(NDalicPINVOKE.Animation_New((float)durationMilliSeconds / 1000.0f), true)
{
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
private AnimationFinishedEventCallbackType _animationFinishedEventCallback;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void AnimationFinishedEventCallbackType(IntPtr data);
private event EventHandler _animationFinishedEventHandler;
private System.IntPtr _finishedCallbackOfNative;
/**
* @brief Event for the finished signal which can be used to subscribe or unsubscribe the event handler.
* The finished signal is emitted when an animation's animations have finished.
*/
/// 3
public event EventHandler Finished
{
add
{
if (_animationFinishedEventHandler == null && disposed == false)
{
FinishedSignal().Connect(_finishedCallbackOfNative);
}
_animationFinishedEventHandler += value;
}
remove
{
_animationFinishedEventHandler -= value;
if (_animationFinishedEventHandler == null && FinishedSignal().Empty() == false)
{
FinishedSignal().Disconnect(_finishedCallbackOfNative);
}
}
}
private void OnFinished(IntPtr data)
{
if (_animationFinishedEventHandler != null)
{
//here we send all data to user event handlers
_animationFinishedEventHandler(this, null);
}
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void AnimationProgressReachedEventCallbackType(IntPtr data);
private AnimationProgressReachedEventCallbackType _animationProgressReachedEventCallback;
private event EventHandler _animationProgressReachedEventHandler;
/**
* @brief Event for the ProgressReached signal, which can be used to subscribe or unsubscribe the event handler.
* The ProgressReached signal is emitted when the animation has reached a given progress percentage, this is set in the api SetProgressNotification.
*/
/// 3
public event EventHandler ProgressReached
{
add
{
if (_animationProgressReachedEventHandler == null)
{
_animationProgressReachedEventCallback = OnProgressReached;
ProgressReachedSignal().Connect(_animationProgressReachedEventCallback);
}
_animationProgressReachedEventHandler += value;
}
remove
{
_animationProgressReachedEventHandler -= value;
if (_animationProgressReachedEventHandler == null && ProgressReachedSignal().Empty() == false)
{
ProgressReachedSignal().Disconnect(_animationProgressReachedEventCallback);
}
}
}
private void OnProgressReached(IntPtr data)
{
if (_animationProgressReachedEventHandler != null)
{
//here we send all data to user event handlers
_animationProgressReachedEventHandler(this, null);
}
}
private float MilliSecondsToSeconds(int millisec)
{
return (float)millisec / 1000.0f;
}
private int SecondsToMilliSeconds(float sec)
{
return (int)(sec * 1000);
}
///
/// Gets or sets the duration in milliseconds of the animation.
///
/// 3
public int Duration
{
set
{
SetDuration(MilliSecondsToSeconds(value));
}
get
{
return SecondsToMilliSeconds(GetDuration());
}
}
///
/// Gets or sets the default alpha function for the animation.
///
/// 3
public AlphaFunction DefaultAlphaFunction
{
set
{
SetDefaultAlphaFunction(value);
}
get
{
AlphaFunction ret = GetDefaultAlphaFunction();
return ret;
}
}
///
/// Queries the state of the animation.
///
/// 3
public States State
{
get
{
return GetState();
}
}
///
/// Set: Enables looping for a specified number of repeats. A zero is the same as Looping = true; i.e., repeat forever.
/// This property resets the looping value and should not be used with the Looping property.
/// Setting this parameter does not cause the animation to Play().
/// Get: Gets the loop count. A zero is the same as Looping = true; i.e., repeat forever.
/// The loop count is initially 1 for play once.
///
/// 3
public int LoopCount
{
set
{
SetLoopCount(value);
}
get
{
int ret = GetLoopCount();
return ret;
}
}
///
/// Gets or sets the status of whether the animation will loop.
/// This property resets the loop count and should not be used with the LoopCount property.
/// Setting this parameter does not cause the animation to Play().
///
/// 3
public bool Looping
{
set
{
SetLooping(value);
}
get
{
bool ret = IsLooping();
return ret;
}
}
///
/// Gets or sets the end action of the animation.
/// This action is performed when the animation ends or if it is stopped.
/// The default end action is cancel.
///
/// 3
public EndActions EndAction
{
set
{
SetEndAction(value);
}
get
{
return GetEndAction();
}
}
///
/// Stops the animation.
///
/// The end action can be set.
/// 3
public void Stop(EndActions action = EndActions.Cancel)
{
SetEndAction(action);
NDalicPINVOKE.Animation_Stop(swigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Gets the current loop count.
/// A value 0 indicating the current loop count when looping.
///
/// 3
public int CurrentLoop
{
get
{
return GetCurrentLoop();
}
}
///
/// Gets or sets the disconnect action.
/// If any of the animated property owners are disconnected from the stage while the animation is being played, then this action is performed.
/// The default action is cancel.
///
/// 3
public EndActions DisconnectAction
{
set
{
NDalicPINVOKE.Animation_SetDisconnectAction(swigCPtr, (int)value);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
get
{
Animation.EndActions ret = (Animation.EndActions)NDalicPINVOKE.Animation_GetDisconnectAction(swigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}
///
/// Gets or sets the progress of the animation.
/// The animation will play (or continue playing) from this point.
/// The progress must be in the 0-1 interval or in the play range interval if defined
/// otherwise, it will be ignored.
///
/// 3
public float CurrentProgress
{
set
{
NDalicPINVOKE.Animation_SetCurrentProgress(swigCPtr, value);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
get
{
float ret = NDalicPINVOKE.Animation_GetCurrentProgress(swigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}
///
/// Gets or sets specificifications of a speed factor for the animation.
/// The speed factor is a multiplier of the normal velocity of the animation.
/// Values between [0, 1] will slow down the animation and values above one will speed up the animation.
/// It is also possible to specify a negative multiplier to play the animation in reverse.
///
/// 3
public float SpeedFactor
{
set
{
NDalicPINVOKE.Animation_SetSpeedFactor(swigCPtr, value);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
get
{
float ret = NDalicPINVOKE.Animation_GetSpeedFactor(swigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}
///
/// Gets or sets the playing range.
/// Animation will play between the values specified. Both values (range.x and range.y ) should be between 0-1,
/// otherwise they will be ignored. If the range provided is not in proper order (minimum, maximum ), it will be reordered.
///
/// 3
public RelativeVector2 PlayRange
{
set
{
NDalicPINVOKE.Animation_SetPlayRange(swigCPtr, Vector2.getCPtr(value));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
get
{
Vector2 ret = new Vector2(NDalicPINVOKE.Animation_GetPlayRange(swigCPtr), true);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}
///
/// Gets or sets the progress notification marker which triggers the ProgressReachedSignal.
/// Percentage of animation progress should be greater than 0 and less than 1, for example, 0.3 for 30%
/// One notification can be set on each animation.
///
/// 3
public float ProgressNotification
{
set
{
NDalicPINVOKE.Animation_SetProgressNotification(swigCPtr, value);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
get
{
float ret = NDalicPINVOKE.Animation_GetProgressNotification(swigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}
///
/// Animates a property value by a relative amount.
///
/// The target object to animate.
/// The target property to animate.
/// The property value will change by this amount.
/// The alpha function to apply.
/// 3
public void AnimateBy(View target, string property, object relativeValue, AlphaFunction alphaFunction = null)
{
Property _prop = PropertyHelper.GetPropertyFromString(target, property);
PropertyType propertyType = target.GetPropertyType(_prop.propertyIndex);
if(propertyType.Equals(PropertyType.Float))
{
System.Type type = relativeValue.GetType();
if (type.Equals(typeof(System.Int32)) || type.Equals(typeof(int)))
{
int num = (int)relativeValue;
relativeValue = (float)num;
}
}
PropertyValue val = PropertyValue.CreateFromObject(relativeValue);
if (alphaFunction != null)
{
AnimateBy(_prop, val, alphaFunction);
}
else
{
AnimateBy(_prop, val);
}
}
///
/// Animates a property value by a relative amount.
///
/// The target object to animate.
/// The target property to animate.
/// The property value will change by this amount.
/// The start time of the animation.
/// The end time of the animation.
/// The alpha function to apply.
/// 3
public void AnimateBy(View target, string property, object relativeValue, int startTime, int endTime, AlphaFunction alphaFunction = null)
{
Property _prop = PropertyHelper.GetPropertyFromString(target, property);
PropertyType propertyType = target.GetPropertyType(_prop.propertyIndex);
if(propertyType.Equals(PropertyType.Float))
{
System.Type type = relativeValue.GetType();
if (type.Equals(typeof(System.Int32)) || type.Equals(typeof(int)))
{
int num = (int)relativeValue;
relativeValue = (float)num;
}
}
PropertyValue val = PropertyValue.CreateFromObject(relativeValue);
if (alphaFunction != null)
{
Tizen.NUI.TimePeriod time = new Tizen.NUI.TimePeriod(MilliSecondsToSeconds(startTime), MilliSecondsToSeconds(endTime - startTime));
AnimateBy(_prop, val, alphaFunction, time);
}
else
{
Tizen.NUI.TimePeriod time = new Tizen.NUI.TimePeriod(MilliSecondsToSeconds(startTime), MilliSecondsToSeconds(endTime - startTime));
AnimateBy(_prop, val, time);
}
}
///
/// Animates a property to a destination value.
///
/// The target object to animate.
/// The target property to animate.
/// The destination value.
/// The alpha function to apply.
/// 3
public void AnimateTo(View target, string property, object destinationValue, AlphaFunction alphaFunction = null)
{
Property _prop = PropertyHelper.GetPropertyFromString(target, property);
PropertyType propertyType = target.GetPropertyType(_prop.propertyIndex);
if(propertyType.Equals(PropertyType.Float))
{
System.Type type = destinationValue.GetType();
if (type.Equals(typeof(System.Int32)) || type.Equals(typeof(int)))
{
int num = (int)destinationValue;
destinationValue = (float)num;
}
}
PropertyValue val = PropertyValue.CreateFromObject(destinationValue);
if (alphaFunction != null)
{
AnimateTo(_prop, val, alphaFunction);
}
else
{
AnimateTo(_prop, val);
}
}
private string[] _properties = null;
public string[] Properties
{
get
{
return _properties;
}
set
{
_properties = value;
}
}
private string[] _destValue = null;
public string[] DestValue
{
get
{
return _destValue;
}
set
{
_destValue = value;
}
}
private int[] _startTime = null;
public int[] StartTime
{
get
{
return _startTime;
}
set
{
_startTime = value;
}
}
private int[] _endTime = null;
public int[] EndTime
{
get
{
return _endTime;
}
set
{
_endTime = value;
}
}
public void PlayAnimateTo(View target)
{
if (_properties.Length == _destValue.Length && _startTime.Length == _endTime.Length && _properties.Length == _startTime.Length)
{
int length = _properties.Length;
for (int index = 0; index < length; index++)
{
//object destinationValue = _destValue[index];
var elementType = target.GetType();
PropertyInfo propertyInfo = elementType.GetProperties().FirstOrDefault(fi => fi.Name == _properties[index]);
//var propertyInfo = elementType.GetRuntimeProperties().FirstOrDefault(p => p.Name == localName);
if (propertyInfo != null)
{
object destinationValue = ConvertTo(_destValue[index], propertyInfo.PropertyType);
if(destinationValue != null)
{
AnimateTo(target, _properties[index], destinationValue, _startTime[index], _endTime[index]);
}
}
}
Play();
}
}
internal object ConvertTo(object value, Type toType)
{
Func