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;
+
/// <summary>
/// Animation can be used to animate the properties of any number of objects, typically view.<br />
/// If the "Finished" event is connected to a member function of an object, it must be disconnected before the object is destroyed.<br />
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<System.Delegate>(_animationFinishedEventCallback);
}
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Animation obj)
/// <since_tizen> 3 </since_tizen>
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 (_animationFinishedEventCallback != null)
- {
- FinishedSignal().Disconnect(_animationFinishedEventCallback);
- }
-
- if (_animationProgressReachedEventCallback != null)
- {
-
- ProgressReachedSignal().Disconnect(_animationProgressReachedEventCallback);
- }
-
- if(this)
+ if (this != null)
{
this.Clear();
- this.Reset();
- NUILog.Error("Now Animation is playing! Clear and Reset here!");
- //throw new System.InvalidOperationException("Animation Instance should not be disposed until getting Finished event. Should be a global variable");
}
//Release your own unmanaged resources here.
[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.
{
add
{
- if (_animationFinishedEventHandler == null)
+ if (_animationFinishedEventHandler == null && disposed == false)
{
- NUILog.Debug("[add before]FinishedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
- _animationFinishedEventCallback = OnFinished;
- FinishedSignal().Connect(_animationFinishedEventCallback);
- NUILog.Debug("[add after]FinishedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
+ FinishedSignal().Connect(_finishedCallbackOfNative);
}
_animationFinishedEventHandler += value;
}
if (_animationFinishedEventHandler == null && FinishedSignal().Empty() == false)
{
- NUILog.Debug("[remove before]FinishedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
- FinishedSignal().Disconnect(_animationFinishedEventCallback);
- NUILog.Debug("[remove after]FinishedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
+ FinishedSignal().Disconnect(_finishedCallbackOfNative);
}
}
}
{
if (_animationProgressReachedEventHandler == null)
{
- NUILog.Debug("[add before]ProgressReachedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
_animationProgressReachedEventCallback = OnProgressReached;
ProgressReachedSignal().Connect(_animationProgressReachedEventCallback);
- NUILog.Debug("[add after]ProgressReachedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
}
_animationProgressReachedEventHandler += value;
if (_animationProgressReachedEventHandler == null && ProgressReachedSignal().Empty() == false)
{
- NUILog.Debug("[remove before]ProgressReachedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
ProgressReachedSignal().Disconnect(_animationProgressReachedEventCallback);
- NUILog.Debug("[remove after]ProgressReachedSignal().Empty=" + FinishedSignal().Empty() + " GetConnectionCount=" + FinishedSignal().GetConnectionCount());
}
}
}
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<object> getConverter = () =>
+ {
+ MemberInfo memberInfo;
+
+ string converterTypeName = GetTypeConverterTypeName(toType.GetTypeInfo().CustomAttributes);
+ if (converterTypeName == null)
+ return null;
+
+ Type convertertype = Type.GetType(converterTypeName);
+ return Activator.CreateInstance(convertertype);
+ };
+
+ return ConvertTo(value, toType, getConverter);
+ }
+
+ internal object ConvertTo(object value, Type toType, Func<object> getConverter)
+ {
+ if (value == null)
+ return null;
+
+ var str = value as string;
+ if (str != null)
+ {
+ //If there's a [TypeConverter], use it
+ object converter = getConverter?.Invoke();
+ var xfTypeConverter = converter as TypeConverter;
+ if (xfTypeConverter != null)
+ return value = xfTypeConverter.ConvertFromInvariantString(str);
+ var converterType = converter?.GetType();
+ if (converterType != null)
+ {
+ var convertFromStringInvariant = converterType.GetRuntimeMethod("ConvertFromInvariantString",
+ new[] { typeof(string) });
+ if (convertFromStringInvariant != null)
+ return value = convertFromStringInvariant.Invoke(converter, new object[] { str });
+ }
+
+ //If the type is nullable, as the value is not null, it's safe to assume we want the built-in conversion
+ if (toType.GetTypeInfo().IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable<>))
+ toType = Nullable.GetUnderlyingType(toType);
+
+ //Obvious Built-in conversions
+ if (toType.GetTypeInfo().IsEnum)
+ return Enum.Parse(toType, str, true);
+ if (toType == typeof(SByte))
+ return SByte.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Int16))
+ return Int16.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Int32))
+ return Int32.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Int64))
+ return Int64.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Byte))
+ return Byte.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(UInt16))
+ return UInt16.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(UInt32))
+ return UInt32.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(UInt64))
+ return UInt64.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Single))
+ return Single.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Double))
+ return Double.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Boolean))
+ return Boolean.Parse(str);
+ if (toType == typeof(TimeSpan))
+ return TimeSpan.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(DateTime))
+ return DateTime.Parse(str, CultureInfo.InvariantCulture);
+ if (toType == typeof(Char))
+ {
+ char c = '\0';
+ Char.TryParse(str, out c);
+ return c;
+ }
+ if (toType == typeof(String) && str.StartsWith("{}", StringComparison.Ordinal))
+ return str.Substring(2);
+ if (toType == typeof(String))
+ return value;
+ if (toType == typeof(Decimal))
+ return Decimal.Parse(str, CultureInfo.InvariantCulture);
+ }
+
+ //if the value is not assignable and there's an implicit conversion, convert
+ if (value != null && !toType.IsAssignableFrom(value.GetType()))
+ {
+ var opImplicit = GetImplicitConversionOperator(value.GetType(), value.GetType(), toType)
+ ?? GetImplicitConversionOperator(toType, value.GetType(), toType);
+ //var opImplicit = value.GetType().GetImplicitConversionOperator(fromType: value.GetType(), toType: toType)
+ // ?? toType.GetImplicitConversionOperator(fromType: value.GetType(), toType: toType);
+
+ if (opImplicit != null)
+ {
+ value = opImplicit.Invoke(null, new[] { value });
+ return value;
+ }
+ }
+
+ var nativeValueConverterService = DependencyService.Get<INativeValueConverterService>();
+
+ object nativeValue = null;
+ if (nativeValueConverterService != null && nativeValueConverterService.ConvertTo(value, toType, out nativeValue))
+ return nativeValue;
+
+ return value;
+ }
+
+ internal string GetTypeConverterTypeName(IEnumerable<CustomAttributeData> attributes)
+ {
+ var converterAttribute =
+ attributes.FirstOrDefault(cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName));
+ if (converterAttribute == null)
+ return null;
+ if (converterAttribute.ConstructorArguments[0].ArgumentType == typeof(string))
+ return (string)converterAttribute.ConstructorArguments[0].Value;
+ if (converterAttribute.ConstructorArguments[0].ArgumentType == typeof(Type))
+ return ((Type)converterAttribute.ConstructorArguments[0].Value).AssemblyQualifiedName;
+ return null;
+ }
+
+ internal MethodInfo GetImplicitConversionOperator(Type onType, Type fromType, Type toType)
+ {
+#if NETSTANDARD1_0
+ var mi = onType.GetRuntimeMethod("op_Implicit", new[] { fromType });
+#else
+ var bindingFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy;
+ var mi = onType.GetMethod("op_Implicit", bindingFlags, null, new[] { fromType }, null);
+#endif
+ if (mi == null) return null;
+ if (!mi.IsSpecialName) return null;
+ if (!mi.IsPublic) return null;
+ if (!mi.IsStatic) return null;
+ if (!toType.IsAssignableFrom(mi.ReturnType)) return null;
+
+ return mi;
+ }
+
/// <summary>
/// Animates a property to a destination value.<br />