From 3e04b5807883f1007b391c3ab5c73a79ba3957f6 Mon Sep 17 00:00:00 2001 From: Jiyun Yang Date: Tue, 24 Dec 2019 16:59:12 +0900 Subject: [PATCH 1/1] [NUI] Implement shadow in View (#1223) Signed-off-by: Jiyun Yang --- .../src/internal/Interop/Interop.PropertyMap.cs | 6 + .../src/internal/Interop/Interop.ViewProperty.cs | 3 + src/Tizen.NUI/src/public/BaseComponents/View.cs | 50 ++++++ .../public/BaseComponents/ViewBindableProperty.cs | 33 ++++ .../src/public/BaseComponents/ViewEnum.cs | 1 + .../src/public/BaseComponents/ViewEvent.cs | 10 ++ src/Tizen.NUI/src/public/PropertyMap.cs | 20 +++ src/Tizen.NUI/src/public/PropertyValue.cs | 24 +++ src/Tizen.NUI/src/public/Rectangle.cs | 5 + src/Tizen.NUI/src/public/Size.cs | 4 + src/Tizen.NUI/src/public/Vector2.cs | 5 + .../src/public/ViewProperty/ImageShadow.cs | 120 ++++++++++++++ src/Tizen.NUI/src/public/ViewProperty/Shadow.cs | 136 ++++++++++++++++ .../ViewProperty/TransformablePropertyMap.cs | 181 +++++++++++++++++++++ 14 files changed, 598 insertions(+) create mode 100644 src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs create mode 100644 src/Tizen.NUI/src/public/ViewProperty/Shadow.cs create mode 100644 src/Tizen.NUI/src/public/ViewProperty/TransformablePropertyMap.cs diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.PropertyMap.cs b/src/Tizen.NUI/src/internal/Interop/Interop.PropertyMap.cs index de02849..f4d4824 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.PropertyMap.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.PropertyMap.cs @@ -76,6 +76,12 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Property_Map_Assign")] public static extern global::System.IntPtr Property_Map_Assign(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Property_Map_SetValue_StringKey")] + public static extern void Property_Map_SetValue_StringKey(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Property_Map_SetValue_IntKey")] + public static extern void Property_Map_SetValue_IntKey(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, global::System.Runtime.InteropServices.HandleRef jarg3); } } } \ No newline at end of file diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.ViewProperty.cs b/src/Tizen.NUI/src/internal/Interop/Interop.ViewProperty.cs index 5d8205d..e52a6a5 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.ViewProperty.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.ViewProperty.cs @@ -52,6 +52,9 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_View_Property_UPDATE_SIZE_HINT_get")] public static extern int View_Property_UPDATE_SIZE_HINT_get(); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_View_Property_SHADOW_get")] + public static extern int View_Property_SHADOW_get(); } } } \ No newline at end of file diff --git a/src/Tizen.NUI/src/public/BaseComponents/View.cs b/src/Tizen.NUI/src/public/BaseComponents/View.cs index 71ba247..62641ab 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/View.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/View.cs @@ -59,6 +59,10 @@ namespace Tizen.NUI.BaseComponents private string[] transitionNames; private Rectangle backgroundImageBorder; + private ImageShadow imageShadow; + + private Shadow boxShadow; + internal Size2D sizeSetExplicitly = new Size2D(); // Store size set by API, will be used in place of NaturalSize if not set. private ViewStyle viewStyle; @@ -295,6 +299,52 @@ namespace Tizen.NUI.BaseComponents } /// + /// Describes a shadow as an image for View. + /// It is null by default. + /// + /// + /// The mutually exclusive with "BoxShadow". + /// If it is not null, the "BoxShadow" property will be ignored. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public ImageShadow ImageShadow + { + get + { + return (ImageShadow)GetValue(ImageShadowProperty); + } + set + { + value.OnPropertyChanged = OnImageShadowChanged; + SetValue(ImageShadowProperty, value); + NotifyPropertyChanged(); + } + } + + /// + /// Describes a box shaped shadow drawing for View. + /// It is null by default. + /// + /// + /// The mutually exclusive with "ImageShadow". + /// If the "ImageShadow" is not null, this property will be ignored. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public Shadow BoxShadow + { + get + { + return (Shadow)GetValue(BoxShadowProperty); + } + set + { + value.OnPropertyChanged = OnBoxShadowChanged; + SetValue(BoxShadowProperty, value); + NotifyPropertyChanged(); + } + } + + /// /// The current state of the view. /// /// 3 diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs index 55cc478..616e7b6 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs @@ -1349,6 +1349,39 @@ namespace Tizen.NUI.BaseComponents }); /// + /// ImageShadow Property + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static readonly BindableProperty ImageShadowProperty = BindableProperty.Create("ImageShadow", typeof(ImageShadow), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) => + { + var view = (View)bindable; + view.imageShadow = (ImageShadow)newValue; + Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), ImageShadow.ToPropertyValue(view.imageShadow)); + }, + defaultValueCreator: (bindable) => + { + return ((View)bindable).imageShadow; + }); + + /// + /// Shadow Property + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static readonly BindableProperty BoxShadowProperty = BindableProperty.Create("BoxShadow", typeof(Shadow), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) => + { + var view = (View)bindable; + view.boxShadow = (Shadow)newValue; + if (view.imageShadow == null) + { + Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), Shadow.ToPropertyValue(view.boxShadow)); + } + }, + defaultValueCreator: (bindable) => + { + return ((View)bindable).boxShadow; + }); + + /// /// XamlStyleProperty /// [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewEnum.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewEnum.cs index 90c996f..5360849 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewEnum.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewEnum.cs @@ -205,6 +205,7 @@ namespace Tizen.NUI.BaseComponents internal static readonly int LAYOUT_DIRECTION = Interop.ActorProperty.Actor_Property_LAYOUT_DIRECTION_get(); internal static readonly int MARGIN = Interop.ViewProperty.View_Property_MARGIN_get(); internal static readonly int PADDING = Interop.ViewProperty.View_Property_PADDING_get(); + internal static readonly int SHADOW = Interop.ViewProperty.View_Property_SHADOW_get(); } } } diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs index 4c40811..d44e3d0 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs @@ -604,6 +604,16 @@ namespace Tizen.NUI.BaseComponents PivotPoint = new Position(x, y, z); } + private void OnImageShadowChanged(TransformablePropertyMap instance) + { + ImageShadow = (ImageShadow)instance; + } + + private void OnBoxShadowChanged(TransformablePropertyMap instance) + { + BoxShadow = (Shadow)instance; + } + private void OnKeyInputFocusGained(IntPtr view) { if (_keyInputFocusGainedEventHandler != null) diff --git a/src/Tizen.NUI/src/public/PropertyMap.cs b/src/Tizen.NUI/src/public/PropertyMap.cs index 42d6f85..6b469bd 100755 --- a/src/Tizen.NUI/src/public/PropertyMap.cs +++ b/src/Tizen.NUI/src/public/PropertyMap.cs @@ -61,6 +61,10 @@ namespace Tizen.NUI { return ValueOfIndex(key); } + internal set + { + SetValue(key, value); + } } /// @@ -76,6 +80,10 @@ namespace Tizen.NUI { return ValueOfIndex(key); } + internal set + { + SetValue(key, value); + } } /// @@ -286,6 +294,18 @@ namespace Tizen.NUI return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; } + internal void SetValue(int key, PropertyValue value) + { + Interop.PropertyMap.Property_Map_SetValue_IntKey(swigCPtr, key, PropertyValue.getCPtr(value)); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + + internal void SetValue(string key, PropertyValue value) + { + Interop.PropertyMap.Property_Map_SetValue_StringKey(swigCPtr, key, PropertyValue.getCPtr(value)); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + /// This will not be public opened. [EditorBrowsable(EditorBrowsableState.Never)] protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr) diff --git a/src/Tizen.NUI/src/public/PropertyValue.cs b/src/Tizen.NUI/src/public/PropertyValue.cs index f48389a..b0ea75d 100755 --- a/src/Tizen.NUI/src/public/PropertyValue.cs +++ b/src/Tizen.NUI/src/public/PropertyValue.cs @@ -331,6 +331,10 @@ namespace Tizen.NUI { value = new PropertyValue((Extents)obj); } + else if (type.Equals(typeof(Rectangle))) + { + value = new PropertyValue((Rectangle)obj); + } else { throw new global::System.InvalidOperationException("Unimplemented type for Property Value :" + type.Name); @@ -645,5 +649,25 @@ namespace Tizen.NUI { Interop.PropertyValue.delete_Property_Value(swigCPtr); } + + internal static PropertyValue CreateWithGuard(string value) + { + return value == null ? new PropertyValue() : new PropertyValue(value); + } + + internal static PropertyValue CreateWithGuard(Vector2 value) + { + return value == null ? new PropertyValue() : new PropertyValue(value); + } + + internal static PropertyValue CreateWithGuard(Rectangle value) + { + return value == null ? new PropertyValue() : new PropertyValue(value); + } + + internal static PropertyValue CreateWithGuard(Color value) + { + return value == null ? new PropertyValue() : new PropertyValue(value); + } } } diff --git a/src/Tizen.NUI/src/public/Rectangle.cs b/src/Tizen.NUI/src/public/Rectangle.cs index cae40b3..903990e 100755 --- a/src/Tizen.NUI/src/public/Rectangle.cs +++ b/src/Tizen.NUI/src/public/Rectangle.cs @@ -57,6 +57,11 @@ namespace Tizen.NUI callback = cb; if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } + + internal Rectangle(RectangleChangedCallback cb, Rectangle other) : this(cb, other.x, other.y, other.width, other.height) + { + } + internal delegate void RectangleChangedCallback(int x, int y, int width, int height); private RectangleChangedCallback callback = null; diff --git a/src/Tizen.NUI/src/public/Size.cs b/src/Tizen.NUI/src/public/Size.cs index ce50f96..b2ca5c6 100755 --- a/src/Tizen.NUI/src/public/Size.cs +++ b/src/Tizen.NUI/src/public/Size.cs @@ -425,6 +425,10 @@ namespace Tizen.NUI if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } + internal Size(SizeChangedCallback cb, Size other) : this(cb, other.Width, other.Height, other.Depth) + { + } + private SizeChangedCallback callback = null; } } diff --git a/src/Tizen.NUI/src/public/Vector2.cs b/src/Tizen.NUI/src/public/Vector2.cs index ed895b1..27c75cb 100755 --- a/src/Tizen.NUI/src/public/Vector2.cs +++ b/src/Tizen.NUI/src/public/Vector2.cs @@ -87,6 +87,11 @@ namespace Tizen.NUI callback = cb; if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } + + internal Vector2(Vector2ChangedCallback cb, Vector2 other) : this(cb, other.X, other.Y) + { + } + internal delegate void Vector2ChangedCallback(float x, float y); private Vector2ChangedCallback callback = null; diff --git a/src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs b/src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs new file mode 100644 index 0000000..21edf54 --- /dev/null +++ b/src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs @@ -0,0 +1,120 @@ +/* + * Copyright(c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + using System.ComponentModel; + +namespace Tizen.NUI +{ + + /// + /// The Shadow composed of image for View + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public class ImageShadow : TransformablePropertyMap + { + private string url; + + private Rectangle border; + + /// + /// Constructor + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public ImageShadow() : base() + { + } + + private void OnBorderChanged(int x, int y, int width, int height) + { + UpdateBorder(); + } + + private void UpdateUrl() + { + propertyMap[ImageVisualProperty.URL] = PropertyValue.CreateWithGuard(url); + OnPropertyChanged?.Invoke(this); + } + + private void UpdateBorder() + { + propertyMap[ImageVisualProperty.Border] = PropertyValue.CreateWithGuard(border); + OnPropertyChanged?.Invoke(this); + } + + /// + /// The url for the shadow image to load. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public string Url + { + get + { + return url; + } + set + { + url = value; + UpdateUrl(); + } + } + + /// + /// Optional.
+ /// The border area of the n-patch image. + /// Set left, right, bottom, top length of the border you don't want to stretch in the image. + ///
+ [EditorBrowsable(EditorBrowsableState.Never)] + public Rectangle Border + { + get + { + return border; + } + set + { + border = value == null? null : new Rectangle(OnBorderChanged, value); + UpdateBorder(); + } + } + + override internal string ToDebugString() + { + string result = ""; + // TODO + return result; + } + + override internal bool IsValid() + { + return url != null; + } + + static internal new PropertyValue ToPropertyValue(TransformablePropertyMap instance) + { + if (instance == null || !instance.IsValid()) + { + return new PropertyValue(); + } + + instance.propertyMap.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.NPatch)); + + return new PropertyValue(instance.propertyMap); + } + } +} + + diff --git a/src/Tizen.NUI/src/public/ViewProperty/Shadow.cs b/src/Tizen.NUI/src/public/ViewProperty/Shadow.cs new file mode 100644 index 0000000..44ee106 --- /dev/null +++ b/src/Tizen.NUI/src/public/ViewProperty/Shadow.cs @@ -0,0 +1,136 @@ +/* + * Copyright(c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + using System.ComponentModel; + +namespace Tizen.NUI +{ + + /// + /// The platform provided shadow drawing for View + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public class Shadow : TransformablePropertyMap + { + private static readonly Color noColor = new Color(0, 0, 0, 0); + + private static readonly Color defaultColor = new Color(0, 0, 0, 0.5f); + + private Color color; + + private uint blurRadius; + + /// + /// Constructor + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public Shadow() : base() + { + Color = defaultColor; + } + + /// + /// The boolean conversion + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static implicit operator Shadow(bool value) + { + Shadow shadow = new Shadow() + { + Color = value ? defaultColor : noColor, + }; + return shadow; + } + + private void OnColorChanged(float r, float g, float b, float a) + { + UpdateColor(); + } + + private void UpdateColor() + { + propertyMap[ColorVisualProperty.MixColor] = PropertyValue.CreateWithGuard(color); + OnPropertyChanged?.Invoke(this); + } + + private void UpdateBlurRadius() + { + // TODO update blur radius value in the property map + OnPropertyChanged?.Invoke(this); + } + + /// + /// The color for the shadow. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public Color Color + { + get + { + return color; + } + set + { + color = value; + UpdateColor(); + } + } + + /// + /// The blur radius value for the shadow. Bigger value, much blurry. + /// + private uint BlurRadius + { + get + { + return blurRadius; + } + set + { + blurRadius = value; + UpdateBlurRadius(); + } + } + + override internal string ToDebugString() + { + string result = ""; + // TODO + return result; + } + + override internal bool IsValid() + { + return color != null && color.A != 0; + } + + static internal new PropertyValue ToPropertyValue(TransformablePropertyMap instance) + { + if (instance == null || !instance.IsValid()) + { + return new PropertyValue(); + } + + // TODO to be other blurable visual in the future + instance.propertyMap.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Color)); + + return new PropertyValue(instance.propertyMap); + } + } +} + + diff --git a/src/Tizen.NUI/src/public/ViewProperty/TransformablePropertyMap.cs b/src/Tizen.NUI/src/public/ViewProperty/TransformablePropertyMap.cs new file mode 100644 index 0000000..d2d2927 --- /dev/null +++ b/src/Tizen.NUI/src/public/ViewProperty/TransformablePropertyMap.cs @@ -0,0 +1,181 @@ +/* + * Copyright(c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + using System.ComponentModel; + +namespace Tizen.NUI +{ + + /// + /// The property map class that has transform property for one of its items. + /// This class can be used to convert visual properties to map. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + abstract public class TransformablePropertyMap + { + internal delegate void PropertyChangedCallback(TransformablePropertyMap instance); + + internal PropertyChangedCallback OnPropertyChanged = null; + + private static readonly Vector2 noOffset = new Vector2(0, 0); + + private static readonly Vector2 noScale = new Vector2(1, 1); + + private static readonly Vector2 defaultOffset = new Vector2(0, 0); + + private static readonly Vector2 defaultOffsetPolicy = new Vector2((int)VisualTransformPolicyType.Absolute, (int)VisualTransformPolicyType.Absolute); + + + /// + /// The offset value that tansform should have in common + /// + protected internal Vector2 offset = defaultOffset; + + /// + /// The size value in scale that tansform should have in common + /// + protected internal Vector2 scale = noScale; + + /// + /// The output property map + /// + protected internal PropertyMap propertyMap; + + /// + /// The transform property map + /// + protected internal PropertyMap transformMap; + + /// + /// Constructor + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public TransformablePropertyMap() + { + // Initialize maps + propertyMap = new PropertyMap(); + transformMap = new PropertyMap(); + + // Offet has default value, so need to update map + transformMap[(int)VisualTransformPropertyType.OffsetPolicy] = new PropertyValue(defaultOffsetPolicy); + transformMap[(int)VisualTransformPropertyType.Offset] = PropertyValue.CreateWithGuard(offset); + propertyMap[Visual.Property.Transform] = new PropertyValue(transformMap); + } + + private void OnOffsetChanged(float x, float y) + { + UpdateOffset(); + } + + private void OnScaleChanged(float widht, float height) + { + UpdateScale(); + } + + private void UpdateOffset() + { + if (!ClearTransformMapIfNeeds()) + { + transformMap[(int)VisualTransformPropertyType.Offset] = PropertyValue.CreateWithGuard(offset); + propertyMap[Visual.Property.Transform] = new PropertyValue(transformMap); + } + OnPropertyChanged?.Invoke(this); + } + + private void UpdateScale() + { + if (!ClearTransformMapIfNeeds()) + { + transformMap[(int)VisualTransformPropertyType.Size] = PropertyValue.CreateWithGuard(scale); + propertyMap[Visual.Property.Transform] = new PropertyValue(transformMap); + } + OnPropertyChanged?.Invoke(this); + } + + /// + /// Indicates whether the transform map is needed or not. + /// This checks offset and scale values are valid. + /// It can be overwritten in the derived class. + /// + virtual protected internal bool NeedTransformMap() + { + return (offset != null && !offset.Equals(noOffset)) || (scale != null && !scale.Equals(noScale)); + } + + /// + /// If this map does not need to have transform property(= no offset and no size), + /// clear existing transform map and return true. + /// Return false when it needs to transform. + /// + protected internal bool ClearTransformMapIfNeeds() + { + if (!NeedTransformMap()) + { + transformMap.Clear(); + transformMap[(int)VisualTransformPropertyType.OffsetPolicy] = new PropertyValue(defaultOffsetPolicy); + propertyMap[Visual.Property.Transform] = new PropertyValue(); + return true; + } + return false; + } + + /// + /// The position offset value (x, y) from the top left corner. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public Vector2 Offset + { + get + { + return offset; + } + set + { + offset = value == null? null : new Vector2(OnOffsetChanged, value); + UpdateOffset(); + } + } + + /// + /// The value indicates percentage of the container size.
+ /// e.g. (0.5f, 1.0f) means 50% of the container's width and 100% of container's height. + ///
+ public Vector2 Scale + { + get + { + return scale; + } + set + { + scale = value == null? null : new Vector2(OnScaleChanged, value); + UpdateScale(); + } + } + + abstract internal string ToDebugString(); + + abstract internal bool IsValid(); + + static internal PropertyValue ToPropertyValue(TransformablePropertyMap instance) + { + return (instance != null && instance.IsValid()) ? new PropertyValue(instance.propertyMap) : new PropertyValue(); + } + } +} + + -- 2.7.4