Add Transit
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / Transit.cs
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.Collections.ObjectModel;
21 using System.Collections.Specialized;
22 using static Interop.Elementary;
23
24 namespace ElmSharp
25 {
26     /// <summary>
27     /// Transit is designed to apply various animated transition effects, such like translation, rotation, etc.
28     /// For using these effects, create an Transit and add the desired transition effects.
29     /// </summary>
30     /// <remarks>Transit is not reusable. If the effect ends, the transit is destroyed automatically.</remarks>
31     public class Transit : IDisposable
32     {
33         IntPtr _handle = IntPtr.Zero;
34         bool _isDisposed = false;
35         ObservableCollection<EvasObject> _objects = new ObservableCollection<EvasObject>();
36         ObservableCollection<Transit> _chains = new ObservableCollection<Transit>();
37         HashSet<object> _checker = new HashSet<object>();
38         Elm_Transit_Del_Cb DeletedCallback;
39         Elm_Transit_Effect_End_Cb EffectEndCallback;
40
41         /// <summary>
42         /// A callback called when the transit is deleted.
43         /// </summary>
44         public event EventHandler Deleted;
45
46         /// <summary>
47         /// Creates and initializes a new instance of Transit class.
48         /// </summary>
49         public Transit()
50         {
51             _handle = Interop.Elementary.elm_transit_add();
52             DeletedCallback = (ptr1, ptr2) => {
53                 Deleted?.Invoke(this, EventArgs.Empty);
54                 Dispose(true);
55             };
56             Interop.Elementary.elm_transit_del_cb_set(_handle, DeletedCallback, IntPtr.Zero);
57             ((INotifyCollectionChanged)_objects).CollectionChanged += OnObjectCollectionChanged;
58             ((INotifyCollectionChanged)_chains).CollectionChanged += OnChaninCollectionChanged;
59         }
60
61         ~Transit()
62         {
63             Dispose(false);
64         }
65
66         /// <summary>
67         /// Gets or sets the transit animation time
68         /// </summary>
69         public double Duration
70         {
71             get
72             {
73                 return Interop.Elementary.elm_transit_duration_get(_handle);
74             }
75             set
76             {
77                 Interop.Elementary.elm_transit_duration_set(_handle, value);
78             }
79         }
80
81         /// <summary>
82         /// Gets or sets a value whether the objects states will be keep or not.
83         /// If it is not kept, the objects states will be reset when transition ends.
84         /// </summary>
85         public bool ObjectStateKeep
86         {
87             get
88             {
89                 return Interop.Elementary.elm_transit_objects_final_state_keep_get(_handle);
90             }
91             set
92             {
93                 Interop.Elementary.elm_transit_objects_final_state_keep_set(_handle, value);
94             }
95         }
96
97         /// <summary>
98         /// Gets or sets the transit animation acceleration type.
99         /// </summary>
100         public TweenMode TweenMode
101         {
102             get
103             {
104                 return (TweenMode)Interop.Elementary.elm_transit_tween_mode_get(_handle);
105             }
106             set
107             {
108                 Interop.Elementary.elm_transit_tween_mode_set(_handle, (int)value);
109             }
110         }
111
112         /// <summary>
113         /// Gets or sets the transit repeat count.
114         /// If the repeat is a negative number, it will repeat infinite times.
115         /// </summary>
116         public int Repeat
117         {
118             get
119             {
120                 return Interop.Elementary.elm_transit_repeat_times_get(_handle);
121             }
122             set
123             {
124                 Interop.Elementary.elm_transit_repeat_times_set(_handle, value);
125             }
126         }
127
128         /// <summary>
129         /// Gets or sets if the auto reverse is on.
130         /// </summary>
131         public bool AutoReverse
132         {
133             get
134             {
135                 return Interop.Elementary.elm_transit_auto_reverse_get(_handle);
136             }
137             set
138             {
139                 Interop.Elementary.elm_transit_auto_reverse_set(_handle, value);
140             }
141         }
142
143         /// <summary>
144         /// Gets or sets the event enabled when transit is operating.
145         /// </summary>
146         public bool EventEnabled
147         {
148             get
149             {
150                 return Interop.Elementary.elm_transit_event_enabled_get(_handle);
151             }
152             set
153             {
154                 Interop.Elementary.elm_transit_event_enabled_set(_handle, value);
155             }
156         }
157
158         /// <summary>
159         /// Gets or sets the smooth scaling for transit map rendering
160         /// This gets smooth scaling for transit map rendering.
161         /// </summary>
162         public bool Smooth
163         {
164             get
165             {
166                 return Interop.Elementary.elm_transit_smooth_get(_handle);
167             }
168             set
169             {
170                 Interop.Elementary.elm_transit_smooth_set(_handle, value);
171             }
172         }
173
174         /// <summary>
175         /// Pause/Resume the transition.
176         /// </summary>
177         public bool Pause
178         {
179             get
180             {
181                 return Interop.Elementary.elm_transit_paused_get(_handle);
182             }
183             set
184             {
185                 Interop.Elementary.elm_transit_paused_set(_handle, value);
186             }
187         }
188
189         /// <summary>
190         /// Get the time progression of the animation (a double value between 0.0 and 1.0).
191         /// The value returned is a fraction(current time / total time).
192         /// It represents the progression position relative to the total.
193         /// </summary>
194         public double Progress
195         {
196             get
197             {
198                 return Interop.Elementary.elm_transit_progress_value_get(_handle);
199             }
200         }
201
202         /// <summary>
203         /// Gets or sets the transit animation tween mode acceleration factor.
204         /// </summary>
205         /// <returns>A factor value from 0.0 to 1.0.</returns>
206         public double BeginAccelerationFactor
207         {
208             get
209             {
210                 double begin = 1.0, end = 0.0;
211                 Interop.Elementary.elm_transit_tween_mode_factor_get(_handle, out begin, out end);
212                 return begin;
213             }
214             set
215             {
216                 Interop.Elementary.elm_transit_tween_mode_factor_set(_handle, value, EndAccelerationFactor);
217             }
218         }
219
220         /// <summary>
221         /// Gets or sets the transit animation tween mode acceleration factor.
222         /// </summary>
223         /// <returns>A factor value from 0.0 to 1.0.</returns>
224         public double EndAccelerationFactor
225         {
226             get
227             {
228                 double begin = 1.0, end = 0.0;
229                 Interop.Elementary.elm_transit_tween_mode_factor_get(_handle, out begin, out end);
230                 return end;
231             }
232             set
233             {
234                 Interop.Elementary.elm_transit_tween_mode_factor_set(_handle, BeginAccelerationFactor, value);
235             }
236         }
237
238         /// <summary>
239         /// Starts the transition in given seconds.
240         /// Once this API is called, the transit begins to measure the time.
241         /// </summary>
242         /// <param name="interval">The interval value in seconds</param>
243         public void Go(double interval = 0)
244         {
245             Interop.Elementary.elm_transit_go_in(_handle, interval);
246         }
247
248         /// <summary>
249         /// Get the current chained transit list.
250         /// </summary>
251         /// <remarks>Cannot add the duplicate transit.</remarks>
252         public IList<Transit> Chains
253         {
254             get { return _chains; }
255         }
256
257         /// <summary>
258         /// Get the objects list of the transit.
259         /// </summary>
260         /// <remarks>Cannot add the duplicate object.</remarks>
261         public IList<EvasObject> Objects
262         {
263             get { return _objects; }
264         }
265
266         /// <summary>
267         /// Add the effect.
268         /// </summary>
269         /// <param name="effect">EffectBase object.</param>
270         public void AddEffect(EffectBase effect)
271         {
272             IntPtr _effect = effect.CreateEffect(_handle);
273             EffectEndCallback = (ptr1, ptr2) => { effect.SendEffectEnd(); };
274             Interop.Elementary.elm_transit_effect_add(_handle, null, _effect, EffectEndCallback);
275         }
276
277         public void Dispose()
278         {
279             Dispose(true);
280             GC.SuppressFinalize(this);
281         }
282
283         protected virtual void Dispose(bool isDisposing)
284         {
285             if (_isDisposed)
286                 return;
287
288             if (isDisposing)
289             {
290                 ((INotifyCollectionChanged)_chains).CollectionChanged -= OnChaninCollectionChanged;
291                 _chains.Clear();
292                 ((INotifyCollectionChanged)_objects).CollectionChanged -= OnObjectCollectionChanged;
293                 _objects.Clear();
294                 _checker.Clear();
295             }
296
297             _isDisposed = true;
298         }
299
300         void OnObjectCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
301         {
302             if (e.Action == NotifyCollectionChangedAction.Add)
303             {
304                 foreach (EvasObject item in e.NewItems)
305                     AddObject(item);
306             }
307             else if (e.Action == NotifyCollectionChangedAction.Remove)
308             {
309                 foreach (EvasObject item in e.OldItems)
310                     RemoveObject(item);
311             }
312         }
313
314         void OnChaninCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
315         {
316             if (e.Action == NotifyCollectionChangedAction.Add)
317             {
318                 foreach (Transit item in e.NewItems)
319                     AddChainedTransit(item);
320             }
321             else if (e.Action == NotifyCollectionChangedAction.Remove)
322             {
323                 foreach (Transit item in e.OldItems)
324                     DeleteChainedTransit(item);
325             }
326         }
327
328         /// <summary>
329         /// Add new object to apply the effects.
330         /// After the first addition of an object to transit, if its object list become empty again, the transit will be killed.
331         /// If the obj belongs to another transit, the obj will be removed from it and it will only belong to the other transit.
332         /// </summary>
333         /// <remarks>It is not allowed to add a new object after transit begins.</remarks>
334         /// <param name="obj">Object to be animated.</param>
335         void AddObject(EvasObject obj)
336         {
337             if (_checker.Contains(obj))
338                 throw new Exception("Cannot add the duplicate object.");
339
340             _checker.Add(obj);
341             Interop.Elementary.elm_transit_object_add(_handle, obj);
342         }
343
344         /// <summary>
345         /// Removes an added object from the transit.
346         /// </summary>
347         /// <param name="obj">Object to be removed from transit.</param>
348         void RemoveObject(EvasObject obj)
349         {
350             if (_checker.Contains(obj))
351                 _checker.Remove(obj);
352
353             Interop.Elementary.elm_transit_object_remove(_handle, obj);
354         }
355
356         /// <summary>
357         /// Makes the chain relationship between two transits.
358         /// </summary>
359         /// <param name="transit">The chain transit object. This transit will be operated after transit is done.</param>
360         void AddChainedTransit(Transit transit)
361         {
362             if (_checker.Contains(transit))
363                 throw new Exception("Cannot add the duplicate transit.");
364
365             _checker.Add(transit);
366             Interop.Elementary.elm_transit_chain_transit_add(_handle, transit._handle);
367         }
368
369         /// <summary>
370         /// Cut off the chain relationship between two transits.
371         /// </summary>
372         /// <param name="transit">The chain transit object.</param>
373         void DeleteChainedTransit(Transit transit)
374         {
375             if (_checker.Contains(transit))
376                 _checker.Remove(transit);
377
378             Interop.Elementary.elm_transit_chain_transit_del(_handle, transit._handle);
379         }
380     }
381 }