a80664656263120b62bc6defd36c5ec41a162183
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / Common / PropertyHelper.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 System;
19 using System.Collections.Generic;
20 using System.Diagnostics;
21 using System.Text;
22 using Tizen.NUI.BaseComponents;
23
24 namespace Tizen.NUI
25 {
26     using OOConverter = Converter<object, object>;
27     using PPConverter = Converter<PropertyValue, PropertyValue>;
28
29     internal static class PropertyHelper
30     {
31         private static readonly Dictionary<string, VisualPropertyData> visualPropertyTable = new Dictionary<string, VisualPropertyData>()
32         {
33             { "backgroundColor",        new VisualPropertyData(View.Property.BACKGROUND, ColorVisualProperty.MixColor, ObjectColorToVector3, PropertyValueColorToVector3,
34                                         new VisualPropertyData(View.Property.BACKGROUND, Visual.Property.Opacity, ObjectColorToAlpha, PropertyValueColorToAlpha)) },
35             { "backgroundOpacity",      new VisualPropertyData(View.Property.BACKGROUND, Visual.Property.Opacity, ObjectIntToFloat) },
36             { "boxShadow.BlurRadius",   new VisualPropertyData(View.Property.SHADOW, ColorVisualProperty.BlurRadius) },
37             { "boxShadow.Color",        new VisualPropertyData(View.Property.SHADOW, ColorVisualProperty.MixColor, ObjectColorToVector3, PropertyValueColorToVector3,
38                                         new VisualPropertyData(View.Property.SHADOW, Visual.Property.Opacity, ObjectColorToAlpha, PropertyValueColorToAlpha)) },
39             { "boxShadow.CornerRadius", new VisualPropertyData(View.Property.SHADOW, Visual.Property.CornerRadius, ObjectIntToFloat) },
40             { "boxShadow.Offset",       new VisualPropertyData(View.Property.SHADOW, (int)VisualTransformPropertyType.Offset) },
41             { "boxShadow.Opacity",      new VisualPropertyData(View.Property.SHADOW, Visual.Property.Opacity, ObjectIntToFloat) },
42             { "cornerRadius",           new VisualPropertyData(View.Property.BACKGROUND, Visual.Property.CornerRadius, ObjectVector4ToFloat, null,
43                                         new VisualPropertyData(View.Property.SHADOW, Visual.Property.CornerRadius, ObjectVector4ToFloat)) },
44             { "imageShadow.Offset",     new VisualPropertyData(View.Property.SHADOW, (int)VisualTransformPropertyType.Offset) },
45             { "shadow.CornerRadius",    new VisualPropertyData(View.Property.SHADOW, Visual.Property.CornerRadius, ObjectIntToFloat) },
46         };
47
48         static PropertyHelper() { }
49
50         ///<summary>
51         /// Returns a Property if stringProperty is a valid index
52         ///</summary>
53         internal static Property GetPropertyFromString(Animatable handle, string stringProperty)
54         {
55             Property property = new Property(handle, LowerFirstLetter(stringProperty));
56             if (property.propertyIndex == Property.InvalidIndex)
57             {
58                 throw new System.ArgumentException("string property is invalid");
59             }
60
61             return property;
62         }
63
64         ///<summary>
65         /// Returns a Property if stringProperty is a valid index
66         ///</summary>
67         internal static SearchResult Search(View view, string stringProperty)
68         {
69             var propertyName = LowerFirstLetter(stringProperty);
70
71             return SearchProperty(view, propertyName) ?? SearchVisualProperty(view, propertyName);
72         }
73
74         private static SearchResult SearchProperty(View view, string lowercasePropertyString)
75         {
76             Property property = new Property(view, lowercasePropertyString);
77
78             if (property.propertyIndex == Property.InvalidIndex)
79             {
80                 property.Dispose();
81                 return null;
82             }
83
84             OOConverter converter = null;
85             if (view.GetPropertyType(property.propertyIndex).Equals(PropertyType.Float))
86             {
87                 converter = ObjectIntToFloat;
88             }
89
90             return new SearchResult(property, converter);
91         }
92
93         private static SearchResult SearchVisualProperty(View view, string lowercasePropertyString)
94         {
95             if (visualPropertyTable.TryGetValue(lowercasePropertyString, out var found))
96             {
97                 return GenerateVisualPropertySearchResult(view, found);
98             }
99
100             return null;
101         }
102
103         private static SearchResult GenerateVisualPropertySearchResult(View view, VisualPropertyData data)
104         {
105             var propertyIntPtr = Interop.View.GetVisualProperty(view.SwigCPtr, data.ViewPropertyIndex, data.VisualPropertyIndex);
106             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
107
108             var property = new Property(propertyIntPtr, true);
109             if (property.propertyIndex == Property.InvalidIndex)
110             {
111                 property.Dispose();
112                 return null;
113             }
114
115             SearchResult result = new SearchResult(property, data.ObjectConverter, data.PropertyValueConverter);
116
117             while (data.RelatedData != null)
118             {
119                 result.NextResult = GenerateVisualPropertySearchResult(view, data.RelatedData);
120                 data = data.RelatedData;
121             }
122
123             return result;
124         }
125
126         private static string LowerFirstLetter(string original)
127         {
128             StringBuilder sb = new StringBuilder(original);
129             sb[0] = (char)(sb[0] | 0x20);
130             return sb.ToString();
131         }
132
133         private static object ObjectColorToVector3(object value)
134         {
135             if (value is Vector4)
136             {
137                 var colorValue = value as Vector4;
138                 return new Vector3(colorValue.R, colorValue.G, colorValue.B);
139             }
140
141             if (value is Color)
142             {
143                 var colorValue = value as Color;
144                 return new Vector3(colorValue.R, colorValue.G, colorValue.B);
145             }
146
147             return null;
148         }
149
150         private static PropertyValue PropertyValueColorToVector3(PropertyValue value)
151         {
152             var valueType = value.GetType();
153
154             if (valueType != PropertyType.Vector4)
155             {
156                 return null;
157             }
158
159             var colorValue = new Vector4();
160             value.Get(colorValue);
161             using (var v3 = new Vector3(colorValue.R, colorValue.G, colorValue.B))
162             {
163                 colorValue.Dispose();
164                 return new PropertyValue(v3);
165             }
166         }
167
168         private static object ObjectColorToAlpha(object value)
169         {
170             if (value is Vector4)
171             {
172                 var colorValue = value as Vector4;
173                 return colorValue.A;
174             }
175
176             if (value is Color)
177             {
178                 var colorValue = value as Color;
179                 return colorValue.A;
180             }
181
182             return null;
183         }
184
185         private static PropertyValue PropertyValueColorToAlpha(PropertyValue value)
186         {
187             var valueType = value.GetType();
188
189             if (valueType != PropertyType.Vector4)
190             {
191                 return null;
192             }
193
194             using (var colorValue = new Vector4())
195             {
196                 value.Get(colorValue);
197                 return new PropertyValue(colorValue.A);
198             }
199         }
200
201         private static object ObjectIntToFloat(object value)
202         {
203             Type type = value.GetType();
204             if (type.Equals(typeof(System.Int32)) || type.Equals(typeof(int)))
205             {
206                 return (float)((int)value);
207             }
208
209             return value;
210         }
211
212         private static object ObjectVector4ToFloat(object value)
213         {
214             if (value is Vector4 vector)
215             {
216                 return vector.X;
217             }
218
219             return value;
220         }
221
222         internal class SearchResult : Disposable
223         {
224             private readonly OOConverter objectConverter;
225             private readonly PPConverter propertyValueConverter;
226
227             internal SearchResult(Property property, OOConverter objectConverter = null, PPConverter propertyValueConverter = null)
228             {
229                 this.objectConverter = objectConverter;
230                 this.propertyValueConverter = propertyValueConverter;
231                 Property = property;
232             }
233
234             internal Property Property { get; }
235
236             internal SearchResult NextResult { get; set; }
237
238             internal PropertyValue RefineValue(object value)
239             {
240                 Debug.Assert(Property != null && value != null);
241
242                 var refined = value;
243
244                 if (objectConverter != null)
245                 {
246                     refined = objectConverter(value);
247                 }
248
249                 if (refined == null)
250                 {
251                     return null;
252                 }
253
254                 return PropertyValue.CreateFromObject(refined);
255             }
256
257             internal KeyFrames RefineKeyFrames(KeyFrames keyFrames)
258             {
259                 Debug.Assert(keyFrames != null);
260
261                 var refined = keyFrames;
262                 if (propertyValueConverter != null)
263                 {
264                     // TODO Enable this code when csharp-binder is ready
265                     // refined = new KeyFrames();
266                     // for (uint i = 0; i < keyFrames.Count; i++)
267                     // {
268                     //     var keyFrame = keyFrames.GetKeyFrame(i);
269                     //     var newKeyFrame = propertyValueConverter(keyFrame);
270                     //     if (newKeyFrame == null)
271                     //     {
272                     //         return null;
273                     //     }
274                     //     refined.Add(newKeyFrame);
275                     // }
276                 }
277
278                 return refined;
279             }
280
281             /// <summary>
282             /// Dispose
283             /// </summary>
284             protected override void Dispose(DisposeTypes type)
285             {
286                 if (disposed)
287                 {
288                     return;
289                 }
290
291                 if (type == DisposeTypes.Explicit)
292                 {
293                     Property.Dispose();
294                     NextResult?.Dispose();
295                 }
296
297                 base.Dispose(type);
298             }
299         }
300
301         private class VisualPropertyData
302         {
303             internal VisualPropertyData(int viewPropertyIndex, int visualPropertyIndex, OOConverter objectConverter = null, PPConverter propertyValueConverter = null, VisualPropertyData relatedData = null)
304             {
305                 ViewPropertyIndex = viewPropertyIndex;
306                 VisualPropertyIndex = visualPropertyIndex;
307                 ObjectConverter = objectConverter;
308                 PropertyValueConverter = propertyValueConverter;
309                 RelatedData = relatedData;
310             }
311
312             internal int ViewPropertyIndex { get; }
313
314             internal int VisualPropertyIndex { get; }
315
316             internal OOConverter ObjectConverter { get; }
317
318             internal PPConverter PropertyValueConverter { get; }
319
320             internal VisualPropertyData RelatedData { get; }
321         }
322     }
323 }