/* * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved * * 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. */ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using static Interop.Elementary; namespace ElmSharp { /// /// Transit is designed to apply various animated transition effects, such like translation, rotation, etc. /// For using these effects, create an Transit and add the desired transition effects. /// /// Transit is not reusable. If the effect ends, the transit is destroyed automatically. public class Transit : IDisposable { IntPtr _handle = IntPtr.Zero; bool _isDisposed = false; ObservableCollection _objects = new ObservableCollection(); ObservableCollection _chains = new ObservableCollection(); HashSet _checker = new HashSet(); Elm_Transit_Del_Cb DeletedCallback; Elm_Transit_Effect_End_Cb EffectEndCallback; Elm_Transit_Effect_Transition_Cb EffectTransitionCallback; /// /// A callback called when the transit is deleted. /// public event EventHandler Deleted; /// /// Creates and initializes a new instance of Transit class. /// public Transit() { _handle = Interop.Elementary.elm_transit_add(); DeletedCallback = (ptr1, ptr2) => { Deleted?.Invoke(this, EventArgs.Empty); Dispose(true); }; Interop.Elementary.elm_transit_del_cb_set(_handle, DeletedCallback, IntPtr.Zero); ((INotifyCollectionChanged)_objects).CollectionChanged += OnObjectCollectionChanged; ((INotifyCollectionChanged)_chains).CollectionChanged += OnChaninCollectionChanged; } ~Transit() { Dispose(false); } /// /// Gets or sets the transit animation time /// public double Duration { get { return Interop.Elementary.elm_transit_duration_get(_handle); } set { Interop.Elementary.elm_transit_duration_set(_handle, value); } } /// /// Gets or sets a value whether the objects states will be keep or not. /// If it is not kept, the objects states will be reset when transition ends. /// public bool ObjectStateKeep { get { return Interop.Elementary.elm_transit_objects_final_state_keep_get(_handle); } set { Interop.Elementary.elm_transit_objects_final_state_keep_set(_handle, value); } } /// /// Gets or sets the transit animation acceleration type. /// public TweenMode TweenMode { get { return (TweenMode)Interop.Elementary.elm_transit_tween_mode_get(_handle); } set { Interop.Elementary.elm_transit_tween_mode_set(_handle, (int)value); } } /// /// Gets or sets the transit repeat count. /// If the repeat is a negative number, it will repeat infinite times. /// public int Repeat { get { return Interop.Elementary.elm_transit_repeat_times_get(_handle); } set { Interop.Elementary.elm_transit_repeat_times_set(_handle, value); } } /// /// Gets or sets if the auto reverse is on. /// public bool AutoReverse { get { return Interop.Elementary.elm_transit_auto_reverse_get(_handle); } set { Interop.Elementary.elm_transit_auto_reverse_set(_handle, value); } } /// /// Gets or sets the event enabled when transit is operating. /// public bool EventEnabled { get { return Interop.Elementary.elm_transit_event_enabled_get(_handle); } set { Interop.Elementary.elm_transit_event_enabled_set(_handle, value); } } /// /// Gets or sets the smooth scaling for transit map rendering /// This gets smooth scaling for transit map rendering. /// public bool Smooth { get { return Interop.Elementary.elm_transit_smooth_get(_handle); } set { Interop.Elementary.elm_transit_smooth_set(_handle, value); } } /// /// Get the time progression of the animation (a double value between 0.0 and 1.0). /// The value returned is a fraction(current time / total time). /// It represents the progression position relative to the total. /// public double Progress { get { return Interop.Elementary.elm_transit_progress_value_get(_handle); } } /// /// Gets or sets the transit animation tween mode acceleration factor. /// /// A factor value from 0.0 to 1.0. public double BeginAccelerationFactor { get { double begin = 1.0, end = 0.0; Interop.Elementary.elm_transit_tween_mode_factor_get(_handle, out begin, out end); return begin; } set { Interop.Elementary.elm_transit_tween_mode_factor_set(_handle, value, EndAccelerationFactor); } } /// /// Gets or sets the transit animation tween mode acceleration factor. /// /// A factor value from 0.0 to 1.0. public double EndAccelerationFactor { get { double begin = 1.0, end = 0.0; Interop.Elementary.elm_transit_tween_mode_factor_get(_handle, out begin, out end); return end; } set { Interop.Elementary.elm_transit_tween_mode_factor_set(_handle, BeginAccelerationFactor, value); } } /// /// Starts the transition in given seconds. /// Once this API is called, the transit begins to measure the time. /// /// The interval value in seconds public void Go(double interval = 0) { Interop.Elementary.elm_transit_go_in(_handle, interval); } /// /// Pause the transition. /// public void Pause() { if (Interop.Elementary.elm_transit_paused_get(_handle) == false) Interop.Elementary.elm_transit_paused_set(_handle, true); } /// /// Resume the transition. /// public void Resume() { if (Interop.Elementary.elm_transit_paused_get(_handle) == true) Interop.Elementary.elm_transit_paused_set(_handle, false); } /// /// Get the current chained transit list. /// /// Cannot add the duplicate transit. public IList Chains { get { return _chains; } } /// /// Get the objects list of the transit. /// /// Cannot add the duplicate object. public IList Objects { get { return _objects; } } /// /// Add the effect. /// /// EffectBase object. public void AddEffect(EffectBase effect) { IntPtr _effect = effect.CreateEffect(_handle); EffectEndCallback = (effectPtr, transitPtr) => { effect.SendEffectEnd(); }; EffectTransitionCallback = (effectPtr, transitPtr, progress) => { }; Interop.Elementary.elm_transit_effect_add(_handle, EffectTransitionCallback, _effect, EffectEndCallback); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool isDisposing) { if (_isDisposed) return; if (isDisposing) { ((INotifyCollectionChanged)_chains).CollectionChanged -= OnChaninCollectionChanged; _chains.Clear(); ((INotifyCollectionChanged)_objects).CollectionChanged -= OnObjectCollectionChanged; _objects.Clear(); _checker.Clear(); } _isDisposed = true; } void OnObjectCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Add) { foreach (EvasObject item in e.NewItems) AddObject(item); } else if (e.Action == NotifyCollectionChangedAction.Remove) { foreach (EvasObject item in e.OldItems) RemoveObject(item); } } void OnChaninCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Add) { foreach (Transit item in e.NewItems) AddChainedTransit(item); } else if (e.Action == NotifyCollectionChangedAction.Remove) { foreach (Transit item in e.OldItems) DeleteChainedTransit(item); } } /// /// Add new object to apply the effects. /// After the first addition of an object to transit, if its object list become empty again, the transit will be killed. /// If the obj belongs to another transit, the obj will be removed from it and it will only belong to the other transit. /// /// It is not allowed to add a new object after transit begins. /// Object to be animated. void AddObject(EvasObject obj) { if (_checker.Contains(obj)) throw new Exception("Cannot add the duplicate object."); _checker.Add(obj); Interop.Elementary.elm_transit_object_add(_handle, obj); } /// /// Removes an added object from the transit. /// /// Object to be removed from transit. void RemoveObject(EvasObject obj) { if (_checker.Contains(obj)) _checker.Remove(obj); Interop.Elementary.elm_transit_object_remove(_handle, obj); } /// /// Makes the chain relationship between two transits. /// /// The chain transit object. This transit will be operated after transit is done. void AddChainedTransit(Transit transit) { if (_checker.Contains(transit)) throw new Exception("Cannot add the duplicate transit."); _checker.Add(transit); Interop.Elementary.elm_transit_chain_transit_add(_handle, transit._handle); } /// /// Cut off the chain relationship between two transits. /// /// The chain transit object. void DeleteChainedTransit(Transit transit) { if (_checker.Contains(transit)) _checker.Remove(transit); Interop.Elementary.elm_transit_chain_transit_del(_handle, transit._handle); } } }