[NUI] Add DisableBindableProperty and VoiceInteractionName as hidden APIs
authordongsug.song <dongsug.song@samsung.com>
Tue, 12 Mar 2024 09:22:14 +0000 (18:22 +0900)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Tue, 12 Mar 2024 09:39:02 +0000 (18:39 +0900)
src/Tizen.NUI/src/public/Application/NUIApplication.cs
src/Tizen.NUI/src/public/BaseComponents/View.cs
src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/DaliDemo/DaliDemo.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/DisableBindablePropertyTest.cs [new file with mode: 0755]

index eabcdef..eaa032c 100755 (executable)
@@ -660,6 +660,17 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// Set to true if BindableProperty is not used. 
+        /// This must be called immediately after the NUIApplication constructor is called.
+        /// The default value is false.        
+        /// </summary>
+        /// <remarks>
+        /// This must be called immediately after the NUIApplication constructor is called.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        static public bool DisableBindableProperty { get; set; } = false;
+
+        /// <summary>
         /// Check if it is loaded as dotnet-loader-nui.
         /// </summary>
         static internal bool IsPreload { get; set; }
index 3423ab0..2571eba 100755 (executable)
@@ -89,20 +89,23 @@ namespace Tizen.NUI.BaseComponents
 
         static View()
         {
-            RegisterPropertyGroup(PositionProperty, positionPropertyGroup);
-            RegisterPropertyGroup(Position2DProperty, positionPropertyGroup);
-            RegisterPropertyGroup(PositionXProperty, positionPropertyGroup);
-            RegisterPropertyGroup(PositionYProperty, positionPropertyGroup);
+            if (NUIApplication.DisableBindableProperty == false)
+            {
+                RegisterPropertyGroup(PositionProperty, positionPropertyGroup);
+                RegisterPropertyGroup(Position2DProperty, positionPropertyGroup);
+                RegisterPropertyGroup(PositionXProperty, positionPropertyGroup);
+                RegisterPropertyGroup(PositionYProperty, positionPropertyGroup);
 
-            RegisterPropertyGroup(SizeProperty, sizePropertyGroup);
-            RegisterPropertyGroup(Size2DProperty, sizePropertyGroup);
-            RegisterPropertyGroup(SizeWidthProperty, sizePropertyGroup);
-            RegisterPropertyGroup(SizeHeightProperty, sizePropertyGroup);
+                RegisterPropertyGroup(SizeProperty, sizePropertyGroup);
+                RegisterPropertyGroup(Size2DProperty, sizePropertyGroup);
+                RegisterPropertyGroup(SizeWidthProperty, sizePropertyGroup);
+                RegisterPropertyGroup(SizeHeightProperty, sizePropertyGroup);
 
-            RegisterPropertyGroup(ScaleProperty, scalePropertyGroup);
-            RegisterPropertyGroup(ScaleXProperty, scalePropertyGroup);
-            RegisterPropertyGroup(ScaleYProperty, scalePropertyGroup);
-            RegisterPropertyGroup(ScaleZProperty, scalePropertyGroup);
+                RegisterPropertyGroup(ScaleProperty, scalePropertyGroup);
+                RegisterPropertyGroup(ScaleXProperty, scalePropertyGroup);
+                RegisterPropertyGroup(ScaleYProperty, scalePropertyGroup);
+                RegisterPropertyGroup(ScaleZProperty, scalePropertyGroup);
+            }
 
             RegisterAccessibilityDelegate();
         }
@@ -145,14 +148,14 @@ namespace Tizen.NUI.BaseComponents
             switch (accessibilityMode)
             {
                 case ViewAccessibilityMode.Custom:
-                {
-                    return Interop.View.NewCustom();
-                }
+                    {
+                        return Interop.View.NewCustom();
+                    }
                 case ViewAccessibilityMode.Default:
                 default:
-                {
-                    return Interop.View.New();
-                }
+                    {
+                        return Interop.View.New();
+                    }
             }
         }
 
@@ -412,7 +415,7 @@ namespace Tizen.NUI.BaseComponents
                             }
 
                             if (child.ControlState != newControlState)
-                            child.ControlState = newControlState;
+                                child.ControlState = newControlState;
                         }
                     }
                 }
@@ -523,11 +526,25 @@ namespace Tizen.NUI.BaseComponents
         {
             get
             {
-                return (Color)GetValue(BackgroundColorProperty);
+                if (NUIApplication.DisableBindableProperty)
+                {
+                    return (Color)GetInternalBackgroundColorProperty(this);
+                }
+                else
+                {
+                    return (Color)GetValue(BackgroundColorProperty);
+                }
             }
             set
             {
-                SetValue(BackgroundColorProperty, value);
+                if (NUIApplication.DisableBindableProperty)
+                {
+                    SetInternalBackgroundColorProperty(this, null, value);
+                }
+                else
+                {
+                    SetValue(BackgroundColorProperty, value);
+                }
                 NotifyPropertyChanged();
             }
         }
@@ -1284,20 +1301,37 @@ namespace Tizen.NUI.BaseComponents
         {
             get
             {
-                var temp = (Size2D)GetValue(Size2DProperty);
-
-                if (this.Layout == null)
+                if (NUIApplication.DisableBindableProperty)
                 {
-                    if (temp.Width < 0) { temp.Width = 0; }
-                    if (temp.Height < 0) { temp.Height = 0; }
+                    var temp = (Size2D)GetInternalSize2DProperty(this);
+                    if (this.Layout == null)
+                    {
+                        if (temp.Width < 0) { temp.Width = 0; }
+                        if (temp.Height < 0) { temp.Height = 0; }
+                    }
+                    return temp;
+                }
+                else
+                {
+                    var temp = (Size2D)GetValue(Size2DProperty);
+                    if (this.Layout == null)
+                    {
+                        if (temp.Width < 0) { temp.Width = 0; }
+                        if (temp.Height < 0) { temp.Height = 0; }
+                    }
+                    return temp;
                 }
-
-                return temp;
             }
             set
             {
-                SetValue(Size2DProperty, value);
-
+                if (NUIApplication.DisableBindableProperty)
+                {
+                    SetInternalSize2DProperty(this, null, value);
+                }
+                else
+                {
+                    SetValue(Size2DProperty, value);
+                }
                 NotifyPropertyChanged();
             }
         }
@@ -1370,11 +1404,25 @@ namespace Tizen.NUI.BaseComponents
         {
             get
             {
-                return (Position2D)GetValue(Position2DProperty);
+                if (NUIApplication.DisableBindableProperty)
+                {
+                    return (Position2D)GetInternalPosition2DProperty(this);
+                }
+                else
+                {
+                    return (Position2D)GetValue(Position2DProperty);
+                }
             }
             set
             {
-                SetValue(Position2DProperty, value);
+                if (NUIApplication.DisableBindableProperty)
+                {
+                    SetInternalPosition2DProperty(this, null, value);
+                }
+                else
+                {
+                    SetValue(Position2DProperty, value);
+                }
                 NotifyPropertyChanged();
             }
         }
@@ -3512,5 +3560,20 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static int AliveCount => aliveCount;
 
+        /// <summary>
+        /// Voice interaction name for voice touch.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public string VoiceInteractionName
+        {
+            set
+            {
+                AutomationId = value;
+            }
+            get
+            {
+                return AutomationId;
+            }
+        }
     }
-}
+}
\ No newline at end of file
index 7b2ac1f..4242482 100755 (executable)
@@ -82,15 +82,16 @@ namespace Tizen.NUI.BaseComponents
             return Object.InternalGetPropertyBool(view.SwigCPtr, View.Property.KeyInputFocus);
         }));
 
-        /// <summary>
-        /// BackgroundColorProperty
-        /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(View), null,
-            propertyChanged: (bindable, oldValue, newValue) =>
-            {
-                var view = (View)bindable;
+        internal static void SetInternalBackgroundColorProperty(BindableObject bindable, object oldValue, object newValue)
+        {
+            var view = (View)bindable;
 
+            if (NUIApplication.DisableBindableProperty)
+            {
+                view.SetBackgroundColor((Color)newValue);
+            }
+            else
+            {
                 view.themeData?.selectorData?.ClearBackground(view);
 
                 if (newValue is Selector<Color> selector)
@@ -102,24 +103,34 @@ namespace Tizen.NUI.BaseComponents
                 {
                     view.SetBackgroundColor((Color)newValue);
                 }
-            },
-            defaultValueCreator: (bindable) =>
-            {
-                var view = (View)bindable;
+            }
+        }
 
-                if (view.internalBackgroundColor == null)
-                {
-                    view.internalBackgroundColor = new Color(view.OnBackgroundColorChanged, 0, 0, 0, 0);
-                }
+        internal static object GetInternalBackgroundColorProperty(BindableObject bindable)
+        {
+            var view = (View)bindable;
 
-                int visualType = (int)Visual.Type.Invalid;
-                Interop.View.InternalRetrievingVisualPropertyInt(view.SwigCPtr, Property.BACKGROUND, Visual.Property.Type, out visualType);
-                if (visualType == (int)Visual.Type.Color)
-                {
-                    Interop.View.InternalRetrievingVisualPropertyVector4(view.SwigCPtr, Property.BACKGROUND, ColorVisualProperty.MixColor, Color.getCPtr(view.internalBackgroundColor));
-                }
-                return view.internalBackgroundColor;
+            if (view.internalBackgroundColor == null)
+            {
+                view.internalBackgroundColor = new Color(view.OnBackgroundColorChanged, 0, 0, 0, 0);
+            }
+
+            int visualType = (int)Visual.Type.Invalid;
+            Interop.View.InternalRetrievingVisualPropertyInt(view.SwigCPtr, Property.BACKGROUND, Visual.Property.Type, out visualType);
+            if (visualType == (int)Visual.Type.Color)
+            {
+                Interop.View.InternalRetrievingVisualPropertyVector4(view.SwigCPtr, Property.BACKGROUND, ColorVisualProperty.MixColor, Color.getCPtr(view.internalBackgroundColor));
             }
+            return view.internalBackgroundColor;
+        }
+
+        /// <summary>
+        /// BackgroundColorProperty
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(View), null,
+            propertyChanged: SetInternalBackgroundColorProperty,
+            defaultValueCreator: GetInternalBackgroundColorProperty
         );
 
         /// <summary>
@@ -717,56 +728,60 @@ namespace Tizen.NUI.BaseComponents
             return view.IsFocusableInTouch();
         });
 
-        /// <summary>
-        /// Size2DProperty
-        /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty Size2DProperty = BindableProperty.Create(nameof(Size2D), typeof(Size2D), typeof(View), null,
-            propertyChanged: (bindable, oldValue, newValue) =>
+        internal static void SetInternalSize2DProperty(BindableObject bindable, object oldValue, object newValue)
+        {
+            var view = (View)bindable;
+            if (newValue != null)
             {
-                var view = (View)bindable;
-                if (newValue != null)
-                {
-                    // Size property setter is only used by user.
-                    // Framework code uses SetSize() instead of Size property setter.
-                    // Size set by user is returned by GetUserSize2D() for SuggestedMinimumWidth/Height.
-                    // SuggestedMinimumWidth/Height is used by Layout calculation.
-                    int width = ((Size2D)newValue).Width;
-                    int height = ((Size2D)newValue).Height;
-                    view.userSizeWidth = (float)width;
-                    view.userSizeHeight = (float)height;
-
-                    bool relayoutRequired = false;
-                    // To avoid duplicated size setup, change internal policy directly.
-                    if (view.widthPolicy != width)
-                    {
-                        view.widthPolicy = width;
-                        relayoutRequired = true;
-                    }
-                    if (view.heightPolicy != height)
-                    {
-                        view.heightPolicy = height;
-                        relayoutRequired = true;
-                    }
-                    if (relayoutRequired)
-                    {
-                        view.layout?.RequestLayout();
-                    }
+                // Size property setter is only used by user.
+                // Framework code uses SetSize() instead of Size property setter.
+                // Size set by user is returned by GetUserSize2D() for SuggestedMinimumWidth/Height.
+                // SuggestedMinimumWidth/Height is used by Layout calculation.
+                int width = ((Size2D)newValue).Width;
+                int height = ((Size2D)newValue).Height;
+                view.userSizeWidth = (float)width;
+                view.userSizeHeight = (float)height;
 
-                    Object.InternalSetPropertyVector2ActualVector3(view.SwigCPtr, View.Property.SIZE, ((Size2D)newValue).SwigCPtr);
+                bool relayoutRequired = false;
+                // To avoid duplicated size setup, change internal policy directly.
+                if (view.widthPolicy != width)
+                {
+                    view.widthPolicy = width;
+                    relayoutRequired = true;
                 }
-            },
-            defaultValueCreator: (bindable) =>
-            {
-                var view = (View)bindable;
-                if (view.internalSize2D == null)
+                if (view.heightPolicy != height)
+                {
+                    view.heightPolicy = height;
+                    relayoutRequired = true;
+                }
+                if (relayoutRequired)
                 {
-                    view.internalSize2D = new Size2D(view.OnSize2DChanged, 0, 0);
+                    view.layout?.RequestLayout();
                 }
-                Object.InternalRetrievingPropertyVector2ActualVector3(view.SwigCPtr, View.Property.SIZE, view.internalSize2D.SwigCPtr);
 
-                return view.internalSize2D;
+                Object.InternalSetPropertyVector2ActualVector3(view.SwigCPtr, View.Property.SIZE, ((Size2D)newValue).SwigCPtr);
             }
+        }
+
+        internal static object GetInternalSize2DProperty(BindableObject bindable)
+        {
+            var view = (View)bindable;
+            if (view.internalSize2D == null)
+            {
+                view.internalSize2D = new Size2D(view.OnSize2DChanged, 0, 0);
+            }
+            Object.InternalRetrievingPropertyVector2ActualVector3(view.SwigCPtr, View.Property.SIZE, view.internalSize2D.SwigCPtr);
+
+            return view.internalSize2D;
+        }
+
+        /// <summary>
+        /// Size2DProperty
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly BindableProperty Size2DProperty = BindableProperty.Create(nameof(Size2D), typeof(Size2D), typeof(View), null,
+            propertyChanged: SetInternalSize2DProperty,
+            defaultValueCreator: GetInternalSize2DProperty
         );
 
         /// <summary>
@@ -795,29 +810,33 @@ namespace Tizen.NUI.BaseComponents
             return Object.InternalGetPropertyFloat(view.SwigCPtr, View.Property.OPACITY);
         }));
 
+        internal static void SetInternalPosition2DProperty(BindableObject bindable, object oldValue, object newValue)
+        {
+            var view = (View)bindable;
+            if (newValue != null)
+            {
+                Object.InternalSetPropertyVector2ActualVector3(view.SwigCPtr, View.Property.POSITION, ((Position2D)newValue).SwigCPtr);
+            }
+        }
+
+        internal static object GetInternalPosition2DProperty(BindableObject bindable)
+        {
+            var view = (View)bindable;
+            if (view.internalPosition2D == null)
+            {
+                view.internalPosition2D = new Position2D(view.OnPosition2DChanged, 0, 0);
+            }
+            Object.InternalRetrievingPropertyVector2ActualVector3(view.SwigCPtr, View.Property.POSITION, view.internalPosition2D.SwigCPtr);
+            return view.internalPosition2D;
+        }
+
         /// <summary>
         /// Position2DProperty
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty Position2DProperty = BindableProperty.Create(nameof(Position2D), typeof(Position2D), typeof(View), null,
-            propertyChanged: (bindable, oldValue, newValue) =>
-            {
-                var view = (View)bindable;
-                if (newValue != null)
-                {
-                    Object.InternalSetPropertyVector2ActualVector3(view.SwigCPtr, View.Property.POSITION, ((Position2D)newValue).SwigCPtr);
-                }
-            },
-            defaultValueCreator: (bindable) =>
-            {
-                var view = (View)bindable;
-                if (view.internalPosition2D == null)
-                {
-                    view.internalPosition2D = new Position2D(view.OnPosition2DChanged, 0, 0);
-                }
-                Object.InternalRetrievingPropertyVector2ActualVector3(view.SwigCPtr, View.Property.POSITION, view.internalPosition2D.SwigCPtr);
-                return view.internalPosition2D;
-            }
+            propertyChanged: SetInternalPosition2DProperty,
+            defaultValueCreator: GetInternalPosition2DProperty
         );
 
         /// <summary>
index 0e530c5..c9570f9 100755 (executable)
@@ -12,6 +12,7 @@ namespace Tizen.NUI.Samples
     {
         public DaliDemo(string styleSheet) : base(styleSheet)
         {
+            //DisableBindableProperty = true;
         }
 
         private IExample curExample = null;
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/DisableBindablePropertyTest.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/DisableBindablePropertyTest.cs
new file mode 100755 (executable)
index 0000000..a85087c
--- /dev/null
@@ -0,0 +1,169 @@
+
+using global::System;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI.Samples
+{
+    using tlog = Tizen.Log;
+    public class DisableBindablePropertyTest : IExample
+    {
+        private const int NUMBER_OF_VIEW = 300;
+        private const int MIN_SIZE = 100;
+        private const int MAX_SIZE = 200;
+        private const int MIN_POSITION = 10;
+        private const int MAX_POSITION = 1000;
+        private const int MAX_TEST_REPEAT = 200;
+        private const int TIMER_TICK_MS = 5;
+
+        private Window win;
+        private View rootView;
+        private Random rand = new Random();
+        private Timer timer;
+        int repeat = 0;
+
+        public void Activate()
+        {
+            //test speed
+            PropertySetGetTest();
+
+            //test memory
+            //ViewDisposeTest();
+        }
+
+        private void ViewDisposeTest()
+        {
+            win = NUIApplication.GetDefaultWindow();
+
+            rootView = new View()
+            {
+                Size = new Size(100, 100),
+                BackgroundColor = Color.Blue,
+            };
+            win.Add(rootView);
+
+            repeat = 0;
+            timer = new Timer(TIMER_TICK_MS);
+            timer.Tick += OnViewDispose;
+            timer.Start();
+            tlog.Fatal("NT", $"view create/dipose timer start! should be {TIMER_TICK_MS * MAX_TEST_REPEAT}ms");
+        }
+
+        private bool OnViewDispose(object source, Timer.TickEventArgs e)
+        {
+            repeat++;
+            if (repeat % 2 == 0)
+            {
+                //create child
+                //tlog.Fatal("NT", $"create views");
+                for (int i = 0; i < NUMBER_OF_VIEW; i++)
+                {
+                    var child = new View()
+                    {
+                        Size2D = new Size2D(rand.Next(MIN_SIZE, MAX_SIZE), rand.Next(MIN_SIZE, MAX_SIZE)),
+                        Position2D = new Position2D(rand.Next(MIN_POSITION, MAX_POSITION), rand.Next(MIN_POSITION, MAX_POSITION)),
+                        BackgroundColor = new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), 1),
+                    };
+                    rootView.Add(child);
+                }
+            }
+            else
+            {
+                //dispose child
+                //tlog.Fatal("NT", $"dispose views");
+                int childCnt = (int)rootView.ChildCount;
+
+                for (int i = childCnt - 1; i >= 0; i--)
+                {
+                    var child = rootView.GetChildAt((uint)i);
+                    rootView.Remove(child);
+                    child.Dispose();
+                }
+            }
+
+            if (repeat > MAX_TEST_REPEAT)
+            {
+                tlog.Fatal("NT", $"view create/dipose timer end!");
+                return false;
+            }
+            return true;
+        }
+
+
+        public void Deactivate()
+        {
+            DisposeChildOfRootView();
+            timer.Stop();
+            timer.Dispose();
+            rootView.Unparent();
+            rootView.Dispose();
+        }
+
+        private void PropertySetGetTest()
+        {
+            win = NUIApplication.GetDefaultWindow();
+
+            rootView = new View()
+            {
+                Size = new Size(100, 100),
+                BackgroundColor = Color.Blue,
+            };
+            win.Add(rootView);
+
+            for (int i = 0; i < NUMBER_OF_VIEW; i++)
+            {
+                var child = new View()
+                {
+                    Size2D = new Size2D(rand.Next(MIN_SIZE, MAX_SIZE), rand.Next(MIN_SIZE, MAX_SIZE)),
+                    Position2D = new Position2D(rand.Next(MIN_POSITION, MAX_POSITION), rand.Next(MIN_POSITION, MAX_POSITION)),
+                    BackgroundColor = new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), 1),
+                };
+                rootView.Add(child);
+            }
+            repeat = 0;
+            timer = new Timer(TIMER_TICK_MS);
+            timer.Tick += OnChangeProperties;
+            timer.Start();
+            tlog.Fatal("NT", $"property change timer start! should be {TIMER_TICK_MS * MAX_TEST_REPEAT}ms");
+        }
+
+        private bool OnChangeProperties(object source, Timer.TickEventArgs e)
+        {
+            uint childCnt = rootView.ChildCount;
+
+            for (uint i = 0; i < childCnt; i++)
+            {
+                int w = rand.Next(MIN_SIZE, MAX_SIZE);
+                int h = rand.Next(MIN_SIZE, MAX_SIZE);
+                int x = rand.Next(MIN_POSITION, MAX_POSITION);
+                int y = rand.Next(MIN_POSITION, MAX_POSITION);
+                float r = (float)rand.NextDouble();
+                float g = (float)rand.NextDouble();
+                float b = (float)rand.NextDouble();
+
+                var child = rootView.GetChildAt(i);
+                child.Size2D = new Size(w, h);
+                child.Position2D = new Position2D(x, y);
+                child.BackgroundColor = new Color(r, g, b, 1);
+            }
+
+            if (repeat++ > MAX_TEST_REPEAT)
+            {
+                tlog.Fatal("NT", $"property change timer end!");
+                return false;
+            }
+            return true;
+        }
+
+        private void DisposeChildOfRootView()
+        {
+            int childCnt = (int)rootView.ChildCount;
+
+            for (int i = childCnt - 1; i >= 0; i--)
+            {
+                var child = rootView.GetChildAt((uint)i);
+                rootView.Remove(child);
+                child.Dispose();
+            }
+        }
+    }
+}