[NUI] RootLayout added to Window (#308)
authordongsug-song <35130733+dongsug-song@users.noreply.github.com>
Fri, 22 Jun 2018 04:12:46 +0000 (13:12 +0900)
committerGitHub <noreply@github.com>
Fri, 22 Jun 2018 04:12:46 +0000 (13:12 +0900)
Change-Id: Ie47ceec452b5f254950263bdaf661e9e3fe86d1f

src/Tizen.NUI/src/internal/ManualPINVOKE.cs
src/Tizen.NUI/src/public/Layer.cs
src/Tizen.NUI/src/public/Window.cs
test/NUITestSample/NUITestSample/examples/layouting/CustomLayout.cs [new file with mode: 0755]
test/NUITestSample/NUITestSample/examples/layouting/SimpleLayout.cs [new file with mode: 0755]
test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test.cs [moved from test/NUITestSample/NUITestSample/examples/custom-layout-test.cs with 100% similarity]
test/NUITestSample/NUITestSample/examples/layouting/linear-layout-test.cs [moved from test/NUITestSample/NUITestSample/examples/linear-layout-test.cs with 100% similarity]

index be50b6d..526e02c 100755 (executable)
@@ -1276,6 +1276,9 @@ namespace Tizen.NUI
         [global::System.Runtime.InteropServices.DllImport("libdali-csharp-binder.so", EntryPoint = "CSharp_Dali_Adaptor_RenderOnce")]
         public static extern void Window_RenderOnce(global::System.Runtime.InteropServices.HandleRef jarg1);
 
+        [global::System.Runtime.InteropServices.DllImport("libdali-csharp-binder.so", EntryPoint="CSharp_Dali_Window_New_Root_Layout")]
+        public static extern global::System.IntPtr Window_NewRootLayout();
+
         //for watch
         [global::System.Runtime.InteropServices.DllImport("libdali-csharp-binder.so", EntryPoint = "CSharp_Dali_new_WatchTime")]
         public static extern global::System.IntPtr new_WatchTime();
index dce0a41..f3fe522 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2018 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.
@@ -64,6 +64,7 @@ namespace Tizen.NUI
             }
         }
 
+
         /// <summary>
         /// Removes a child view from this layer. If the view was not a child of this layer, this is a no-op.
         /// </summary>
@@ -462,6 +463,16 @@ namespace Tizen.NUI
             return ret;
         }
 
+        internal void AddViewToLayerList( View view )
+        {
+            Children.Add(view);
+        }
+
+        internal void RemoveViewFromLayerList( View view )
+        {
+            Children.Remove(view);
+        }
+
         /// <summary>
         /// Enumeration for the behavior of the layer.
         /// </summary>
index 960194e..a6c838e 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2018 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.
@@ -31,6 +31,8 @@ namespace Tizen.NUI
     {
         private global::System.Runtime.InteropServices.HandleRef swigCPtr;
         private global::System.Runtime.InteropServices.HandleRef stageCPtr;
+        private global::System.Runtime.InteropServices.HandleRef rootLayoutCPtr;
+        private global::System.IntPtr rootLayoutIntPtr;
         private Layer _rootLayer;
         private string _windowTitle;
 
@@ -49,6 +51,15 @@ namespace Tizen.NUI
             if (NDalicPINVOKE.Stage_IsInstalled())
             {
                 stageCPtr = new global::System.Runtime.InteropServices.HandleRef(this, NDalicPINVOKE.Stage_GetCurrent());
+                // Create a root layout (AbsoluteLayout) that is invisible to the user but enables layouts added to the Window
+                // Enables layouts added to the Window to have a parent layout.  As parent layout is needed to store measure spec properties.
+                // Currently without these measure specs the new layout added will always be the size of the window.
+                rootLayoutIntPtr = NDalicManualPINVOKE.Window_NewRootLayout();
+                // Store HandleRef used by Add()
+                rootLayoutCPtr = new global::System.Runtime.InteropServices.HandleRef(this, rootLayoutIntPtr);
+                Layer rootLayer = GetRootLayer();
+                // Add the root layout created above to the root layer.
+                NDalicPINVOKE.Actor_Add(  Layer.getCPtr(rootLayer), rootLayoutCPtr );
             }
         }
 
@@ -597,7 +608,9 @@ namespace Tizen.NUI
         /// <since_tizen> 3 </since_tizen>
         public void Add(View view)
         {
-            GetRootLayer()?.Add(view);
+            NDalicPINVOKE.Actor_Add( rootLayoutCPtr, View.getCPtr(view) );
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            this.GetRootLayer().AddViewToLayerList(view); // Maintain the children list in the Layer
         }
 
         /// <summary>
@@ -607,7 +620,8 @@ namespace Tizen.NUI
         /// <since_tizen> 3 </since_tizen>
         public void Remove(View view)
         {
-            GetRootLayer()?.Remove(view);
+            NDalicPINVOKE.Actor_Remove( rootLayoutCPtr, View.getCPtr(view) );
+            this.GetRootLayer().RemoveViewFromLayerList(view); // Maintain the children list in the Layer
         }
 
         internal Vector2 GetSize()
@@ -662,6 +676,7 @@ namespace Tizen.NUI
             // Core has been initialized, not when Stage is ready.
             if (_rootLayer == null && Window.IsInstalled())
             {
+                // Get RootLayer so can add RootLayout to it.
                 _rootLayer = new Layer(NDalicPINVOKE.Stage_GetRootLayer(stageCPtr), true);
                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
                 LayersChildren.Add(_rootLayer);
diff --git a/test/NUITestSample/NUITestSample/examples/layouting/CustomLayout.cs b/test/NUITestSample/NUITestSample/examples/layouting/CustomLayout.cs
new file mode 100755 (executable)
index 0000000..ac55ae3
--- /dev/null
@@ -0,0 +1,106 @@
+
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+
+namespace SimpleLayout
+{
+    public class CustomLayout : LayoutGroup
+    {
+        protected override void OnMeasure( LayoutMeasureSpec widthMeasureSpec, LayoutMeasureSpec heightMeasureSpec )
+        {
+            var accumulatedWidth = new LayoutLength( 0 );
+            var maxHeight = 0;
+            var measuredWidth = new LayoutLength( 0 );
+            LayoutLength measuredHeight = new LayoutLength( 0) ;
+            LayoutMeasureSpec.ModeType widthMode = widthMeasureSpec.Mode;
+            LayoutMeasureSpec.ModeType heightMode = heightMeasureSpec.Mode;
+
+            bool isWidthExact = (widthMode == LayoutMeasureSpec.ModeType.EXACTLY);
+            bool isHeightExact = (heightMode == LayoutMeasureSpec.ModeType.EXACTLY);
+
+            // In this layout we will:
+            //  Measuring the layout with the children in a horizontal configuration, one after another
+            //  Set the required width to be the accumulated width of our children
+            //  Set the required height to be the maximum height of any of our children
+
+            for( uint i = 0; i < ChildCount; ++i )
+            {
+                var childLayout = GetChildAt( i );
+                if( childLayout )
+                {
+                    MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+                    accumulatedWidth += childLayout.MeasuredWidth;
+                    maxHeight = System.Math.Max( childLayout.MeasuredHeight.Value, maxHeight );
+                }
+            }
+
+            measuredHeight.Value = maxHeight ;
+            measuredWidth = accumulatedWidth;
+
+            if( isWidthExact )
+            {
+                measuredWidth = new LayoutLength( widthMeasureSpec.Size );
+            }
+
+            if( isHeightExact )
+            {
+                measuredHeight = new LayoutLength( heightMeasureSpec.Size );
+            }
+
+            // Finally, call this method to set the dimensions we would like
+            SetMeasuredDimensions( new MeasuredSize( measuredWidth ), new MeasuredSize( measuredHeight ) );
+        }
+
+        protected override void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+        {
+            LayoutLength childTop = new LayoutLength( 0 );
+            LayoutLength childLeft = new LayoutLength( 0 );
+
+            // We want to vertically align the children to the middle
+            var height = bottom - top;
+            var middle = height / 2;
+
+            // Horizontally align the children to the middle of the space they are given too
+            var width = right - left;
+            uint count = ChildCount;
+            var childIncrement = 0;
+            if (count > 0)
+            {
+                childIncrement = width.Value / System.Convert.ToInt32( count );
+            }
+            var center = childIncrement / 2;
+
+            // Check layout direction
+            var view = GetOwner();
+            ViewLayoutDirectionType layoutDirection = view.LayoutDirection;
+
+            for ( uint i = 0; i < count; i++ )
+            {
+                uint itemIndex;
+                // If RTL, then layout the last item first
+                if (layoutDirection == ViewLayoutDirectionType.RTL)
+                {
+                    itemIndex = count - 1 - i;
+                }
+                else
+                {
+                    itemIndex = i;
+                }
+
+                LayoutItem childLayout = GetChildAt( itemIndex );
+                if( childLayout )
+                {
+                    var childWidth = childLayout.MeasuredWidth;
+                    var childHeight = childLayout.MeasuredHeight;
+
+                    childTop = middle - (childHeight / 2);
+
+                    var leftPosition = childLeft + center - childWidth / 2;
+
+                    childLayout.Layout( leftPosition, childTop, leftPosition + childWidth, childTop + childHeight );
+                    childLeft += childIncrement;
+                }
+            }
+        }
+    }
+}
diff --git a/test/NUITestSample/NUITestSample/examples/layouting/SimpleLayout.cs b/test/NUITestSample/NUITestSample/examples/layouting/SimpleLayout.cs
new file mode 100755 (executable)
index 0000000..3f067e7
--- /dev/null
@@ -0,0 +1,88 @@
+using System;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+
+namespace SimpleLayout
+{
+    static class TestImages
+    {
+        private const string resources = "./res";
+
+        /// Child image filenames
+        public static readonly string[] s_images = new string[]
+        {
+            resources + "/images/application-icon-101.png",
+            resources + "/images/application-icon-102.png",
+            resources + "/images/application-icon-103.png",
+            resources + "/images/application-icon-104.png"
+        };
+    }
+
+    class SimpleLayout : NUIApplication
+    {
+        protected override void OnCreate()
+        {
+            base.OnCreate();
+            Initialize();
+        }
+
+        private void Initialize()
+        {
+            // Change the background color of Window to White
+            Window window = Window.Instance;
+            window.BackgroundColor = Color.White;
+
+            //Layer layer = new Layer();
+
+            //window.AddLayer(layer);
+
+            // Create a new view
+            View customLayoutView = new View();
+            customLayoutView.Name = "CustomLayoutView";
+            customLayoutView.ParentOrigin = ParentOrigin.Center;
+            customLayoutView.PivotPoint = PivotPoint.Center;
+            customLayoutView.PositionUsesPivotPoint = true;
+            // Set our Custom Layout on the view
+            var layout = new CustomLayout();
+            customLayoutView.Layout = layout;
+            customLayoutView.SetProperty( LayoutItemWrapper.ChildProperty.WIDTH_SPECIFICATION, new PropertyValue(-2) );  // -2 WRAP_CONTENT
+            customLayoutView.SetProperty( LayoutItemWrapper.ChildProperty.HEIGHT_SPECIFICATION, new PropertyValue(350) );
+            customLayoutView.BackgroundColor = Color.Blue;
+            window.Add( customLayoutView );
+
+            // Add child image-views to the created view
+            foreach (String image in TestImages.s_images)
+            {
+                customLayoutView.Add( CreateChildImageView( image, new Size2D( 100, 100 ) ) );
+            }
+        }
+
+        /// <summary>
+        /// Helper function to create ImageViews with given filename and size..<br />
+        /// </summary>
+        /// <param name="filename"> The filename of the image to use.</param>
+        /// <param name="size"> The size that the image should be loaded at.</param>
+        /// <returns>The created ImageView.</returns>
+        ImageView CreateChildImageView( String url, Size2D size )
+        {
+            ImageView imageView = new ImageView();
+            ImageVisual imageVisual = new ImageVisual();
+
+            imageVisual.URL = url;
+            imageVisual.DesiredHeight = size.Height;
+            imageVisual.DesiredWidth = size.Width;
+            imageView.Image = imageVisual.OutputVisualMap;
+
+            imageView.Name = "ImageView";
+            imageView.HeightResizePolicy = ResizePolicyType.Fixed;
+            imageView.WidthResizePolicy = ResizePolicyType.Fixed;
+            return imageView;
+        }
+
+        static void Main(string[] args)
+        {
+            SimpleLayout simpleLayout = new SimpleLayout();
+            simpleLayout.Run(args);
+        }
+    }
+}