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(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) },
48 static PropertyHelper() { }
51 /// Returns a Property if stringProperty is a valid index
53 internal static Property GetPropertyFromString(Animatable handle, string stringProperty)
55 Property property = new Property(handle, LowerFirstLetter(stringProperty));
56 if (property.propertyIndex == Property.InvalidIndex)
58 throw new System.ArgumentException("string property is invalid");
65 /// Returns a Property if stringProperty is a valid index
67 internal static SearchResult Search(View view, string stringProperty)
69 var propertyName = LowerFirstLetter(stringProperty);
71 return SearchProperty(view, propertyName) ?? SearchVisualProperty(view, propertyName);
74 private static SearchResult SearchProperty(View view, string lowercasePropertyString)
76 Property property = new Property(view, lowercasePropertyString);
78 if (property.propertyIndex == Property.InvalidIndex)
84 OOConverter converter = null;
85 if (view.GetPropertyType(property.propertyIndex).Equals(PropertyType.Float))
87 converter = ObjectIntToFloat;
90 return new SearchResult(property, converter);
93 private static SearchResult SearchVisualProperty(View view, string lowercasePropertyString)
95 if (visualPropertyTable.TryGetValue(lowercasePropertyString, out var found))
97 return GenerateVisualPropertySearchResult(view, found);
103 private static SearchResult GenerateVisualPropertySearchResult(View view, VisualPropertyData data)
105 var propertyIntPtr = Interop.View.GetVisualProperty(view.SwigCPtr, data.ViewPropertyIndex, data.VisualPropertyIndex);
106 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
108 var property = new Property(propertyIntPtr, true);
109 if (property.propertyIndex == Property.InvalidIndex)
115 SearchResult result = new SearchResult(property, data.ObjectConverter, data.PropertyValueConverter);
117 while (data.RelatedData != null)
119 result.NextResult = GenerateVisualPropertySearchResult(view, data.RelatedData);
120 data = data.RelatedData;
126 private static string LowerFirstLetter(string original)
128 StringBuilder sb = new StringBuilder(original);
129 sb[0] = (char)(sb[0] | 0x20);
130 return sb.ToString();
133 private static object ObjectColorToVector3(object value)
135 if (value is Vector4)
137 var colorValue = value as Vector4;
138 return new Vector3(colorValue.R, colorValue.G, colorValue.B);
143 var colorValue = value as Color;
144 return new Vector3(colorValue.R, colorValue.G, colorValue.B);
150 private static PropertyValue PropertyValueColorToVector3(PropertyValue value)
152 var valueType = value.GetType();
154 if (valueType != PropertyType.Vector4)
159 var colorValue = new Vector4();
160 value.Get(colorValue);
161 using (var v3 = new Vector3(colorValue.R, colorValue.G, colorValue.B))
163 colorValue.Dispose();
164 return new PropertyValue(v3);
168 private static object ObjectColorToAlpha(object value)
170 if (value is Vector4)
172 var colorValue = value as Vector4;
178 var colorValue = value as Color;
185 private static PropertyValue PropertyValueColorToAlpha(PropertyValue value)
187 var valueType = value.GetType();
189 if (valueType != PropertyType.Vector4)
194 using (var colorValue = new Vector4())
196 value.Get(colorValue);
197 return new PropertyValue(colorValue.A);
201 private static object ObjectIntToFloat(object value)
203 Type type = value.GetType();
204 if (type.Equals(typeof(System.Int32)) || type.Equals(typeof(int)))
206 return (float)((int)value);
212 private static object ObjectVector4ToFloat(object value)
214 if (value is Vector4 vector)
222 internal class SearchResult : Disposable
224 private readonly OOConverter objectConverter;
225 private readonly PPConverter propertyValueConverter;
227 internal SearchResult(Property property, OOConverter objectConverter = null, PPConverter propertyValueConverter = null)
229 this.objectConverter = objectConverter;
230 this.propertyValueConverter = propertyValueConverter;
234 internal Property Property { get; }
236 internal SearchResult NextResult { get; set; }
238 internal PropertyValue RefineValue(object value)
240 Debug.Assert(Property != null && value != null);
244 if (objectConverter != null)
246 refined = objectConverter(value);
254 return PropertyValue.CreateFromObject(refined);
257 internal KeyFrames RefineKeyFrames(KeyFrames keyFrames)
259 Debug.Assert(keyFrames != null);
261 var refined = keyFrames;
262 if (propertyValueConverter != null)
264 // TODO Enable this code when csharp-binder is ready
265 // refined = new KeyFrames();
266 // for (uint i = 0; i < keyFrames.Count; i++)
268 // var keyFrame = keyFrames.GetKeyFrame(i);
269 // var newKeyFrame = propertyValueConverter(keyFrame);
270 // if (newKeyFrame == null)
274 // refined.Add(newKeyFrame);
284 protected override void Dispose(DisposeTypes type)
291 if (type == DisposeTypes.Explicit)
294 NextResult?.Dispose();
301 private class VisualPropertyData
303 internal VisualPropertyData(int viewPropertyIndex, int visualPropertyIndex, OOConverter objectConverter = null, PPConverter propertyValueConverter = null, VisualPropertyData relatedData = null)
305 ViewPropertyIndex = viewPropertyIndex;
306 VisualPropertyIndex = visualPropertyIndex;
307 ObjectConverter = objectConverter;
308 PropertyValueConverter = propertyValueConverter;
309 RelatedData = relatedData;
312 internal int ViewPropertyIndex { get; }
314 internal int VisualPropertyIndex { get; }
316 internal OOConverter ObjectConverter { get; }
318 internal PPConverter PropertyValueConverter { get; }
320 internal VisualPropertyData RelatedData { get; }