[NUI] Implement missing properties for LottieAnimationView.
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / VisualView.cs
1 // Copyright (c) 2019 Samsung Electronics Co., Ltd.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15
16 using System;
17 using System.Text;
18 using System.Runtime.InteropServices;
19 using System.Collections.Generic;
20 using System.Linq;
21 using System.ComponentModel;
22
23 namespace Tizen.NUI.BaseComponents
24 {
25     /// <summary>
26     /// A visual view control if a user adds any visual to it.
27     /// </summary>
28     /// <example>
29     /// Example:
30     /// <code>
31     /// VisualView _visualView = new VisualView();
32     /// ImageVisualMap imageVisualMap1 = new ImageVisualMap();
33     /// imageVisualMap1.URL = "./NUISample/res/images/image-1.jpg";
34     /// imageVisualMap1.VisualSize = new Vector2( 300.0f, 300.0f );
35     /// imageVisualMap1.Offset = new Vector2( 50.0f, 50.0f );
36     /// imageVisualMap1.OffsetSizeMode = new Vector4( 1.0f, 1.0f, 1.0f, 1.0f );
37     /// imageVisualMap1.Origin = AlignType.TOP_BEGIN;
38     /// imageVisualMap1.AnchorPoint = AlignType.TOP_BEGIN;
39     /// _visualView.AddVisual("imageVisual1", imageVisualMap1);
40     /// </code>
41     /// </example>
42     /// <since_tizen> 3 </since_tizen>
43     public class VisualView : CustomView
44     {
45         private Dictionary<int, string> visualNameDictionary = null;
46         private Dictionary<int, VisualBase> visualDictionary = null;
47         private Dictionary<int, PropertyMap> tranformDictionary = null;
48         private PropertyArray animateArray = null;
49
50         /// <summary>
51         /// Constructor.
52         /// </summary>
53         /// <since_tizen> 3 </since_tizen>
54         public VisualView() : this(CustomViewBehaviour.ViewBehaviourDefault | CustomViewBehaviour.RequiresTouchEventsSupport)
55         {
56         }
57
58         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
59         [EditorBrowsable(EditorBrowsableState.Never)]
60         public VisualView(ViewStyle viewStyle) : this(CustomViewBehaviour.ViewBehaviourDefault | CustomViewBehaviour.RequiresTouchEventsSupport, viewStyle)
61         {
62
63         }
64
65         /// <summary>Create a VisualView with specified behaviour.</summary>
66         /// <param name="behaviour">CustomView behaviour</param>
67         [EditorBrowsable(EditorBrowsableState.Never)]
68         public VisualView(CustomViewBehaviour behaviour) : base(typeof(VisualView).FullName, behaviour)
69         {
70         }
71
72         /// <summary>Create a VisualView with specified behaviour and a style.</summary>
73         /// <param name="behaviour">CustomView behaviour</param>
74         /// <param name="viewStyle">The ViewStyle.</param>
75         [EditorBrowsable(EditorBrowsableState.Never)]
76         public VisualView(CustomViewBehaviour behaviour, ViewStyle viewStyle) : base(typeof(VisualView).FullName, behaviour, viewStyle)
77         {
78         }
79
80         // static constructor registers the control type (for user can add kinds of visuals to it)
81         static VisualView()
82         {
83             // ViewRegistry registers control type with DALi type registry
84             // also uses introspection to find any properties that need to be registered with type registry
85             CustomViewRegistry.Instance.Register(CreateInstance, typeof(VisualView));
86         }
87
88         /// <summary>
89         /// Gets the total number of visuals which are added by users.
90         /// </summary>
91         /// <since_tizen> 3 </since_tizen>
92         public int NumberOfVisuals
93         {
94             get
95             {
96                 return visualDictionary.Count;
97             }
98         }
99
100         /// <summary>
101         /// Overrides the parent method.
102         /// </summary>
103         /// <since_tizen> 3 </since_tizen>
104         public override void OnInitialize()
105         {
106             base.OnInitialize();
107
108             //Initialize empty
109             visualNameDictionary = new Dictionary<int, string>();
110             visualDictionary = new Dictionary<int, VisualBase>();
111             tranformDictionary = new Dictionary<int, PropertyMap>();
112             animateArray = new PropertyArray();
113         }
114
115         /// <summary>
116         /// Adds or updates a visual to visual view.
117         /// </summary>
118         /// <param name="visualName">The name of a visual to add. If a name is added to an existing visual name, the visual will be replaced.</param>
119         /// <param name="visualMap">The property map of a visual to create.</param>
120         /// <exception cref="ArgumentNullException"> Thrown when visualMap is null. </exception>
121         /// <since_tizen> 3 </since_tizen>
122         public void AddVisual(string visualName, VisualMap visualMap)
123         {
124             int visualIndex = -1;
125
126             /* If the visual had added, then replace it using RegisterVusal. */
127             //visual.Name = name;
128             foreach (var item in visualNameDictionary)
129             {
130                 if (item.Value == visualName)
131                 {
132                     /* Find a existed visual, its key also exited. */
133                     visualIndex = item.Key;
134                     UnregisterVisual(visualIndex);
135                     visualNameDictionary.Remove(visualIndex);
136                     visualDictionary.Remove(visualIndex);
137                     tranformDictionary.Remove(visualIndex);
138                     break;
139                 }
140             }
141
142             if (visualIndex == -1) // The visual is a new one, create index for it. */
143             {
144                 using (var temp = new PropertyValue(visualName))
145                 {
146                     visualIndex = RegisterProperty(visualName, temp, PropertyAccessMode.ReadWrite);
147                 }
148             }
149
150             if (visualIndex > 0)
151             {
152                 if (visualMap == null)
153                 {
154                     throw new ArgumentNullException(nameof(visualMap));
155                 }
156
157                 visualMap.VisualIndex = visualIndex;
158                 visualMap.Name = visualName;
159                 visualMap.Parent = this;
160
161                 // Register index and name
162                 UpdateVisual(visualIndex, visualName, visualMap);
163             }
164         }
165
166         /// <summary>
167         /// Removes a visual by name.
168         /// </summary>
169         /// <param name="visualName">The name of a visual to remove.</param>
170         /// <since_tizen> 3 </since_tizen>
171         public void RemoveVisual(string visualName)
172         {
173             foreach (var item in visualNameDictionary)
174             {
175                 if (item.Value == visualName)
176                 {
177                     EnableVisual(item.Key, false);
178                     UnregisterVisual(item.Key);
179                     tranformDictionary.Remove(item.Key);
180                     visualDictionary.Remove(item.Key);
181                     visualNameDictionary.Remove(item.Key);
182
183                     RelayoutRequest();
184                     break;
185                 }
186             }
187         }
188
189         /// <summary>
190         /// Removes all visuals of the visual view.
191         /// </summary>
192         /// <since_tizen> 3 </since_tizen>
193         public void RemoveAll()
194         {
195             foreach (var item in visualNameDictionary)
196             {
197                 EnableVisual(item.Key, false);
198                 UnregisterVisual(item.Key);
199             }
200             visualDictionary.Clear();
201             tranformDictionary.Clear();
202             visualNameDictionary.Clear();
203             RelayoutRequest();
204         }
205
206         /// <summary>
207         /// Overrides the method of OnRelayout() for CustomView class.<br />
208         /// Called after the size negotiation has been finished for this control.<br />
209         /// The control is expected to assign this given size to itself or its children.<br />
210         /// Should be overridden by derived classes if they need to layout actors differently after certain operations like add or remove actors, resize, or after changing specific properties.<br />
211         /// </summary>
212         /// <remarks>As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).</remarks>
213         /// <param name="size">The allocated size.</param>
214         /// <param name="container">The control should add actors to this container that it is not able to allocate a size for.</param>
215         /// <since_tizen> 3 </since_tizen>
216         public override void OnRelayout(Vector2 size, RelayoutContainer container)
217         {
218             foreach (var item in visualDictionary)
219             {
220                 if(item.Value != null)
221                 {
222                     item.Value.SetTransformAndSize(tranformDictionary[item.Key], size);
223                     EnableVisual(item.Key, true);
224                 }
225             }
226         }
227
228         /// <summary>
229         /// Creates a visual animation (transition) with the input parameters.
230         /// </summary>
231         /// <param name="target">The visual map to animation.</param>
232         /// <param name="property">The property of visual to animation.</param>
233         /// <param name="destinationValue">The destination value of property after animation.</param>
234         /// <param name="startTime">The start time of visual animation.</param>
235         /// <param name="endTime">The end time of visual animation.</param>
236         /// <param name="alphaFunction">The alpha function of visual animation.</param>
237         /// <param name="initialValue">The initial property value of visual animation.</param>
238         /// <returns>Animation instance</returns>
239         /// <exception cref="ArgumentNullException"> Thrown when target is null. </exception>
240         /// <since_tizen> 3 </since_tizen>
241         public Animation AnimateVisual(VisualMap target, string property, object destinationValue, int startTime, int endTime, AlphaFunction.BuiltinFunctions? alphaFunction = null, object initialValue = null)
242         {
243             if (target == null)
244             {
245                 throw new ArgumentNullException(nameof(target));
246             }
247
248             string strAlpha = alphaFunction?.GetDescription();
249
250             foreach (var item in visualNameDictionary.ToList())
251             {
252                 if (item.Value == target.Name)
253                 {
254                     using (PropertyMap animator = new PropertyMap())
255                     using (PropertyMap timePeriod = new PropertyMap())
256                     using (PropertyValue pvDuration = new PropertyValue((endTime - startTime) / 1000.0f))
257                     using (PropertyValue pvDelay = new PropertyValue(startTime / 1000.0f))
258                     using (PropertyValue destVal = PropertyValue.CreateFromObject(destinationValue))
259                     using (PropertyMap transition = new PropertyMap())
260                     using (PropertyValue pvTarget = new PropertyValue(target.Name))
261                     {
262                         if (strAlpha != null)
263                         {
264                             using (PropertyValue pvAlpha = new PropertyValue(strAlpha))
265                             {
266                                 animator.Add("alphaFunction", pvAlpha);
267                             }
268                         }
269                         timePeriod.Add("duration", pvDuration);
270                         timePeriod.Add("delay", pvDelay);
271                         using (PropertyValue pvTimePeriod = new PropertyValue(timePeriod))
272                         {
273                             animator.Add("timePeriod", pvTimePeriod);
274                         }
275
276                         StringBuilder sb = new StringBuilder(property);
277                         sb[0] = (char)(sb[0] | 0x20);
278                         string _str = sb.ToString();
279                         if (_str == "position") { _str = "offset"; }
280
281                         transition.Add("target", pvTarget);
282                         using (PropertyValue pvStr = new PropertyValue(_str))
283                         {
284                             transition.Add("property", pvStr);
285                         }
286
287                         if (initialValue != null)
288                         {
289                             using (PropertyValue initVal = PropertyValue.CreateFromObject(initialValue))
290                             using (PropertyValue pvInitialValue = new PropertyValue(initVal))
291                             {
292                                 transition.Add("initialValue", pvInitialValue);
293                             }
294                         }
295                         transition.Add("targetValue", destVal);
296                         using (PropertyValue pvAnimator = new PropertyValue(animator))
297                         {
298                             transition.Add("animator", pvAnimator);
299                         }
300
301                         using (TransitionData transitionData = new TransitionData(transition))
302                         {
303                             return this.CreateTransition(transitionData);
304                         }
305                     }
306                 }
307             }
308             return null;
309         }
310
311         /// <summary>
312         /// Adds a group visual animation (transition) map with the input parameters.
313         /// </summary>
314         /// <param name="target">The visual map to animation.</param>
315         /// <param name="property">The property of visual to animation.</param>
316         /// <param name="destinationValue">The destination value of property after animation.</param>
317         /// <param name="startTime">The start time of visual animation.</param>
318         /// <param name="endTime">The end time of visual animation.</param>
319         /// <param name="alphaFunction">The alpha function of visual animation.</param>
320         /// <param name="initialValue">The initial property value of visual animation.</param>
321         /// <exception cref="ArgumentNullException"> Thrown when target is null. </exception>
322         /// <since_tizen> 3 </since_tizen>
323         public void AnimateVisualAdd(VisualMap target, string property, object destinationValue, int startTime, int endTime, AlphaFunction.BuiltinFunctions? alphaFunction = null, object initialValue = null)
324         {
325             if (target == null)
326             {
327                 throw new ArgumentNullException(nameof(target));
328             }
329
330             string strAlpha = alphaFunction?.GetDescription();
331
332             foreach (var item in visualNameDictionary.ToList())
333             {
334                 if (item.Value == target.Name)
335                 {
336                     using (PropertyMap animator = new PropertyMap())
337                     using (PropertyMap timePeriod = new PropertyMap())
338                     using (PropertyValue pvDuration = new PropertyValue((endTime - startTime) / 1000.0f))
339                     using (PropertyValue pvDelay = new PropertyValue(startTime / 1000.0f))
340                     using (PropertyValue destVal = PropertyValue.CreateFromObject(destinationValue))
341                     using (PropertyMap transition = new PropertyMap())
342                     using (PropertyValue pvTarget = new PropertyValue(target.Name))
343                     {
344                         if (strAlpha != null)
345                         {
346                             using (PropertyValue pvStrAlpha = new PropertyValue(strAlpha))
347                             {
348                                 animator.Add("alphaFunction", pvStrAlpha);
349                             }
350                         }
351
352                         timePeriod.Add("duration", pvDuration);
353                         timePeriod.Add("delay", pvDelay);
354                         using (PropertyValue pvTimePeriod = new PropertyValue(timePeriod))
355                         {
356                             animator.Add("timePeriod", pvTimePeriod);
357                         }
358
359                         StringBuilder sb = new StringBuilder(property);
360                         sb[0] = (char)(sb[0] | 0x20);
361                         string _str = sb.ToString();
362                         if (_str == "position") { _str = "offset"; }
363
364                         transition.Add("target", pvTarget);
365                         using (PropertyValue pvStr = new PropertyValue(_str))
366                         {
367                             transition.Add("property", pvStr);
368                         }
369
370                         if (initialValue != null)
371                         {
372                             using (PropertyValue initVal = PropertyValue.CreateFromObject(initialValue))
373                             using (PropertyValue pvInitialValue = new PropertyValue(initVal))
374                             {
375                                 transition.Add("initialValue", pvInitialValue);
376                             }
377                         }
378                         transition.Add("targetValue", destVal);
379                         using (PropertyValue pvAnimator = new PropertyValue(animator))
380                         {
381                             transition.Add("animator", pvAnimator);
382                         }
383
384                         using (PropertyValue pvTransition = new PropertyValue(transition))
385                         {
386                             PropertyArray temp = animateArray.Add(pvTransition);
387                             temp.Dispose();
388                         }
389                     }
390                 }
391             }
392         }
393
394         /// <summary>
395         /// Finishes to add a visual animation (transition) map and creates a transition animation.
396         /// </summary>
397         /// <returns>Animation instance.</returns>
398         /// <since_tizen> 3 </since_tizen>
399         public Animation AnimateVisualAddFinish()
400         {
401             if (animateArray == null || animateArray.Empty())
402             {
403                 Tizen.Log.Fatal("NUI", "animate visual property array is empty!");
404                 return null;
405             }
406             TransitionData transitionData = new TransitionData(animateArray);
407             Animation ret = this.CreateTransition(transitionData);
408             transitionData.Dispose();
409             return ret;
410         }
411
412         /// <summary>
413         /// temporary fix to pass TCT.
414         /// </summary>
415         /// <exception cref="ArgumentNullException"> Thrown when visualMap is null. </exception>
416         /// <since_tizen> 3 </since_tizen>
417         public Animation VisualAnimate(Tizen.NUI.VisualAnimator visualMap)
418         {
419             if (visualMap == null)
420             {
421                 throw new ArgumentNullException(nameof(visualMap));
422             }
423
424             foreach (var item in visualNameDictionary.ToList())
425             {
426                 if (item.Value == visualMap.Target)
427                 {
428                     using (TransitionData transitionData = new TransitionData(visualMap.OutputVisualMap))
429                     {
430                         return this.CreateTransition(transitionData);
431                     }
432                 }
433             }
434             return null;
435         }
436         //temporary fix to pass TCT
437
438         internal void UpdateVisual(int visualIndex, string visualName, VisualMap visualMap)
439         {
440             VisualBase visual = VisualFactory.Instance.CreateVisual(visualMap.OutputVisualMap);
441
442             visualNameDictionary[visualIndex] = visualName;
443             visualDictionary[visualIndex] = visual;
444             tranformDictionary[visualIndex] = visualMap.OutputTransformMap;
445
446             if(visual != null)
447             {
448                 visual.Name = visualName;
449                 visual.DepthIndex = visualMap.DepthIndex;
450
451                 RegisterVisual(visualIndex, visual);
452
453                 RelayoutRequest();
454                 NUILog.Debug("UpdateVisual() name=" + visualName);
455             }
456             else
457             {
458                 NUILog.Debug("UpdateVisual() FAIL! visual create failed name=" + visualName);
459             }
460         }
461
462         static CustomView CreateInstance()
463         {
464             return new VisualView();
465         }
466
467     }
468 }