[NUI] Fix button layout when resize policy is FillToParent and etc. (#2809)
authorhuiyu.eun <huiyu.eun@samsung.com>
Tue, 20 Apr 2021 05:46:42 +0000 (14:46 +0900)
committerhuiyueun <35286162+huiyueun@users.noreply.github.com>
Tue, 20 Apr 2021 06:13:00 +0000 (15:13 +0900)
* Add ItemAlignment property to make it "center" for a Button and "begin" for others.
* Add ItemSpacing to set space between icon and text.

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
Signed-off-by: huiyu.eun <huiyu.eun@samsung.com>
src/Tizen.NUI.Components/Controls/Button.Internal.cs
src/Tizen.NUI.Components/Controls/Button.cs
src/Tizen.NUI.Components/Style/ButtonStyle.cs
src/Tizen.NUI.Components/Theme/DefaultThemeCommon.cs

index c6ef247..33f85a7 100755 (executable)
@@ -17,6 +17,7 @@
 
 using System;
 using System.ComponentModel;
+using System.Diagnostics;
 using Tizen.NUI.BaseComponents;
 using Tizen.NUI.Components.Extension;
 using Tizen.NUI.Accessibility; // To use AccessibilityManager
@@ -28,6 +29,7 @@ namespace Tizen.NUI.Components
         private ImageView overlayImage;
         private TextLabel buttonText;
         private ImageView buttonIcon;
+        private Vector2 size;
 
         private EventHandler<StateChangedEventArgs> stateChangeHandler;
 
@@ -283,6 +285,17 @@ namespace Tizen.NUI.Components
 
         /// <inheritdoc/>
         [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void OnRelayout(Vector2 size, RelayoutContainer container)
+        {
+            Debug.Assert(size != null);
+
+            this.size = new Vector2(size);
+
+            UpdateSizeAndSpacing();
+        }
+
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
         {
             base.OnControlStateChanged(controlStateChangedInfo);
@@ -322,7 +335,8 @@ namespace Tizen.NUI.Components
                 Layout = new LinearLayout()
                 {
                     LinearOrientation = LinearLayout.Orientation.Horizontal,
-                    LinearAlignment = LinearLayout.Alignment.Center,
+                    LinearAlignment = itemAlignment,
+                    CellPadding = itemSpacing ?? new Size2D(0, 0)
                 };
 
                 Add(buttonIcon);
@@ -333,7 +347,8 @@ namespace Tizen.NUI.Components
                 Layout = new LinearLayout()
                 {
                     LinearOrientation = LinearLayout.Orientation.Horizontal,
-                    LinearAlignment = LinearLayout.Alignment.Center,
+                    LinearAlignment = itemAlignment,
+                    CellPadding = itemSpacing ?? new Size2D(0, 0)
                 };
 
                 Add(buttonText);
@@ -344,7 +359,8 @@ namespace Tizen.NUI.Components
                 Layout = new LinearLayout()
                 {
                     LinearOrientation = LinearLayout.Orientation.Vertical,
-                    LinearAlignment = LinearLayout.Alignment.Center,
+                    LinearAlignment = itemAlignment,
+                    CellPadding = itemSpacing ?? new Size2D(0, 0)
                 };
 
                 Add(buttonIcon);
@@ -355,7 +371,8 @@ namespace Tizen.NUI.Components
                 Layout = new LinearLayout()
                 {
                     LinearOrientation = LinearLayout.Orientation.Vertical,
-                    LinearAlignment = LinearLayout.Alignment.Center,
+                    LinearAlignment = itemAlignment,
+                    CellPadding = itemSpacing ?? new Size2D(0, 0)
                 };
 
                 Add(buttonText);
@@ -369,6 +386,53 @@ namespace Tizen.NUI.Components
             }
         }
 
+        private void UpdateSizeAndSpacing()
+        {
+            if (size == null || buttonIcon == null || buttonText == null)
+            {
+                return;
+            }
+
+            LinearLayout layout = Layout as LinearLayout;
+
+            if (layout == null)
+            {
+                return;
+            }
+
+            float lengthWithoutText = 0;
+            Size2D cellPadding = null;
+            Extents iconMargin = buttonIcon.Margin ?? new Extents(0);
+            Extents textMargin = buttonText.Margin ?? new Extents(0);
+
+            if (buttonIcon.Size.Width != 0 && buttonIcon.Size.Height != 0)
+            {
+                lengthWithoutText = buttonIcon.Size.Width;
+
+                if (!String.IsNullOrEmpty(buttonText.Text))
+                {
+                    cellPadding = itemSpacing;
+
+                    if (iconRelativeOrientation == IconOrientation.Left || iconRelativeOrientation == IconOrientation.Right)
+                    {
+                        lengthWithoutText += (itemSpacing?.Width ?? 0) + iconMargin.Start + iconMargin.End + textMargin.Start + textMargin.End;
+                    }
+                    else
+                    {
+                        lengthWithoutText += (itemSpacing?.Height ?? 0) + iconMargin.Top + iconMargin.Bottom + textMargin.Top + textMargin.Bottom;
+                    }
+                }
+            }
+
+            layout.CellPadding = cellPadding ?? new Size2D(0, 0);
+
+            // If the button has fixed width and the text is not empty, the text should not exceed button boundary.
+            if (WidthSpecification != LayoutParamPolicies.WrapContent && !String.IsNullOrEmpty(buttonText.Text))
+            {
+                buttonText.MaximumSize = new Size2D((int)Math.Max(size.Width - lengthWithoutText, Math.Max(buttonText.MinimumSize.Width, 1)), (int)size.Height);
+            }
+        }
+
         private void OnClickedInternal(ClickedEventArgs eventArgs)
         {
             Command?.Execute(CommandParameter);
index 2e466df..96021fb 100755 (executable)
@@ -127,33 +127,53 @@ namespace Tizen.NUI.Components
         public static readonly BindableProperty IconPaddingProperty = BindableProperty.Create(nameof(IconPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var instance = (Button)bindable;
-            instance.iconPadding = (Extents)((Extents)newValue).Clone();
-            if (instance.buttonIcon != null)
+            if (instance.buttonIcon == null)
             {
-                instance.buttonIcon.Margin = instance.iconPadding;
+                return;
             }
+            instance.buttonIcon.Padding = (Extents)newValue;
         },
-        defaultValueCreator: (bindable) => ((Button)bindable).iconPadding);
+        defaultValueCreator: (bindable) => ((Button)bindable).buttonIcon?.Padding);
 
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty TextPaddingProperty = BindableProperty.Create(nameof(TextPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var instance = (Button)bindable;
-            instance.textPadding = (Extents)((Extents)newValue).Clone();
-            if (instance.buttonText != null)
+            if (instance.buttonText == null)
             {
-                instance.buttonText.Margin = instance.textPadding;
+                return;
             }
+            instance.buttonText.Padding = (Extents)newValue;
         },
-        defaultValueCreator: (bindable) => ((Button)bindable).textPadding);
+        defaultValueCreator: (bindable) => ((Button)bindable).buttonText?.Padding);
+
+        /// <summary> The bindable property of ItemAlignment. </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        internal static readonly BindableProperty ItemAlignmentProperty = BindableProperty.Create(nameof(ItemAlignment), typeof(LinearLayout.Alignment), typeof(Button), LinearLayout.Alignment.Center, propertyChanged: (bindable, oldValue, newValue) =>
+        {
+            var instance = (Button)bindable;
+            instance.itemAlignment = (LinearLayout.Alignment)newValue;
+            instance.LayoutItems();
+        },
+        defaultValueCreator: (bindable) => ((Button)bindable).itemAlignment);
+
+        /// <summary> The bindable property of ItemSpacing. </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        internal static readonly BindableProperty ItemSpacingProperty = BindableProperty.Create(nameof(ItemSpacing), typeof(Size2D), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
+        {
+            var instance = (Button)bindable;
+            instance.itemSpacing = (Size2D)newValue;
+            instance.UpdateSizeAndSpacing();
+        },
+        defaultValueCreator: (bindable) => ((Button)bindable).itemSpacing);
 
         private IconOrientation? iconRelativeOrientation = IconOrientation.Left;
         private bool isSelected = false;
         private bool isSelectable = false;
         private bool isEnabled = true;
-        private Extents iconPadding;
-        private Extents textPadding;
+        private Size2D itemSpacing;
+        private LinearLayout.Alignment itemAlignment;
 
         static Button() { }
 
@@ -610,7 +630,7 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
-        /// Icon padding in Button, work only when show icon and text.
+        /// Icon padding in Button. It is shortcut of Icon.Padding.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
         public Extents IconPadding
@@ -620,7 +640,7 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
-        /// Text padding in Button, work only when show icon and text.
+        /// Text padding in Button. It is shortcut of TextLabel.Padding.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
         public Extents TextPadding
@@ -630,6 +650,28 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
+        /// The item (text or icon or both) alignment.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public LinearLayout.Alignment ItemAlignment
+        {
+            get => (LinearLayout.Alignment)GetValue(ItemAlignmentProperty);
+            set => SetValue(ItemAlignmentProperty, value);
+        }
+
+        /// <summary>
+        /// The space between icon and text.
+        /// The value is applied when there exist icon and text both.
+        /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Size2D ItemSpacing
+        {
+            get => (Size2D)GetValue(ItemSpacingProperty);
+            set => SetValue(ItemSpacingProperty, value);
+        }
+
+        /// <summary>
         /// Called after a key event is received by the view that has had its focus set.
         /// </summary>
         /// <param name="key">The key event.</param>
@@ -737,9 +779,11 @@ namespace Tizen.NUI.Components
                 if (Extension != null)
                 {
                     buttonIcon.Unparent();
-                    buttonText.Unparent();
                     buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
+
+                    buttonText.Unparent();
                     buttonText = Extension.OnCreateText(this, buttonText);
+
                     LayoutItems();
                 }
 
index 0b132a1..728493a 100755 (executable)
@@ -98,12 +98,30 @@ namespace Tizen.NUI.Components
             return buttonStyle.textPadding;
         });
 
+        /// <summary> The bindable property of ItemAlignment. </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        internal static readonly BindableProperty ItemAlignmentProperty = BindableProperty.Create(nameof(ItemAlignment), typeof(LinearLayout.Alignment?), typeof(ButtonStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
+        {
+            ((ButtonStyle)bindable).itemAlignment = (LinearLayout.Alignment?)newValue;
+        },
+        defaultValueCreator: (bindable) => ((ButtonStyle)bindable).itemAlignment);
+
+        /// <summary> The bindable property of ItemSpacing. </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        internal static readonly BindableProperty ItemSpacingProperty = BindableProperty.Create(nameof(ItemSpacing), typeof(Size2D), typeof(ButtonStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
+        {
+            ((ButtonStyle)bindable).itemSpacing = (Size2D)newValue;
+        },
+        defaultValueCreator: (bindable) => ((ButtonStyle)bindable).itemSpacing);
+
         private bool? isSelectable;
         private bool? isSelected;
         private bool? isEnabled;
         private Button.IconOrientation? iconRelativeOrientation;
         private Extents iconPadding;
         private Extents textPadding;
+        private Size2D itemSpacing;
+        private LinearLayout.Alignment? itemAlignment;
 
         static ButtonStyle() { }
 
@@ -183,17 +201,19 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
-        /// Icon padding in Button, work only when show icon and text.
+        /// Icon padding in Button. It is shortcut of Icon.Padding.
         /// </summary>
         /// <since_tizen> 8 </since_tizen>
         public Extents IconPadding
         {
+            // TODO Fixme
+            // When there are icon and text, the linear layout does not count padding.
             get => ((Extents)GetValue(IconPaddingProperty)) ?? (iconPadding = new Extents());
             set => SetValue(IconPaddingProperty, value);
         }
 
         /// <summary>
-        /// Text padding in Button, work only when show icon and text.
+        /// Text padding in Button. It is shortcut of Text.Padding.
         /// </summary>
         /// <since_tizen> 8 </since_tizen>
         public Extents TextPadding
@@ -203,6 +223,28 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
+        /// The item (text or icon or both) alignment.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public LinearLayout.Alignment? ItemAlignment
+        {
+            get => (LinearLayout.Alignment?)GetValue(ItemAlignmentProperty);
+            set => SetValue(ItemAlignmentProperty, value);
+        }
+
+        /// <summary>
+        /// The space between icon and text.
+        /// The value is applied when there exist icon and text both.
+        /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Size2D ItemSpacing
+        {
+            get => (Size2D)GetValue(ItemSpacingProperty);
+            set => SetValue(ItemSpacingProperty, value);
+        }
+
+        /// <summary>
         /// Style's clone function.
         /// </summary>
         /// <param name="bindableObject">The style that need to copy.</param>
index dfc069f..fd608c6 100755 (executable)
@@ -38,6 +38,7 @@ namespace Tizen.NUI.Components
                 Size = new Size(339, 96),
                 CornerRadiusPolicy = VisualTransformPolicyType.Relative,
                 CornerRadius = 0.2916f,
+                ItemAlignment = LinearLayout.Alignment.Center,
                 BackgroundColor = new Selector<Color>()
                 {
                     Normal = new Color(0.039f, 0.055f, 0.29f, 1),
@@ -54,7 +55,8 @@ namespace Tizen.NUI.Components
 
             theme.AddStyleWithoutClone("Tizen.NUI.Components.CheckBox", new ButtonStyle()
             {
-                TextPadding = new Extents(32, 0, 0, 0),
+                ItemSpacing = new Size2D(32, 32),
+                ItemAlignment = LinearLayout.Alignment.Begin,
                 Icon = new ImageViewStyle()
                 {
                     Size = new Size(36, 36),
@@ -134,7 +136,8 @@ namespace Tizen.NUI.Components
 
             theme.AddStyleWithoutClone("Tizen.NUI.Components.RadioButton", new ButtonStyle()
             {
-                TextPadding = new Extents(32, 0, 0, 0),
+                ItemSpacing = new Size2D(32, 32),
+                ItemAlignment = LinearLayout.Alignment.Begin,
                 Icon = new ImageViewStyle()
                 {
                     Size = new Size(36, 36),
@@ -188,7 +191,8 @@ namespace Tizen.NUI.Components
 
             theme.AddStyleWithoutClone("Tizen.NUI.Components.Switch", new SwitchStyle()
             {
-                TextPadding = new Extents(32, 0, 0, 0),
+                ItemSpacing = new Size2D(32, 32),
+                ItemAlignment = LinearLayout.Alignment.Begin,
                 Track = new ImageViewStyle()
                 {
                     Size = new Size(80, 40),