[NUI] Create TextLayout when parent has layout
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Layouting / LayoutGroup.cs
index c138812..091824e 100755 (executable)
@@ -20,6 +20,8 @@ using System.ComponentModel;
 using System.Diagnostics;
 using Tizen.NUI.BaseComponents;
 using System.Linq;
+using Tizen.NUI.Binding.Internals;
+using static Tizen.NUI.Binding.BindableObject;
 
 namespace Tizen.NUI
 {
@@ -102,27 +104,13 @@ namespace Tizen.NUI
                         // Add LayoutItem to the transition stack so can animate it out.
                         NUIApplication.GetDefaultWindow().LayoutController.AddTransitionDataEntry(new LayoutData(layoutItem, ConditionForAnimation, 0, 0, 0, 0));
                     }
-                    else
-                    {
-                        if(childLayout.Owner != null)
-                        {
-                            View parent = childLayout.Owner.GetParent() as View;
-
-                            if(parent != null)
-                            {
-                                parent.RemoveChild(childLayout.Owner);
-                            }
-                            else
-                            {
-                                NUIApplication.GetDefaultWindow().Remove(childLayout.Owner);
-                            }
-                        }
-                    }
 
                     // Reset condition for animation ready for next transition when required.
                     // SetFrame usually would do this but this LayoutItem is being removed.
                     childLayout.ConditionForAnimation = TransitionCondition.Unspecified;
                     childRemoved = true;
+
+                    break;
                 }
             }
 
@@ -131,7 +119,7 @@ namespace Tizen.NUI
                 // If child removed then set all siblings not being added to a ChangeOnRemove transition.
                 SetConditionsForAnimationOnLayoutGroup(TransitionCondition.ChangeOnRemove);
             }
-
+            OnChildRemove(layoutItem);
             RequestLayout();
         }
 
@@ -145,17 +133,20 @@ namespace Tizen.NUI
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void ChangeLayoutSiblingOrder(int order)
         {
-            if(Owner != null && Owner.Parent != null)
+            if (Owner != null)
             {
-                LayoutGroup parent = Owner.Parent.Layout as LayoutGroup;
-
-                if(parent != null && parent.LayoutChildren.Count>order)
+                var ownerParent = Owner.GetParent() as View;
+                if (ownerParent != null)
                 {
-                    parent.LayoutChildren.Remove(this);
-                    parent.LayoutChildren.Insert(order,this);
+                    var parent = ownerParent.Layout as LayoutGroup;
+
+                    if (parent != null && parent.LayoutChildren.Count > order)
+                    {
+                        parent.LayoutChildren.Remove(this);
+                        parent.LayoutChildren.Insert(order, this);
+                    }
                 }
             }
-
             RequestLayout();
         }
 
@@ -175,16 +166,7 @@ namespace Tizen.NUI
                 {
                     // If child of this layout is a pure View then assign it a LayoutGroup
                     // If the child is derived from a View then it may be a legacy or existing container hence will do layouting itself.
-                    if (child.GetType() == typeof(View))
-                    {
-                        child.Layout = new LayoutGroup();
-                    }
-                    else
-                    {
-                        // Adding child as a leaf, layouting will not propagate past this child.
-                        // Legacy containers will be a LayoutItems too and layout their children how they wish.
-                        child.Layout = new LayoutItem();
-                    }
+                    child.Layout = (child as TextLabel)?.CreateTextLayout() ?? new AbsoluteLayout();
                 }
             }
             else
@@ -204,8 +186,10 @@ namespace Tizen.NUI
         /// <param name="child">Child View to remove.</param>
         internal void RemoveChildFromLayoutGroup(View child)
         {
-            Debug.Assert(child.Layout !=null);
-            Remove(child.Layout);
+            if(child.Layout != null)
+            {
+                Remove(child.Layout);
+            }
         }
 
         /// <summary>
@@ -291,7 +275,7 @@ namespace Tizen.NUI
             MeasureSpecification.ModeType resultMode = MeasureSpecification.ModeType.Unspecified;
 
             // Child only can use parent's size without parent's padding and own margin.
-            LayoutLength resultSize = new LayoutLength(Math.Max( 0.0f, parentMeasureSpec.Size.AsDecimal()));
+            LayoutLength resultSize = new LayoutLength(Math.Max( 0.0f, (parentMeasureSpec.Size - padding).AsDecimal()));
             switch( specMode )
             {
                 // Parent has imposed an exact size on us
@@ -299,19 +283,14 @@ namespace Tizen.NUI
                 {
                     if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent)
                     {
-                        // Child wants to be our size. So be it.
                         resultMode = MeasureSpecification.ModeType.Exactly;
                     }
                     else if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent)
                     {
-                        // Child wants to determine its own size. It can't be
-                        // bigger than us.
-                        // Don't need parent's size. Size of this child will be determined by its children.
                         resultMode = MeasureSpecification.ModeType.AtMost;
                     }
                     else
                     {
-                        // Child has its own size.
                         resultSize = childDimension;
                         resultMode = MeasureSpecification.ModeType.Exactly;
                     }
@@ -397,7 +376,7 @@ namespace Tizen.NUI
             {
                 if( childLayout != null )
                 {
-                    MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+                    MeasureChildWithMargins( childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0) );
                     LayoutLength childWidth = new LayoutLength(childLayout.MeasuredWidth.Size);
                     LayoutLength childHeight = new LayoutLength( childLayout.MeasuredHeight.Size);
 
@@ -463,6 +442,10 @@ namespace Tizen.NUI
             // Layout takes ownership of it's owner's children.
             foreach (View view in Owner.Children)
             {
+                if (view is TextLabel)
+                {
+                    view.Layout = (view as TextLabel)?.CreateTextLayout();
+                }
                 AddChildToLayoutGroup(view);
             }
 
@@ -472,6 +455,17 @@ namespace Tizen.NUI
             // Removing Child from the owners View will directly call the LayoutGroup removal API.
         }
 
+        /// <summary>
+        /// Virtual method to allow derived classes to remove any children before it is removed from
+        /// its parent.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void OnUnparent()
+        {
+            // Disconnect to owner ChildAdded signal.
+            Owner.ChildAdded -= OnChildAddedToOwner;
+        }
+
         // Virtual Methods that can be overridden by derived classes.
 
         /// <summary>
@@ -505,7 +499,7 @@ namespace Tizen.NUI
         {
             foreach( LayoutItem childLayout in LayoutChildren )
             {
-                MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+                MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));
             }
         }
 
@@ -523,27 +517,22 @@ namespace Tizen.NUI
             View childOwner = child.Owner;
 
             MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
-                        new MeasureSpecification(
-                            new LayoutLength(parentWidthMeasureSpec.Size - (Padding.Start + Padding.End + childOwner.Margin.Start + childOwner.Margin.End)),
-                            parentWidthMeasureSpec.Mode),
+                        new MeasureSpecification(new LayoutLength(parentWidthMeasureSpec.Size), parentWidthMeasureSpec.Mode),
                         new LayoutLength(Padding.Start + Padding.End ),
                         new LayoutLength(childOwner.WidthSpecification) );
 
             MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
-                        new MeasureSpecification(
-                            new LayoutLength(parentHeightMeasureSpec.Size - (Padding.Top + Padding.Bottom + childOwner.Margin.Top + childOwner.Margin.Bottom)),
-                            parentHeightMeasureSpec.Mode),
+                        new MeasureSpecification(new LayoutLength(parentHeightMeasureSpec.Size), parentHeightMeasureSpec.Mode),
                         new LayoutLength(Padding.Top + Padding.Bottom),
                         new LayoutLength(childOwner.HeightSpecification));
 
-            child.Measure( childWidthMeasureSpec, childHeightMeasureSpec );
+            child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
         }
 
         /// <summary>
         /// Ask one of the children of this view to measure itself, taking into
         /// account both the MeasureSpec requirements for this view and its padding.<br />
-        /// and margins. The child must have MarginLayoutParams The heavy lifting is
-        /// done in GetChildMeasureSpecification.<br />
+        /// and margins. The heavy lifting is done in GetChildMeasureSpecification.<br />
         /// </summary>
         /// <param name="child">The child to measure.</param>
         /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
@@ -558,19 +547,65 @@ namespace Tizen.NUI
 
             MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
                         new MeasureSpecification(
-                            new LayoutLength(parentWidthMeasureSpec.Size + widthUsed - (Padding.Start + Padding.End + childOwner.Margin.Start + childOwner.Margin.End)),
+                            new LayoutLength(parentWidthMeasureSpec.Size + widthUsed - (childOwner.Margin.Start + childOwner.Margin.End)),
                             parentWidthMeasureSpec.Mode),
                         new LayoutLength(Padding.Start + Padding.End ),
                         new LayoutLength(childOwner.WidthSpecification) );
 
             MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
                         new MeasureSpecification(
-                            new LayoutLength(parentHeightMeasureSpec.Size + heightUsed - (Padding.Top + Padding.Bottom + childOwner.Margin.Top + childOwner.Margin.Bottom)),
+                            new LayoutLength(parentHeightMeasureSpec.Size + heightUsed - (childOwner.Margin.Top + childOwner.Margin.Bottom)),
                             parentHeightMeasureSpec.Mode),
                         new LayoutLength(Padding.Top + Padding.Bottom),
                         new LayoutLength(childOwner.HeightSpecification));
             child.Measure( childWidthMeasureSpec, childHeightMeasureSpec );
 
         }
+
+        /// <summary>
+        /// Gets the value that is contained in the attached BindableProperty.
+        /// </summary>
+        /// <typeparam name="T">The return type of property</typeparam>
+        /// <param name="bindable">The bindable object.</param>
+        /// <param name="property">The BindableProperty for which to get the value.</param>
+        /// <returns>The value that is contained in the attached BindableProperty.</returns>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static T GetAttachedValue<T>(Binding.BindableObject bindable, Binding.BindableProperty property)
+        {
+            if (bindable == null)
+                throw new ArgumentNullException(nameof(bindable));
+
+            return (T)bindable.GetValue(property);
+        }
+
+        /// <summary>
+        /// Sets the value of the attached property.
+        /// </summary>
+        /// <param name="bindable">The bindable object.</param>
+        /// <param name="property">The BindableProperty on which to assign a value.</param>
+        /// <param name="value">The value to set.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static void SetAttachedValue(Binding.BindableObject bindable, Binding.BindableProperty property, object value)
+        {
+            if (bindable == null)
+                throw new ArgumentNullException(nameof(bindable));
+
+            bindable.SetValueCore(property, value, SetValueFlags.None, SetValuePrivateFlags.ManuallySet, false);
+        }
+        internal static void OnChildPropertyChanged(Binding.BindableObject bindable, object oldValue, object newValue)
+        {
+            View view = bindable as View;
+            view?.Layout?.RequestLayout();
+        }
+
+        internal static Binding.BindableProperty.ValidateValueDelegate ValidateEnum(int enumMin, int enumMax)
+        {
+
+            return (Binding.BindableObject bindable, object value) =>
+            {
+                int @enum = (int)value;
+                return enumMin <= @enum && @enum <= enumMax;
+            };
+        }
     }
-}
\ No newline at end of file
+}