7b79f32e8d05d8d45b9da850af1d5e298fe852df
[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         Elm_Transit_Effect_Transition_Cb EffectTransitionCallback;
41
42         /// <summary>
43         /// A callback called when the transit is deleted.
44         /// </summary>
45         public event EventHandler Deleted;
46
47         /// <summary>
48         /// Creates and initializes a new instance of Transit class.
49         /// </summary>
50         public Transit()
51         {
52             _handle = Interop.Elementary.elm_transit_add();
53             DeletedCallback = (ptr1, ptr2) =>
54             {
55                 Deleted?.Invoke(this, EventArgs.Empty);
56                 Dispose(true);
57             };
58             Interop.Elementary.elm_transit_del_cb_set(_handle, DeletedCallback, IntPtr.Zero);
59             ((INotifyCollectionChanged)_objects).CollectionChanged += OnObjectCollectionChanged;
60             ((INotifyCollectionChanged)_chains).CollectionChanged += OnChaninCollectionChanged;
61         }
62
63         /// <summary>
64         /// Destroy the Transit object.
65         /// </summary>
66         ~Transit()
67         {
68             Dispose(false);
69         }
70
71         /// <summary>
72         /// Gets or sets the transit animation time
73         /// </summary>
74         public double Duration
75         {
76             get
77             {
78                 return Interop.Elementary.elm_transit_duration_get(_handle);
79             }
80             set
81             {
82                 Interop.Elementary.elm_transit_duration_set(_handle, value);
83             }
84         }
85
86         /// <summary>
87         /// Gets or sets a value whether the objects states will be keep or not.
88         /// If it is not kept, the objects states will be reset when transition ends.
89         /// </summary>
90         public bool ObjectStateKeep
91         {
92             get
93             {
94                 return Interop.Elementary.elm_transit_objects_final_state_keep_get(_handle);
95             }
96             set
97             {
98                 Interop.Elementary.elm_transit_objects_final_state_keep_set(_handle, value);
99             }
100         }
101
102         /// <summary>
103         /// Gets or sets the transit animation acceleration type.
104         /// </summary>
105         public TweenMode TweenMode
106         {
107             get
108             {
109                 return (TweenMode)Interop.Elementary.elm_transit_tween_mode_get(_handle);
110             }
111             set
112             {
113                 Interop.Elementary.elm_transit_tween_mode_set(_handle, (int)value);
114             }
115         }
116
117         /// <summary>
118         /// Gets or sets the transit repeat count.
119         /// If the repeat is a negative number, it will repeat infinite times.
120         /// </summary>
121         public int Repeat
122         {
123             get
124             {
125                 return Interop.Elementary.elm_transit_repeat_times_get(_handle);
126             }
127             set
128             {
129                 Interop.Elementary.elm_transit_repeat_times_set(_handle, value);
130             }
131         }
132
133         /// <summary>
134         /// Gets or sets if the auto reverse is on.
135         /// </summary>
136         public bool AutoReverse
137         {
138             get
139             {
140                 return Interop.Elementary.elm_transit_auto_reverse_get(_handle);
141             }
142             set
143             {
144                 Interop.Elementary.elm_transit_auto_reverse_set(_handle, value);
145             }
146         }
147
148         /// <summary>
149         /// Gets or sets the event enabled when transit is operating.
150         /// </summary>
151         public bool EventEnabled
152         {
153             get
154             {
155                 return Interop.Elementary.elm_transit_event_enabled_get(_handle);
156             }
157             set
158             {
159                 Interop.Elementary.elm_transit_event_enabled_set(_handle, value);
160             }
161         }
162
163         /// <summary>
164         /// Gets or sets the smooth scaling for transit map rendering
165         /// This gets smooth scaling for transit map rendering.
166         /// </summary>
167         public bool Smooth
168         {
169             get
170             {
171                 return Interop.Elementary.elm_transit_smooth_get(_handle);
172             }
173             set
174             {
175                 Interop.Elementary.elm_transit_smooth_set(_handle, value);
176             }
177         }
178
179         /// <summary>
180         /// Get the time progression of the animation (a double value between 0.0 and 1.0).
181         /// The value returned is a fraction(current time / total time).
182         /// It represents the progression position relative to the total.
183         /// </summary>
184         public double Progress
185         {
186             get
187             {
188                 return Interop.Elementary.elm_transit_progress_value_get(_handle);
189             }
190         }
191
192         /// <summary>
193         /// Gets or sets the transit animation tween mode acceleration factor.
194         /// </summary>
195         /// <returns>A factor value from 0.0 to 1.0.</returns>
196         public double BeginAccelerationFactor
197         {
198             get
199             {
200                 double begin = 1.0, end = 0.0;
201                 Interop.Elementary.elm_transit_tween_mode_factor_get(_handle, out begin, out end);
202                 return begin;
203             }
204             set
205             {
206                 Interop.Elementary.elm_transit_tween_mode_factor_set(_handle, value, EndAccelerationFactor);
207             }
208         }
209
210         /// <summary>
211         /// Gets or sets the transit animation tween mode acceleration factor.
212         /// </summary>
213         /// <returns>A factor value from 0.0 to 1.0.</returns>
214         public double EndAccelerationFactor
215         {
216             get
217             {
218                 double begin = 1.0, end = 0.0;
219                 Interop.Elementary.elm_transit_tween_mode_factor_get(_handle, out begin, out end);
220                 return end;
221             }
222             set
223             {
224                 Interop.Elementary.elm_transit_tween_mode_factor_set(_handle, BeginAccelerationFactor, value);
225             }
226         }
227
228         /// <summary>
229         /// Starts the transition in given seconds.
230         /// Once this API is called, the transit begins to measure the time.
231         /// </summary>
232         /// <param name="interval">The interval value in seconds</param>
233         public void Go(double interval = 0)
234         {
235             Interop.Elementary.elm_transit_go_in(_handle, interval);
236         }
237
238         /// <summary>
239         /// Pause the transition.
240         /// </summary>
241         public void Pause()
242         {
243             if (Interop.Elementary.elm_transit_paused_get(_handle) == false)
244                 Interop.Elementary.elm_transit_paused_set(_handle, true);
245         }
246
247         /// <summary>
248         /// Resume the transition.
249         /// </summary>
250         public void Resume()
251         {
252             if (Interop.Elementary.elm_transit_paused_get(_handle) == true)
253                 Interop.Elementary.elm_transit_paused_set(_handle, false);
254         }
255
256         /// <summary>
257         /// Get the current chained transit list.
258         /// </summary>
259         /// <remarks>Cannot add the duplicate transit.</remarks>
260         public IList<Transit> Chains
261         {
262             get { return _chains; }
263         }
264
265         /// <summary>
266         /// Get the objects list of the transit.
267         /// </summary>
268         /// <remarks>Cannot add the duplicate object.</remarks>
269         public IList<EvasObject> Objects
270         {
271             get { return _objects; }
272         }
273
274         /// <summary>
275         /// Add the effect.
276         /// </summary>
277         /// <param name="effect">EffectBase object.</param>
278         public void AddEffect(EffectBase effect)
279         {
280             IntPtr _effect = effect.CreateEffect(_handle);
281             EffectEndCallback = (effectPtr, transitPtr) => { effect.SendEffectEnd(); };
282             EffectTransitionCallback = (effectPtr, transitPtr, progress) => { };
283             Interop.Elementary.elm_transit_effect_add(_handle, EffectTransitionCallback, _effect, EffectEndCallback);
284         }
285
286         /// <summary>
287         /// Destroy current object
288         /// </summary>
289         public void Dispose()
290         {
291             Dispose(true);
292             GC.SuppressFinalize(this);
293         }
294
295         /// <summary>
296         /// Releases all resources currently used by this instance.
297         /// </summary>
298         /// <param name="disposing">
299         /// true if managed resources should be disposed
300         /// otherwise, false.
301         /// </param>
302         protected virtual void Dispose(bool disposing)
303         {
304             if (_isDisposed)
305                 return;
306
307             if (disposing)
308             {
309                 ((INotifyCollectionChanged)_chains).CollectionChanged -= OnChaninCollectionChanged;
310                 _chains.Clear();
311                 ((INotifyCollectionChanged)_objects).CollectionChanged -= OnObjectCollectionChanged;
312                 _objects.Clear();
313                 _checker.Clear();
314             }
315
316             _isDisposed = true;
317         }
318
319         void OnObjectCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
320         {
321             if (e.Action == NotifyCollectionChangedAction.Add)
322             {
323                 foreach (EvasObject item in e.NewItems)
324                     AddObject(item);
325             }
326             else if (e.Action == NotifyCollectionChangedAction.Remove)
327             {
328                 foreach (EvasObject item in e.OldItems)
329                     RemoveObject(item);
330             }
331         }
332
333         void OnChaninCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
334         {
335             if (e.Action == NotifyCollectionChangedAction.Add)
336             {
337                 foreach (Transit item in e.NewItems)
338                     AddChainedTransit(item);
339             }
340             else if (e.Action == NotifyCollectionChangedAction.Remove)
341             {
342                 foreach (Transit item in e.OldItems)
343                     DeleteChainedTransit(item);
344             }
345         }
346
347         /// <summary>
348         /// Add new object to apply the effects.
349         /// After the first addition of an object to transit, if its object list become empty again, the transit will be killed.
350         /// If the obj belongs to another transit, the obj will be removed from it and it will only belong to the other transit.
351         /// </summary>
352         /// <remarks>It is not allowed to add a new object after transit begins.</remarks>
353         /// <param name="obj">Object to be animated.</param>
354         void AddObject(EvasObject obj)
355         {
356             if (_checker.Contains(obj))
357                 throw new Exception("Cannot add the duplicate object.");
358
359             _checker.Add(obj);
360             Interop.Elementary.elm_transit_object_add(_handle, obj);
361         }
362
363         /// <summary>
364         /// Removes an added object from the transit.
365         /// </summary>
366         /// <param name="obj">Object to be removed from transit.</param>
367         void RemoveObject(EvasObject obj)
368         {
369             if (_checker.Contains(obj))
370                 _checker.Remove(obj);
371
372             Interop.Elementary.elm_transit_object_remove(_handle, obj);
373         }
374
375         /// <summary>
376         /// Makes the chain relationship between two transits.
377         /// </summary>
378         /// <param name="transit">The chain transit object. This transit will be operated after transit is done.</param>
379         void AddChainedTransit(Transit transit)
380         {
381             if (_checker.Contains(transit))
382                 throw new Exception("Cannot add the duplicate transit.");
383
384             _checker.Add(transit);
385             Interop.Elementary.elm_transit_chain_transit_add(_handle, transit._handle);
386         }
387
388         /// <summary>
389         /// Cut off the chain relationship between two transits.
390         /// </summary>
391         /// <param name="transit">The chain transit object.</param>
392         void DeleteChainedTransit(Transit transit)
393         {
394             if (_checker.Contains(transit))
395                 _checker.Remove(transit);
396
397             Interop.Elementary.elm_transit_chain_transit_del(_handle, transit._handle);
398         }
399     }
400 }