[NUI] Add SetUnderline, GetUnderline to Text Components
[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 LinkedList<VisualBase> _visualList = 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             visualDictionary = new Dictionary<int, VisualBase>();
110             tranformDictionary = new Dictionary<int, PropertyMap>();
111             animateArray = new PropertyArray();
112         }
113
114         /// <summary>
115         /// Adds or updates a visual to visual view.
116         /// </summary>
117         /// <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>
118         /// <param name="visualMap">The property map of a visual to create.</param>
119         /// <exception cref="ArgumentNullException"> Thrown when visualMap is null. </exception>
120         /// <since_tizen> 3 </since_tizen>
121         public void AddVisual(string visualName, VisualMap visualMap)
122         {
123             VisualBase visual = null;
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 visualDictionary)
129             {
130                 if (item.Value.Name == visualName)
131                 {
132                     /* Find a existed visual, its key also exited. */
133                     visualIndex = item.Key;
134                     UnregisterVisual(visualIndex);
135                     visualDictionary.Remove(visualIndex);
136                     tranformDictionary.Remove(visualIndex);
137                     break;
138                 }
139             }
140
141             if (visualIndex == -1) // The visual is a new one, create index for it. */
142             {
143                 using (var temp = new PropertyValue(visualName))
144                 {
145                     visualIndex = RegisterProperty(visualName, temp, PropertyAccessMode.ReadWrite);
146                 }
147             }
148
149             if (visualIndex > 0)
150             {
151                 if (visualMap == null)
152                 {
153                     throw new ArgumentNullException(nameof(visualMap));
154                 }
155                 visual = VisualFactory.Instance.CreateVisual(visualMap.OutputVisualMap); // Create a visual for the new one.
156                 visual.Name = visualName;
157                 visual.DepthIndex = visualMap.DepthIndex;
158
159                 RegisterVisual(visualIndex, visual);
160
161                 visualDictionary.Add(visualIndex, visual);
162                 tranformDictionary.Add(visualIndex, visualMap.OutputTransformMap);
163
164                 visualMap.VisualIndex = visualIndex;
165                 visualMap.Name = visualName;
166                 visualMap.Parent = this;
167
168                 RelayoutRequest();
169             }
170         }
171
172         /// <summary>
173         /// Removes a visual by name.
174         /// </summary>
175         /// <param name="visualName">The name of a visual to remove.</param>
176         /// <since_tizen> 3 </since_tizen>
177         public void RemoveVisual(string visualName)
178         {
179             foreach (var item in visualDictionary)
180             {
181                 if (item.Value.Name == visualName)
182                 {
183                     EnableVisual(item.Key, false);
184                     UnregisterVisual(item.Key);
185                     tranformDictionary.Remove(item.Key);
186                     visualDictionary.Remove(item.Key);
187
188                     RelayoutRequest();
189                     break;
190                 }
191             }
192         }
193
194         /// <summary>
195         /// Removes all visuals of the visual view.
196         /// </summary>
197         /// <since_tizen> 3 </since_tizen>
198         public void RemoveAll()
199         {
200             foreach (var item in visualDictionary)
201             {
202                 EnableVisual(item.Key, false);
203                 UnregisterVisual(item.Key);
204             }
205             visualDictionary.Clear();
206             tranformDictionary.Clear();
207             RelayoutRequest();
208         }
209
210         /// <summary>
211         /// Overrides the method of OnRelayout() for CustomView class.<br />
212         /// Called after the size negotiation has been finished for this control.<br />
213         /// The control is expected to assign this given size to itself or its children.<br />
214         /// 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 />
215         /// </summary>
216         /// <remarks>As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).</remarks>
217         /// <param name="size">The allocated size.</param>
218         /// <param name="container">The control should add actors to this container that it is not able to allocate a size for.</param>
219         /// <since_tizen> 3 </since_tizen>
220         public override void OnRelayout(Vector2 size, RelayoutContainer container)
221         {
222             foreach (var item in visualDictionary)
223             {
224                 item.Value.SetTransformAndSize(tranformDictionary[item.Key], size);
225                 EnableVisual(item.Key, true);
226             }
227         }
228
229         /// <summary>
230         /// Creates a visual animation (transition) with the input parameters.
231         /// </summary>
232         /// <param name="target">The visual map to animation.</param>
233         /// <param name="property">The property of visual to animation.</param>
234         /// <param name="destinationValue">The destination value of property after animation.</param>
235         /// <param name="startTime">The start time of visual animation.</param>
236         /// <param name="endTime">The end time of visual animation.</param>
237         /// <param name="alphaFunction">The alpha function of visual animation.</param>
238         /// <param name="initialValue">The initial property value of visual animation.</param>
239         /// <returns>Animation instance</returns>
240         /// <exception cref="ArgumentNullException"> Thrown when target is null. </exception>
241         /// <since_tizen> 3 </since_tizen>
242         public Animation AnimateVisual(VisualMap target, string property, object destinationValue, int startTime, int endTime, AlphaFunction.BuiltinFunctions? alphaFunction = null, object initialValue = null)
243         {
244             if (target == null)
245             {
246                 throw new ArgumentNullException(nameof(target));
247             }
248
249             string strAlpha = alphaFunction?.GetDescription();
250
251             foreach (var item in visualDictionary.ToList())
252             {
253                 if (item.Value.Name == target.Name)
254                 {
255                     using (PropertyMap animator = new PropertyMap())
256                     using (PropertyMap timePeriod = new PropertyMap())
257                     using (PropertyValue pvDuration = new PropertyValue((endTime - startTime) / 1000.0f))
258                     using (PropertyValue pvDelay = new PropertyValue(startTime / 1000.0f))
259                     using (PropertyValue destVal = PropertyValue.CreateFromObject(destinationValue))
260                     using (PropertyMap transition = new PropertyMap())
261                     using (PropertyValue pvTarget = new PropertyValue(target.Name))
262                     {
263                         if (strAlpha != null)
264                         {
265                             using (PropertyValue pvAlpha = new PropertyValue(strAlpha))
266                             {
267                                 animator.Add("alphaFunction", pvAlpha);
268                             }
269                         }
270                         timePeriod.Add("duration", pvDuration);
271                         timePeriod.Add("delay", pvDelay);
272                         using (PropertyValue pvTimePeriod = new PropertyValue(timePeriod))
273                         {
274                             animator.Add("timePeriod", pvTimePeriod);
275                         }
276
277                         StringBuilder sb = new StringBuilder(property);
278                         sb[0] = (char)(sb[0] | 0x20);
279                         string _str = sb.ToString();
280                         if (_str == "position") { _str = "offset"; }
281
282                         transition.Add("target", pvTarget);
283                         using (PropertyValue pvStr = new PropertyValue(_str))
284                         {
285                             transition.Add("property", pvStr);
286                         }
287
288                         if (initialValue != null)
289                         {
290                             using (PropertyValue initVal = PropertyValue.CreateFromObject(initialValue))
291                             using (PropertyValue pvInitialValue = new PropertyValue(initVal))
292                             {
293                                 transition.Add("initialValue", pvInitialValue);
294                             }
295                         }
296                         transition.Add("targetValue", destVal);
297                         using (PropertyValue pvAnimator = new PropertyValue(animator))
298                         {
299                             transition.Add("animator", pvAnimator);
300                         }
301
302                         using (TransitionData transitionData = new TransitionData(transition))
303                         {
304                             return this.CreateTransition(transitionData);
305                         }
306                     }
307                 }
308             }
309             return null;
310         }
311
312         /// <summary>
313         /// Adds a group visual animation (transition) map with the input parameters.
314         /// </summary>
315         /// <param name="target">The visual map to animation.</param>
316         /// <param name="property">The property of visual to animation.</param>
317         /// <param name="destinationValue">The destination value of property after animation.</param>
318         /// <param name="startTime">The start time of visual animation.</param>
319         /// <param name="endTime">The end time of visual animation.</param>
320         /// <param name="alphaFunction">The alpha function of visual animation.</param>
321         /// <param name="initialValue">The initial property value of visual animation.</param>
322         /// <exception cref="ArgumentNullException"> Thrown when target is null. </exception>
323         /// <since_tizen> 3 </since_tizen>
324         public void AnimateVisualAdd(VisualMap target, string property, object destinationValue, int startTime, int endTime, AlphaFunction.BuiltinFunctions? alphaFunction = null, object initialValue = null)
325         {
326             if (target == null)
327             {
328                 throw new ArgumentNullException(nameof(target));
329             }
330
331             string strAlpha = alphaFunction?.GetDescription();
332
333             foreach (var item in visualDictionary.ToList())
334             {
335                 if (item.Value.Name == target.Name)
336                 {
337                     using (PropertyMap animator = new PropertyMap())
338                     using (PropertyMap timePeriod = new PropertyMap())
339                     using (PropertyValue pvDuration = new PropertyValue((endTime - startTime) / 1000.0f))
340                     using (PropertyValue pvDelay = new PropertyValue(startTime / 1000.0f))
341                     using (PropertyValue destVal = PropertyValue.CreateFromObject(destinationValue))
342                     using (PropertyMap transition = new PropertyMap())
343                     using (PropertyValue pvTarget = new PropertyValue(target.Name))
344                     {
345                         if (strAlpha != null)
346                         {
347                             using (PropertyValue pvStrAlpha = new PropertyValue(strAlpha))
348                             {
349                                 animator.Add("alphaFunction", pvStrAlpha);
350                             }
351                         }
352
353                         timePeriod.Add("duration", pvDuration);
354                         timePeriod.Add("delay", pvDelay);
355                         using (PropertyValue pvTimePeriod = new PropertyValue(timePeriod))
356                         {
357                             animator.Add("timePeriod", pvTimePeriod);
358                         }
359
360                         StringBuilder sb = new StringBuilder(property);
361                         sb[0] = (char)(sb[0] | 0x20);
362                         string _str = sb.ToString();
363                         if (_str == "position") { _str = "offset"; }
364
365                         transition.Add("target", pvTarget);
366                         using (PropertyValue pvStr = new PropertyValue(_str))
367                         {
368                             transition.Add("property", pvStr);
369                         }
370
371                         if (initialValue != null)
372                         {
373                             using (PropertyValue initVal = PropertyValue.CreateFromObject(initialValue))
374                             using (PropertyValue pvInitialValue = new PropertyValue(initVal))
375                             {
376                                 transition.Add("initialValue", pvInitialValue);
377                             }
378                         }
379                         transition.Add("targetValue", destVal);
380                         using (PropertyValue pvAnimator = new PropertyValue(animator))
381                         {
382                             transition.Add("animator", pvAnimator);
383                         }
384
385                         using (PropertyValue pvTransition = new PropertyValue(transition))
386                         {
387                             PropertyArray temp = animateArray.Add(pvTransition);
388                             temp.Dispose();
389                         }
390                     }
391                 }
392             }
393         }
394
395         /// <summary>
396         /// Finishes to add a visual animation (transition) map and creates a transition animation.
397         /// </summary>
398         /// <returns>Animation instance.</returns>
399         /// <since_tizen> 3 </since_tizen>
400         public Animation AnimateVisualAddFinish()
401         {
402             if (animateArray == null || animateArray.Empty())
403             {
404                 Tizen.Log.Fatal("NUI", "animate visual property array is empty!");
405                 return null;
406             }
407             TransitionData transitionData = new TransitionData(animateArray);
408             Animation ret = this.CreateTransition(transitionData);
409             transitionData.Dispose();
410             return ret;
411         }
412
413         /// <summary>
414         /// temporary fix to pass TCT.
415         /// </summary>
416         /// <exception cref="ArgumentNullException"> Thrown when visualMap is null. </exception>
417         /// <since_tizen> 3 </since_tizen>
418         public Animation VisualAnimate(Tizen.NUI.VisualAnimator visualMap)
419         {
420             if (visualMap == null)
421             {
422                 throw new ArgumentNullException(nameof(visualMap));
423             }
424
425             foreach (var item in visualDictionary.ToList())
426             {
427                 if (item.Value.Name == visualMap.Target)
428                 {
429                     using (TransitionData transitionData = new TransitionData(visualMap.OutputVisualMap))
430                     {
431                         return this.CreateTransition(transitionData);
432                     }
433                 }
434             }
435             return null;
436         }
437         //temporary fix to pass TCT
438
439         internal void UpdateVisual(int visualIndex, string visualName, VisualMap visualMap)
440         {
441             VisualBase visual = null;
442
443             visual = VisualFactory.Instance.CreateVisual(visualMap.OutputVisualMap);
444             visual.Name = visualName;
445             visual.DepthIndex = visualMap.DepthIndex;
446
447             RegisterVisual(visualIndex, visual);
448
449             visualDictionary[visualIndex] = visual;
450             tranformDictionary[visualIndex] = visualMap.OutputTransformMap;
451
452             RelayoutRequest();
453             NUILog.Debug("UpdateVisual() name=" + visualName);
454         }
455
456         static CustomView CreateInstance()
457         {
458             return new VisualView();
459         }
460
461     }
462 }