2 * Copyright(c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 using System.Collections.Generic;
20 using System.Diagnostics;
22 using Tizen.NUI.BaseComponents;
26 using OOConverter = Converter<object, object>;
27 using PPConverter = Converter<PropertyValue, PropertyValue>;
29 internal static class PropertyHelper
31 private static readonly Dictionary<string, VisualPropertyData> visualPropertyTable = new Dictionary<string, VisualPropertyData>()
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(ImageView.Property.IMAGE, Visual.Property.CornerRadius, null, null,
43 new VisualPropertyData(View.Property.SHADOW, Visual.Property.CornerRadius, null, null,
44 new VisualPropertyData(View.Property.BACKGROUND, Visual.Property.CornerRadius, null, null))) },
45 { "borderlineWidth", new VisualPropertyData(ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, ObjectIntToFloat, null,
46 new VisualPropertyData(View.Property.BACKGROUND, Visual.Property.BorderlineWidth, ObjectIntToFloat, null)) },
47 { "borderlineColor", new VisualPropertyData(ImageView.Property.IMAGE, Visual.Property.BorderlineColor, null, null,
48 new VisualPropertyData(View.Property.BACKGROUND, Visual.Property.BorderlineColor, null, null)) },
49 { "borderlineOffset", new VisualPropertyData(ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, null, null,
50 new VisualPropertyData(View.Property.BACKGROUND, Visual.Property.BorderlineOffset, null, null)) },
51 { "imageShadow.Offset", new VisualPropertyData(View.Property.SHADOW, (int)VisualTransformPropertyType.Offset) },
52 { "shadow.CornerRadius", new VisualPropertyData(View.Property.SHADOW, Visual.Property.CornerRadius, ObjectIntToFloat) },
55 static PropertyHelper() { }
58 /// Returns a Property if stringProperty is a valid index
60 internal static Property GetPropertyFromString(Animatable handle, string stringProperty)
62 Property property = new Property(handle, LowerFirstLetter(stringProperty));
63 if (property.propertyIndex == Property.InvalidIndex)
65 throw new System.ArgumentException("string property is invalid");
72 /// Returns a Property if stringProperty is a valid index
74 internal static SearchResult Search(Animatable animatable, string stringProperty)
76 var propertyName = LowerFirstLetter(stringProperty);
78 if(animatable is View)
80 View view = animatable as View;
81 return SearchProperty(view, propertyName) ?? SearchVisualProperty(view, propertyName);
83 return SearchProperty(animatable, propertyName);
86 private static SearchResult SearchProperty(Animatable animatable, string lowercasePropertyString)
88 Property property = new Property(animatable, lowercasePropertyString);
90 if (property.propertyIndex == Property.InvalidIndex)
96 OOConverter converter = null;
97 if (animatable.GetPropertyType(property.propertyIndex).Equals(PropertyType.Float))
99 converter = ObjectIntToFloat;
102 return new SearchResult(property, converter);
105 private static SearchResult SearchVisualProperty(View view, string lowercasePropertyString)
107 if (visualPropertyTable.TryGetValue(lowercasePropertyString, out var found))
109 return GenerateVisualPropertySearchResult(view, found);
115 private static SearchResult GenerateVisualPropertySearchResult(View view, VisualPropertyData data)
117 var propertyIntPtr = Interop.View.GetVisualProperty(view.SwigCPtr, data.ViewPropertyIndex, data.VisualPropertyIndex);
118 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
120 var property = new Property(propertyIntPtr, true);
121 if (property.propertyIndex == Property.InvalidIndex)
124 return data.RelatedData == null ? null : GenerateVisualPropertySearchResult(view, data.RelatedData);
127 SearchResult result = new SearchResult(property, data.ObjectConverter, data.PropertyValueConverter);
129 if (data.RelatedData != null)
131 result.NextResult = GenerateVisualPropertySearchResult(view, data.RelatedData);
137 private static string LowerFirstLetter(string original)
139 StringBuilder sb = new StringBuilder(original);
140 sb[0] = (char)(sb[0] | 0x20);
141 return sb.ToString();
144 private static object ObjectColorToVector3(object value)
146 if (value is Vector4)
148 var colorValue = value as Vector4;
149 return new Vector3(colorValue.R, colorValue.G, colorValue.B);
154 var colorValue = value as Color;
155 return new Vector3(colorValue.R, colorValue.G, colorValue.B);
161 private static PropertyValue PropertyValueColorToVector3(PropertyValue value)
163 var valueType = value.GetType();
165 if (valueType != PropertyType.Vector4)
170 var colorValue = new Vector4();
171 value.Get(colorValue);
172 using (var v3 = new Vector3(colorValue.R, colorValue.G, colorValue.B))
174 colorValue.Dispose();
175 return new PropertyValue(v3);
179 private static object ObjectColorToAlpha(object value)
181 if (value is Vector4)
183 var colorValue = value as Vector4;
189 var colorValue = value as Color;
196 private static PropertyValue PropertyValueColorToAlpha(PropertyValue value)
198 var valueType = value.GetType();
200 if (valueType != PropertyType.Vector4)
205 using (var colorValue = new Vector4())
207 value.Get(colorValue);
208 return new PropertyValue(colorValue.A);
212 private static object ObjectIntToFloat(object value)
214 Type type = value.GetType();
215 if (type.Equals(typeof(System.Int32)) || type.Equals(typeof(int)))
217 return (float)((int)value);
223 private static object ObjectVector4ToFloat(object value)
225 if (value is Vector4 vector)
233 internal class SearchResult : Disposable
235 private readonly OOConverter objectConverter;
236 private readonly PPConverter propertyValueConverter;
238 internal SearchResult(Property property, OOConverter objectConverter = null, PPConverter propertyValueConverter = null)
240 this.objectConverter = objectConverter;
241 this.propertyValueConverter = propertyValueConverter;
245 internal Property Property { get; }
247 internal SearchResult NextResult { get; set; }
249 internal PropertyValue RefineValue(object value)
251 Debug.Assert(Property != null && value != null);
255 if (objectConverter != null)
257 refined = objectConverter(value);
265 return PropertyValue.CreateFromObject(refined);
269 // Refine object as IntPtr of PropertyValue to optimize.
270 // Warning : This API don't automatically release memory.
271 internal global::System.IntPtr RefineValueIntPtr(object value)
273 Debug.Assert(Property != null && value != null);
277 if (objectConverter != null)
279 refined = objectConverter(value);
284 return global::System.IntPtr.Zero;
287 return PropertyValue.CreateFromObjectIntPtr(refined);
290 internal KeyFrames RefineKeyFrames(KeyFrames keyFrames)
292 Debug.Assert(keyFrames != null);
294 var refined = keyFrames;
295 if (propertyValueConverter != null)
297 // TODO Enable this code when csharp-binder is ready
298 // refined = new KeyFrames();
299 // for (uint i = 0; i < keyFrames.Count; i++)
301 // var keyFrame = keyFrames.GetKeyFrame(i);
302 // var newKeyFrame = propertyValueConverter(keyFrame);
303 // if (newKeyFrame == null)
307 // refined.Add(newKeyFrame);
317 protected override void Dispose(DisposeTypes type)
324 if (type == DisposeTypes.Explicit)
327 NextResult?.Dispose();
334 private class VisualPropertyData
336 internal VisualPropertyData(int viewPropertyIndex, int visualPropertyIndex, OOConverter objectConverter = null, PPConverter propertyValueConverter = null, VisualPropertyData relatedData = null)
338 ViewPropertyIndex = viewPropertyIndex;
339 VisualPropertyIndex = visualPropertyIndex;
340 ObjectConverter = objectConverter;
341 PropertyValueConverter = propertyValueConverter;
342 RelatedData = relatedData;
345 internal int ViewPropertyIndex { get; }
347 internal int VisualPropertyIndex { get; }
349 internal OOConverter ObjectConverter { get; }
351 internal PPConverter PropertyValueConverter { get; }
353 internal VisualPropertyData RelatedData { get; }