e8ac7c7a1eb586633455171c521601597a3d2aa2
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / AnimatedImageView.cs
1 /*
2  * Copyright(c) 2019 Samsung Electronics Co., Ltd.
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
18 using System.Collections.Generic;
19 using System.ComponentModel;
20
21 namespace Tizen.NUI.BaseComponents
22 {
23     /// <summary>
24     /// AnimatedImageView is a class for displaying Animated-GIF and Image-Array
25     /// </summary>
26     // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
27     [EditorBrowsable(EditorBrowsableState.Never)]
28     public partial class AnimatedImageView : ImageView
29     {
30         #region Internal
31         #endregion Internal
32
33         #region Private
34         // Collection of animated-image-sensitive properties.
35         private static readonly List<int> cachedAnimatedImagePropertyKeyList = new List<int> {
36             ImageVisualProperty.BatchSize,
37             ImageVisualProperty.CacheSize,
38             ImageVisualProperty.FrameDelay,
39             ImageVisualProperty.LoopCount,
40             ImageVisualProperty.StopBehavior,
41         };
42         private List<string> resourceURLs = new List<string>();
43         #endregion Private
44
45         #region Constructor, Destructor, Dispose
46         /// <summary>
47         /// Construct AnimatedImageView
48         /// </summary>
49         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
50         [EditorBrowsable(EditorBrowsableState.Never)]
51         public AnimatedImageView() : base()
52         {
53             ActionPlay = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
54             ActionPause = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
55             ActionStop = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
56         }
57
58         /// <summary>
59         /// You can override it to clean-up your own resources
60         /// </summary>
61         /// <param name="type">DisposeTypes</param>
62         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
63         [EditorBrowsable(EditorBrowsableState.Never)]
64         protected override void Dispose(DisposeTypes type)
65         {
66             if (disposed)
67             {
68                 return;
69             }
70
71             //Release your own unmanaged resources here.
72             //You should not access any managed member here except static instance.
73             //because the execution order of Finalizes is non-deterministic.
74             base.Dispose(type);
75         }
76         #endregion Constructor, Destructor, Dispose
77
78         #region Property
79         /// <summary>
80         ///  Image URL list for Image-Array
81         /// </summary>
82         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
83         [EditorBrowsable(EditorBrowsableState.Never)]
84         public List<string> URLs
85         {
86             get
87             {
88                 return resourceURLs;
89             }
90         }
91
92         /// <summary>
93         /// Defines the batch size for pre-loading images in the Image-Array animation.
94         /// number of images to pre-load before starting to play. Default value: 1.
95         /// </summary>
96         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public int BatchSize
99         {
100             get
101             {
102                 return (int)GetValue(BatchSizeProperty);
103             }
104             set
105             {
106                 SetValue(BatchSizeProperty, value);
107                 NotifyPropertyChanged();
108             }
109         }
110
111         private int InternalBatchSize
112         {
113             get
114             {
115                 int ret = 1;
116
117                 PropertyValue batchSize = GetCachedImageVisualProperty(ImageVisualProperty.BatchSize);
118                 batchSize?.Get(out ret);
119                 batchSize?.Dispose();
120
121                 return ret;
122             }
123             set
124             {
125                 using PropertyValue setValue = new PropertyValue(value);
126                 UpdateImage(ImageVisualProperty.BatchSize, setValue);
127             }
128         }
129
130         /// <summary>
131         /// Defines the cache size for loading images in the Image-Array animation.
132         /// number of images to keep cached ahead during playback. Default value: 1.
133         ///</summary>
134         ///<remarks>
135         /// cacheSize should be >= batchSize. If it isn't, then the cache will automatically be changed to batchSize.
136         /// because of the defaults, it is expected that the application developer tune the batch and cache sizes to their particular use case.
137         /// </remarks>
138         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
139         [EditorBrowsable(EditorBrowsableState.Never)]
140         public int CacheSize
141         {
142             get
143             {
144                 return (int)GetValue(CacheSizeProperty);
145             }
146             set
147             {
148                 SetValue(CacheSizeProperty, value);
149                 NotifyPropertyChanged();
150             }
151         }
152
153         private int InternalCacheSize
154         {
155             get
156             {
157                 int ret = 1;
158
159                 PropertyValue cacheSize = GetCachedImageVisualProperty(ImageVisualProperty.CacheSize);
160                 cacheSize?.Get(out ret);
161                 cacheSize?.Dispose();
162
163                 return ret;
164             }
165             set
166             {
167                 using PropertyValue setValue = new PropertyValue(value);
168                 UpdateImage(ImageVisualProperty.CacheSize, setValue);
169             }
170         }
171
172         /// <summary>
173         /// The number of milliseconds between each frame in the Image-Array animation.
174         /// The number of milliseconds between each frame.
175         /// </summary>
176         /// <remarks>
177         /// This is only used when URLs(multiple string) are provided.
178         /// </remarks>
179         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
180         [EditorBrowsable(EditorBrowsableState.Never)]
181         public int FrameDelay
182         {
183             get
184             {
185                 return (int)GetValue(FrameDelayProperty);
186             }
187             set
188             {
189                 SetValue(FrameDelayProperty, value);
190                 NotifyPropertyChanged();
191             }
192         }
193
194         private int InternalFrameDelay
195         {
196             get
197             {
198                 int ret = 0;
199
200                 PropertyValue frameDelay = GetCachedImageVisualProperty(ImageVisualProperty.FrameDelay);
201                 frameDelay?.Get(out ret);
202                 frameDelay?.Dispose();
203
204                 return ret;
205             }
206             set
207             {
208                 using PropertyValue setValue = new PropertyValue(value);
209                 UpdateImage(ImageVisualProperty.FrameDelay, setValue);
210             }
211         }
212
213         /// <summary>
214         /// The number of looping.
215         /// </summary>
216         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
217         [EditorBrowsable(EditorBrowsableState.Never)]
218         public int LoopCount
219         {
220             get
221             {
222                 return (int)GetValue(LoopCountProperty);
223             }
224             set
225             {
226                 SetValue(LoopCountProperty, value);
227                 NotifyPropertyChanged();
228             }
229         }
230
231         private int InternalLoopCount
232         {
233             get
234             {
235                 int ret = -1;
236
237                 PropertyValue loopCount = GetCachedImageVisualProperty(ImageVisualProperty.LoopCount);
238                 loopCount?.Get(out ret);
239                 loopCount?.Dispose();
240
241                 return ret;
242             }
243             set
244             {
245                 using PropertyValue setValue = new PropertyValue(value);
246                 UpdateImage(ImageVisualProperty.LoopCount, setValue);
247             }
248         }
249
250         /// <summary>
251         /// Sets or gets the stop behavior.
252         /// </summary>
253         [EditorBrowsable(EditorBrowsableState.Never)]
254         public StopBehaviorType StopBehavior
255         {
256             get
257             {
258                 return (StopBehaviorType)GetValue(StopBehaviorProperty);
259             }
260             set
261             {
262                 SetValue(StopBehaviorProperty, value);
263                 NotifyPropertyChanged();
264             }
265         }
266
267         private StopBehaviorType InternalStopBehavior
268         {
269             get
270             {
271                 int ret = 0;
272
273                 PropertyValue stopBehavior = GetCachedImageVisualProperty(ImageVisualProperty.StopBehavior);
274                 stopBehavior?.Get(out ret);
275                 stopBehavior?.Dispose();
276
277                 return (StopBehaviorType)ret;
278             }
279             set
280             {
281                 using PropertyValue setValue = new PropertyValue((int)value);
282                 UpdateImage(ImageVisualProperty.StopBehavior, setValue);
283             }
284         }
285
286         /// <summary>
287         /// Get the number of total frames
288         /// </summary>
289         [EditorBrowsable(EditorBrowsableState.Never)]
290         public int TotalFrame
291         {
292             get
293             {
294                 int ret = -1;
295                 PropertyMap map = base.Image;
296                 if (map != null)
297                 {
298                     PropertyValue val = map.Find(ImageVisualProperty.TotalFrameNumber);
299                     if (val != null)
300                     {
301                         if (val.Get(out ret))
302                         {
303                             return ret;
304                         }
305                     }
306                 }
307                 return ret;
308             }
309         }
310
311         /// <summary>
312         /// Set or get the current frame. When setting a specific frame, it is displayed as a still image.
313         /// </summary>
314         /// <remarks>
315         /// Gets the value set by a user. If the setting value is out-ranged, it is reset as a minimum frame or a maximum frame.
316         /// </remarks>
317         [EditorBrowsable(EditorBrowsableState.Never)]
318         public int CurrentFrame
319         {
320             get
321             {
322                 return (int)GetValue(CurrentFrameProperty);
323             }
324             set
325             {
326                 SetValue(CurrentFrameProperty, value);
327                 NotifyPropertyChanged();
328             }
329         }
330
331         private int InternalCurrentFrame
332         {
333             set
334             {
335                 // Sync as current properties
336                 UpdateImage();
337
338                 DoAction(ImageView.Property.IMAGE, ActionJumpTo, new PropertyValue(value));
339             }
340             get
341             {
342                 int ret = -1;
343                 PropertyMap map = base.Image;
344                 if (map != null)
345                 {
346                     PropertyValue val = map.Find(ImageVisualProperty.CurrentFrameNumber);
347                     if (val != null)
348                     {
349                         if (val.Get(out ret))
350                         {
351                             return ret;
352                         }
353                     }
354                 }
355                 return ret;
356             }
357         }
358
359         /// <summary>
360         /// Actions property value to Jump to the specified frame.
361         /// This property can be redefined by child class if it use different value.
362         /// </summary>
363         [EditorBrowsable(EditorBrowsableState.Never)]
364         protected int ActionJumpTo { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionJumpToGet();
365         #endregion Property
366
367         #region Method
368         /// <summary>
369         /// To make the properies be set. This should be called after the properties are set.
370         /// </summary>
371         // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
372         [EditorBrowsable(EditorBrowsableState.Never)]
373         public void SetValues()
374         {
375             // This API assume that Animated relative properties setuped forcely.
376             imagePropertyUpdatedFlag = true;
377
378             // Sync as current properties
379             UpdateImage();
380         }
381
382         /// <summary>
383         /// Update animated-image-relative properties synchronously.
384         /// After call this API, All image properties updated.
385         /// </summary>
386         [EditorBrowsable(EditorBrowsableState.Never)]
387         protected override void UpdateImage()
388         {
389             if (!imagePropertyUpdatedFlag) return;
390
391             // Assume that we are using standard Image at first.
392             // (Since we might cache Visual.Property.Type as Visual.Type.AnimatedImage even we don't use URLs.)
393             using (PropertyValue imageType = new PropertyValue((int)Visual.Type.Image))
394             {
395                 UpdateImage(Visual.Property.Type, imageType, false);
396             }
397
398             if (resourceURLs != null && resourceURLs.Count != 0)
399             {
400                 using (PropertyArray indexPropertyArray = new PropertyArray())
401                 {
402                     PropertyArray returnedArr = new PropertyArray();
403                     foreach (var iter in resourceURLs)
404                     {
405                         using (PropertyValue index = new PropertyValue(iter))
406                         {
407                             returnedArr = indexPropertyArray.Add(index);
408                         }
409                     }
410                     returnedArr.Dispose();
411                     using PropertyValue arrayProperty = new PropertyValue(indexPropertyArray);
412
413                     // Trigger the ImageView so that we have something update
414                     UpdateImage(ImageVisualProperty.URL, arrayProperty, false);
415                 }
416
417                 // Trick that we are using resourceURLs without ResourceUrl API.
418                 using PropertyValue animatiedImage = new PropertyValue((int)Visual.Type.AnimatedImage);
419                 UpdateImage(Visual.Property.Type, animatiedImage, false);
420             }
421
422             base.UpdateImage();
423         }
424
425         /// <summary>
426         /// Update NUI cached animated image visual property map by inputed property map.
427         /// And call base.MergeCachedImageVisualProperty()
428         /// </summary>
429         /// <remarks>
430         /// For performance issue, we will collect only "cachedAnimatedImagePropertyKeyList" hold in this class.
431         /// </remarks>
432         [EditorBrowsable(EditorBrowsableState.Never)]
433         protected override void MergeCachedImageVisualProperty(PropertyMap map)
434         {
435             if (map == null) return;
436             if (cachedImagePropertyMap == null)
437             {
438                 cachedImagePropertyMap = new PropertyMap();
439             }
440             foreach (var key in cachedAnimatedImagePropertyKeyList)
441             {
442                 PropertyValue value = map.Find(key);
443                 if (value != null)
444                 {
445                     // Update-or-Insert new value
446                     cachedImagePropertyMap[key] = value;
447                 }
448             }
449             base.MergeCachedImageVisualProperty(map);
450         }
451         #endregion Method
452
453         #region Event, Enum, Struct, ETC
454
455         /// <summary>
456         /// Enumeration for what to do when the animation is stopped.
457         /// </summary>
458         [EditorBrowsable(EditorBrowsableState.Never)]
459         public enum StopBehaviorType
460         {
461             /// <summary>
462             /// When the animation is stopped, the current frame is shown.
463             /// </summary>
464             [EditorBrowsable(EditorBrowsableState.Never)]
465             CurrentFrame,
466             /// <summary>
467             /// When the animation is stopped, the min frame (first frame) is shown.
468             /// </summary>
469             [EditorBrowsable(EditorBrowsableState.Never)]
470             MinimumFrame,
471             /// <summary>
472             /// When the animation is stopped, the max frame (last frame) is shown.
473             /// </summary>
474             [EditorBrowsable(EditorBrowsableState.Never)]
475             MaximumFrame
476         }
477
478         #endregion Event, Enum, Struct, ETC
479     }
480 }