1b9ac72b39b76d49a57c40e8c826d1ab40bcc355
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / AnimatedVectorImageView.cs
1 /*
2  * Copyright(c) 2021 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 global::System;
19 using System.ComponentModel;
20
21 namespace Tizen.NUI.BaseComponents
22 {
23     /// <summary>
24     /// AnimatedVectorImageView is a class for displaying a vector resource.
25     /// </summary>
26     [EditorBrowsable(EditorBrowsableState.Never)]
27     public partial class AnimatedVectorImageView : LottieAnimationView
28     {
29         #region Constructor, Destructor, Dispose
30         /// <summary>
31         /// Construct VectorAnimationView.
32         /// </summary>
33         [EditorBrowsable(EditorBrowsableState.Never)]
34         public AnimatedVectorImageView() : base()
35         {
36             NUILog.Debug($"[AnimatedVectorImageView START[ constructor objId={GetId()} ] END]");
37         }
38
39         /// <summary>
40         /// Construct VectorAnimationView.
41         /// </summary>
42         /// <param name="scale">Set scaling factor for Vector Animation, while creating.</param>
43         [EditorBrowsable(EditorBrowsableState.Never)]
44         public AnimatedVectorImageView(float scale) : base(scale)
45         {
46             NUILog.Debug($"[AnimatedVectorImageView START[ constructor scale={scale}) objId={GetId()} ] END]");
47         }
48
49         /// <summary>
50         /// You can override it to clean-up your own resources
51         /// </summary>
52         /// <param name="type">DisposeTypes</param>
53         [EditorBrowsable(EditorBrowsableState.Never)]
54         protected override void Dispose(DisposeTypes type)
55         {
56             if (disposed)
57             {
58                 return;
59             }
60             NUILog.Debug($"AnimatedVectorImageView START");
61
62             //Release your own unmanaged resources here.
63             //You should not access any managed member here except static instance.
64             //because the execution order of Finalizes is non-deterministic.
65
66             base.Dispose(type);
67
68             NUILog.Debug($"AnimatedVectorImageView END");
69         }
70         #endregion Constructor, Destructor, Dispose
71
72
73         #region Property
74         /// <summary>
75         /// Set Resource URL
76         /// </summary>
77         // Suppress warning : This has been being used by users, so that the interface can not be changed.
78         [EditorBrowsable(EditorBrowsableState.Never)]
79         public string ResourceURL
80         {
81             get
82             {
83                 return GetValue(ResourceURLProperty) as string;
84             }
85             set
86             {
87                 SetValue(ResourceURLProperty, value);
88                 NotifyPropertyChanged();
89             }
90         }
91
92         private string InternalResourceURL
93         {
94             set
95             {
96                 NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] ResourceURL SET");
97
98                 if (value == resourceUrl)
99                 {
100                     NUILog.Debug($"set same URL! ");
101                     return;
102                 }
103                 resourceUrl = (value == null) ? "" : value;
104                 URL = resourceUrl;
105                 isMinMaxFrameSet = minMaxSetTypes.NotSetByUser;
106                 totalFrameNum = base.TotalFrame;
107                 NUILog.Debug($" [{GetId()}] resourceUrl={resourceUrl}) ]AnimatedVectorImageView END]");
108             }
109             get => resourceUrl;
110         }
111
112         /// <summary>
113         /// Set Resource URL
114         /// </summary>
115         // Suppress warning : This has been being used by users, so that the interface can not be changed.
116         [EditorBrowsable(EditorBrowsableState.Never)]
117         public new string ResourceUrl
118         {
119             get
120             {
121                 return GetValue(ResourceUrlProperty) as string;
122             }
123             set
124             {
125                 SetValue(ResourceUrlProperty, value);
126                 NotifyPropertyChanged();
127             }
128         }
129
130         private string InternalResourceUrl
131         {
132             set
133             {
134                 NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] ResourceUrl SET");
135                 this.ResourceURL = value;
136                 NUILog.Debug($" [{GetId()}] value={value}) ]AnimatedVectorImageView END]");
137             }
138             get
139             {
140                 NUILog.Debug($"[AnimatedVectorImageView [ [{GetId()}] ResourceUrl GET");
141                 return this.ResourceURL;
142             }
143         }
144
145
146         /// <summary>
147         /// RepeatCount of animation.
148         /// The repeat count is 0 by default.
149         /// If the RepeatCount is 0, the animation is never repeated.
150         /// If the RepeatCount is greater than 0, the repeat mode will be taken into account.
151         /// If RepeatCount is -1, animation is infinite loops.
152         /// </summary>
153         [EditorBrowsable(EditorBrowsableState.Never)]
154         public int RepeatCount
155         {
156             get
157             {
158                 return (int)GetValue(RepeatCountProperty);
159             }
160             set
161             {
162                 SetValue(RepeatCountProperty, value);
163                 NotifyPropertyChanged();
164             }
165         }
166
167         private int InternalRepeatCount
168         {
169             set
170             {
171                 NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] RepeatCount SET");
172
173                 repeatCnt = (value < -1) ? -1 : value;
174                 LoopCount = (repeatCnt < 0) ? repeatCnt : repeatCnt + 1;
175
176                 NUILog.Debug($"[{GetId()}] repeatCnt={repeatCnt} ]AnimatedVectorImageView END]");
177             }
178             get => repeatCnt;
179         }
180
181         /// <summary>
182         /// TotalFrame of animation.
183         /// </summary>
184         [EditorBrowsable(EditorBrowsableState.Never)]
185         public new int TotalFrame
186         {
187             get => totalFrameNum;
188         }
189
190         /// <summary>
191         /// CurrentFrame of animation.
192         /// </summary>
193         /// <returns> Returns user set value for the current frame. Cannot provide actual playing current frame. </returns>
194         [EditorBrowsable(EditorBrowsableState.Never)]
195         public new int CurrentFrame
196         {
197             get
198             {
199                 return (int)GetValue(CurrentFrameProperty);
200             }
201             set
202             {
203                 SetValue(CurrentFrameProperty, value);
204                 NotifyPropertyChanged();
205             }
206         }
207
208         private int InternalCurrentFrame
209         {
210             set
211             {
212                 NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] CurrentFrame SET");
213
214                 if (string.IsNullOrEmpty(resourceUrl))
215                 {
216                     throw new InvalidOperationException("Resource Url not yet Set");
217                 }
218
219                 if (value < 0)
220                 {
221                     value = 0;
222                 }
223                 else if (value >= totalFrameNum)
224                 {
225                     value = totalFrameNum - 1;
226                 }
227
228                 innerCurrentFrame = value;
229                 AnimationState = AnimationStates.Paused;
230
231                 base.SetMinMaxFrame(0, totalFrameNum - 1);
232                 base.CurrentFrame = innerCurrentFrame;
233
234                 NUILog.Debug($" [{GetId()}] innerCurrentFrame={innerCurrentFrame}) ]AnimatedVectorImageView END]");
235             }
236             get => innerCurrentFrame;
237         }
238
239         /// <summary>
240         /// RepeatMode of animation.
241         /// </summary>
242         [EditorBrowsable(EditorBrowsableState.Never)]
243         public RepeatModes RepeatMode
244         {
245             get
246             {
247                 return (RepeatModes)GetValue(RepeatModeProperty);
248             }
249             set
250             {
251                 SetValue(RepeatModeProperty, value);
252                 NotifyPropertyChanged();
253             }
254         }
255
256         private RepeatModes InternalRepeatMode
257         {
258             set
259             {
260                 NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] RepeatMode SET");
261                 repeatMode = value;
262
263                 switch (repeatMode)
264                 {
265                     case RepeatModes.Restart:
266                         LoopingMode = LoopingModeType.Restart;
267                         break;
268                     case RepeatModes.Reverse:
269                         LoopingMode = LoopingModeType.AutoReverse;
270                         break;
271                     default:
272                         LoopingMode = LoopingModeType.Restart;
273                         break;
274                 }
275
276                 NUILog.Debug($" [{GetId()}] repeatMode={repeatMode}) ]AnimatedVectorImageView END]");
277             }
278             get => repeatMode;
279         }
280
281         /// <summary>
282         /// Get state of animation.
283         /// </summary>
284         [EditorBrowsable(EditorBrowsableState.Never)]
285         public AnimationStates AnimationState
286         {
287             private set
288             {
289                 CurrentAnimationState = value;
290             }
291             get
292             {
293                 if (CurrentAnimationState == AnimationStates.Playing)
294                 {
295                     if (PlayState == PlayStateType.Stopped)
296                     {
297                         CurrentAnimationState = AnimationStates.Stopped;
298                     }
299                 }
300                 return CurrentAnimationState;
301             }
302         }
303         #endregion Property
304
305
306         #region Method
307         /// <summary>
308         /// Set minimum frame and maximum frame
309         /// </summary>
310         /// <param name="minFrame">minimum frame.</param>
311         /// <param name="maxFrame">maximum frame.</param>
312         [EditorBrowsable(EditorBrowsableState.Never)]
313         public void SetMinAndMaxFrame(int minFrame, int maxFrame)
314         {
315             NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] SetMinAndMaxFrame({minFrame}, {maxFrame})");
316
317             minimumFrame = (minFrame) > 0 ? minFrame : 0;
318             maximumFrame = (maxFrame) > 0 ? maxFrame : 0;
319             isMinMaxFrameSet = minMaxSetTypes.SetByMinAndMaxFrameMethod;
320
321             if (minimumFrame >= totalFrameNum)
322             {
323                 minimumFrame = totalFrameNum - 1;
324             }
325
326             if (maximumFrame >= totalFrameNum)
327             {
328                 maximumFrame = totalFrameNum - 1;
329             }
330
331             if (minimumFrame > maximumFrame)
332             {
333                 return;
334             }
335
336             NUILog.Debug($" [{GetId()}] minimumFrame:{minimumFrame}, maximumFrame:{maximumFrame}) ]AnimatedVectorImageView END]");
337         }
338
339         /// <summary>
340         /// SetMinMaxFrame(int startFrame, int endFrame)
341         /// </summary>
342         /// <param name="minFrame"></param>
343         /// <param name="maxFrame"></param>
344         [EditorBrowsable(EditorBrowsableState.Never)]
345         public new void SetMinMaxFrame(int minFrame, int maxFrame)
346         {
347             NUILog.Debug($"SetMinMaxFrame({minFrame}, {maxFrame})!!!");
348
349             minimumFrame = (minFrame) > 0 ? minFrame : 0;
350             maximumFrame = (maxFrame) > 0 ? maxFrame : 0;
351             isMinMaxFrameSet = minMaxSetTypes.SetByBaseSetMinMaxFrameMethod;
352
353             if (minimumFrame >= totalFrameNum)
354             {
355                 minimumFrame = totalFrameNum - 1;
356             }
357
358             if (maximumFrame >= totalFrameNum)
359             {
360                 maximumFrame = totalFrameNum - 1;
361             }
362
363             base.SetMinMaxFrame(minimumFrame, maximumFrame);
364         }
365
366         /// <summary>
367         /// A marker has its start frame and end frame. 
368         /// Animation will play between the start frame and the end frame of the marker if one marker is specified.
369         /// Or animation will play between the start frame of the first marker and the end frame of the second marker if two markers are specified.   *
370         /// </summary>
371         /// <param name="marker1">First marker</param>
372         /// <param name="marker2">Second marker</param>
373         [EditorBrowsable(EditorBrowsableState.Never)]
374         public new void SetMinMaxFrameByMarker(string marker1, string marker2 = null)
375         {
376             NUILog.Debug($"SetMinMaxFrameByMarker({marker1}, {marker2})");
377             isMinMaxFrameSet = minMaxSetTypes.SetByMarker;
378             base.SetMinMaxFrameByMarker(marker1, marker2);
379         }
380
381         /// <summary>
382         /// Play Animation.
383         /// </summary>
384         [EditorBrowsable(EditorBrowsableState.Never)]
385         public new void Play()
386         {
387             NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] AnimationState={AnimationState}, PlayState={PlayState}");
388
389             if (string.IsNullOrEmpty(resourceUrl))
390             {
391                 throw new InvalidOperationException("Resource Url not yet Set");
392             }
393
394             switch (isMinMaxFrameSet)
395             {
396                 case minMaxSetTypes.NotSetByUser:
397                     base.SetMinMaxFrame(0, totalFrameNum - 1);
398                     base.CurrentFrame = 0;
399                     break;
400
401                 case minMaxSetTypes.SetByMinAndMaxFrameMethod:
402                     base.SetMinMaxFrame(minimumFrame, maximumFrame);
403                     base.CurrentFrame = minimumFrame;
404                     break;
405
406                 case minMaxSetTypes.SetByMarker:
407                 case minMaxSetTypes.SetByBaseSetMinMaxFrameMethod:
408                 default:
409                     //do nothing!
410                     break;
411             }
412
413             //temporal fix
414             Extents tmp = base.Margin;
415             base.Margin = tmp;
416
417             base.Play();
418             AnimationState = AnimationStates.Playing;
419
420             NUILog.Debug($" [{GetId()}] isMinMaxFrameSet={isMinMaxFrameSet}) ]AnimatedVectorImageView END]");
421         }
422
423         /// <summary>
424         /// Pause Animation.
425         /// </summary>
426         [EditorBrowsable(EditorBrowsableState.Never)]
427         public new void Pause()
428         {
429             NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] AnimationState={AnimationState}, PlayState={PlayState}");
430
431             if (string.IsNullOrEmpty(resourceUrl))
432             {
433                 throw new InvalidOperationException("Resource Url not yet Set");
434             }
435
436             base.Pause();
437             AnimationState = AnimationStates.Paused;
438
439             NUILog.Debug($" [{GetId()}] ]AnimatedVectorImageView END]");
440         }
441
442         /// <summary>
443         /// Stop Animation.
444         /// </summary>
445         /// <param name="endAction">Defines, what should be behaviour after cancel operation
446         /// End action is Cancel, Animation Stops at the Current Frame.
447         /// End action is Discard, Animation Stops at the Min Frame
448         /// End action is StopFinal, Animation Stops at the Max Frame
449         /// </param>
450         [EditorBrowsable(EditorBrowsableState.Never)]
451         public void Stop(EndActions endAction = EndActions.Cancel)
452         {
453             NUILog.Debug($"[AnimatedVectorImageView START[ [{GetId()}] endAction:({endAction}), PlayState={PlayState}");
454
455             if (string.IsNullOrEmpty(resourceUrl))
456             {
457                 throw new InvalidOperationException("Resource Url not yet Set");
458             }
459
460             if (AnimationState == AnimationStates.Stopped)
461             {
462                 return;
463             }
464
465             if (innerEndAction != endAction)
466             {
467                 innerEndAction = endAction;
468                 switch (endAction)
469                 {
470                     case EndActions.Cancel:
471                         StopBehavior = StopBehaviorType.CurrentFrame;
472                         break;
473                     case EndActions.Discard:
474                         StopBehavior = StopBehaviorType.MinimumFrame;
475                         break;
476                     case EndActions.StopFinal:
477                         StopBehavior = StopBehaviorType.MaximumFrame;
478                         break;
479                     default:
480                         NUILog.Debug($" [{GetId()}] no endAction : default set");
481                         break;
482                 }
483             }
484             AnimationState = AnimationStates.Stopped;
485
486             base.Stop();
487
488             if (endAction == EndActions.StopFinal)
489             {
490                 switch (isMinMaxFrameSet)
491                 {
492                     case minMaxSetTypes.NotSetByUser:
493                         if (base.CurrentFrame != totalFrameNum - 1)
494                         {
495                             NUILog.Debug($"isMinMaxFrameSet:{isMinMaxFrameSet}, CurrentFrameNumber:{base.CurrentFrame}, totalFrameNum:{ totalFrameNum}");
496                             base.CurrentFrame = totalFrameNum - 1;
497                             NUILog.Debug($"set CurrentFrameNumber({base.CurrentFrame}) as totalFrameNum({maximumFrame}) - 1 !");
498                         }
499                         break;
500
501                     case minMaxSetTypes.SetByMinAndMaxFrameMethod:
502                         if (base.CurrentFrame != maximumFrame)
503                         {
504                             NUILog.Debug($"isMinMaxFrameSet:{isMinMaxFrameSet}, CurrentFrameNumber:{base.CurrentFrame}, maximumFrame:{ maximumFrame}");
505                             base.CurrentFrame = maximumFrame;
506                             NUILog.Debug($"set CurrentFrameNumber({base.CurrentFrame}) as maximumFrame({maximumFrame})!!!");
507                         }
508                         break;
509                     case minMaxSetTypes.SetByBaseSetMinMaxFrameMethod:
510                     case minMaxSetTypes.SetByMarker:
511                     default:
512                         //do nothing!
513                         break;
514                 }
515             }
516             NUILog.Debug($" [{GetId()}] ]AnimatedVectorImageView END]");
517         }
518         #endregion Method
519
520
521         #region Event, Enum, Struct, ETC
522         /// <summary>
523         /// RepeatMode of animation.
524         /// </summary>
525         // Suppress warning : This has been being used by users, so that the interface can not be changed.
526         [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1717:Only FlagsAttribute enums should have plural names", Justification = "<Pending>")]
527         [EditorBrowsable(EditorBrowsableState.Never)]
528         public enum RepeatModes
529         {
530             /// <summary>
531             /// When the animation reaches the end and RepeatCount is nonZero, the animation restarts from the beginning. 
532             /// </summary>
533             [EditorBrowsable(EditorBrowsableState.Never)]
534             Restart = LoopingModeType.Restart,
535             /// <summary>
536             /// When the animation reaches the end and RepeatCount nonZero, the animation reverses direction on every animation cycle. 
537             /// </summary>
538             [EditorBrowsable(EditorBrowsableState.Never)]
539             Reverse = LoopingModeType.AutoReverse
540         }
541
542         /// <summary>
543         /// EndActions of animation.
544         /// </summary>
545         // Suppress warning : This has been being used by users, so that the interface can not be changed.
546         [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1717:Only FlagsAttribute enums should have plural names", Justification = "<Pending>")]
547         [EditorBrowsable(EditorBrowsableState.Never)]
548         public enum EndActions
549         {
550             /// <summary> End action is Cancel, Animation Stops at the Current Frame.</summary>
551             [EditorBrowsable(EditorBrowsableState.Never)]
552             Cancel = 0,
553             /// <summary>  End action is Discard, Animation Stops at the Min Frame</summary>
554             [EditorBrowsable(EditorBrowsableState.Never)]
555             Discard = 1,
556             /// <summary> End action is StopFinal, Animation Stops at the Max Frame</summary>
557             [EditorBrowsable(EditorBrowsableState.Never)]
558             StopFinal = 2
559         }
560
561         /// <summary>
562         /// AnimationStates of animation.
563         /// </summary>
564         // Suppress warning : This has been being used by users, so that the interface can not be changed.
565         [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1717:Only FlagsAttribute enums should have plural names", Justification = "<Pending>")]
566         [EditorBrowsable(EditorBrowsableState.Never)]
567         public enum AnimationStates
568         {
569             /// <summary> The animation has stopped.</summary>
570             [EditorBrowsable(EditorBrowsableState.Never)]
571             Stopped = PlayStateType.Stopped,
572             /// <summary> The animation is playing.</summary>
573             [EditorBrowsable(EditorBrowsableState.Never)]
574             Playing = PlayStateType.Playing,
575             /// <summary> The animation is paused.</summary>
576             [EditorBrowsable(EditorBrowsableState.Never)]
577             Paused = PlayStateType.Paused
578         }
579         #endregion Event, Enum, Struct, ETC
580
581
582         #region Internal
583         #endregion Internal
584
585
586         #region Private
587         private string resourceUrl = null;
588         private int repeatCnt = 0;
589         private int totalFrameNum = 0;
590         private RepeatModes repeatMode = RepeatModes.Restart;
591         private int minimumFrame = -1, maximumFrame = -1;
592         private minMaxSetTypes isMinMaxFrameSet = minMaxSetTypes.NotSetByUser;
593         private int innerCurrentFrame = -1;
594         private EndActions innerEndAction = EndActions.Cancel;
595         private enum minMaxSetTypes
596         {
597             NotSetByUser,
598             SetByMinAndMaxFrameMethod,
599             SetByMarker,
600             SetByBaseSetMinMaxFrameMethod,
601         }
602
603         private string tag = "NUITEST";
604         private AnimationStates CurrentAnimationState = AnimationStates.Stopped;
605         #endregion Private
606     }
607 }