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