[NUI] Add TextFitArray
authorBowon Ryu <bowon.ryu@samsung.com>
Tue, 10 Oct 2023 02:20:47 +0000 (11:20 +0900)
committerEunki Hong <h.pichulia@gmail.com>
Wed, 25 Oct 2023 12:48:44 +0000 (21:48 +0900)
Add a new function to satisfy the UX that
operates TextFit by considering the PointSize and MinLineSize of the text.

For example, TextFit should be able to find the one that
fits among [PointSize 24 + MinLineSize 40] or [PointSize 28 + MinLineSize 44].

But the previous TextFit only considers PointSize.

TextFitArray can solve this problem,
and this implemented it to respond to additional requirements without modifying the API.

https://review.tizen.org/gerrit/#/c/platform/core/uifw/dali-toolkit/+/299557/
https://review.tizen.org/gerrit/#/c/platform/core/uifw/dali-csharp-binder/+/299690/

Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
src/Tizen.NUI/src/internal/Interop/Interop.TextLabel.cs
src/Tizen.NUI/src/public/BaseComponents/TextConstants.cs
src/Tizen.NUI/src/public/BaseComponents/TextLabel.cs
src/Tizen.NUI/src/public/BaseComponents/TextMapHelper.cs
src/Tizen.NUI/src/public/BaseComponents/TextUtils.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/TextFitChangedSample.cs

index 23ebfe0496a31b1f3a0cf024f7cd2ed459d1f2bb..205cc46ef40d76cd4b74df3c2e6e85250a92a2e1 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 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.
@@ -165,6 +165,12 @@ namespace Tizen.NUI
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_GetTextPosition")]
             public static extern global::System.IntPtr GetTextPosition(global::System.Runtime.InteropServices.HandleRef textLabelRef, uint start, uint end);
 
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_SetTextFitArray")]
+            public static extern void SetTextFitArray(global::System.Runtime.InteropServices.HandleRef textLabel, bool enable, uint arraySize, float[] pointSizeArray, float[] minLineSizeArray);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_GetTextFitArray")]
+            public static extern global::System.IntPtr GetTextFitArray(global::System.Runtime.InteropServices.HandleRef textLabel);
+
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_AnchorClickedSignal")]
             public static extern global::System.IntPtr AnchorClickedSignal(global::System.Runtime.InteropServices.HandleRef jarg1);
 
index b141b0a680b181c06d86292b7a56214931f56e75..85b0b0d0c3d1c2d138b90322bc51d6c7b6d997c2 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 Samsung Electronics Co., Ltd.
+// Copyright (c) 2023 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.
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 using System;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics.CodeAnalysis;
 
@@ -546,6 +547,77 @@ namespace Tizen.NUI.Text
         public override int GetHashCode() => (Enable, MinSize, MaxSize, StepSize, FontSizeType, FontSize).GetHashCode();
     }
 
+    /// <summary>
+    /// A struct to pass data of TextFitArray's OptionList.
+    /// </summary>
+    /// <remarks>
+    /// The TextFitArrayOption struct is used as an item to TextFitArray's OptionList. <br />
+    /// See <see cref="Tizen.NUI.Text.TextFitArray"/>.
+    /// </remarks>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815: Override equals and operator equals on value types")]
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public struct TextFitArrayOption
+    {
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="pointSize">The PointSize for TextFitArrayOption</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TextFitArrayOption(float pointSize)
+        {
+            PointSize = pointSize;
+            MinLineSize = null;
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="pointSize">The PointSize for TextFitArrayOption</param>
+        /// <param name="minLineSize">The MinLineSize for TextFitArrayOption</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TextFitArrayOption(float pointSize, float? minLineSize)
+        {
+            PointSize = pointSize;
+            MinLineSize = minLineSize;
+        }
+
+        /// <summary>
+        /// Point size for text fit array.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public float PointSize { get; set; }
+
+        /// <summary>
+        /// Min line size for text fit array.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public float? MinLineSize { get; set; }
+    }
+
+    /// <summary>
+    /// A struct to pass data of SetTextFitArray and GetTextFitArray methods.
+    /// </summary>
+    /// <remarks>
+    /// The TextFitArray struct is used as an argument to SetTextFitArray and GetTextFitArray methods. <br />
+    /// See <see cref="Tizen.NUI.BaseComponents.TextLabel.SetTextFitArray"/> and <see cref="Tizen.NUI.BaseComponents.TextLabel.GetTextFitArray"/>.
+    /// </remarks>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815: Override equals and operator equals on value types")]
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public struct TextFitArray
+    {
+        /// <summary>
+        /// True to enable the text fit array or false to disable (the default value is false).
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool Enable { get; set; }
+
+        /// <summary>
+        /// A List of TextFitArrayOptions.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public List<TextFitArrayOption> OptionList { get; set; }
+    }
+
     /// <summary>
     /// A struct to pass data of Placeholder PropertyMap. <br />
     /// </summary>
index 91e3659214067d0fc08d7426cb62d0cdeb0835b1..e935960729630496ea282cc0837362b2e6b47d02 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 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.
@@ -1404,6 +1404,105 @@ namespace Tizen.NUI.BaseComponents
             return textFit;
         }
 
+        /// <summary>
+        /// Set TextFitArray to TextLabel. <br />
+        /// TextFitArray finds and applies the largest PointSize that fits among OptionList.
+        /// </summary>
+        /// <param name="textFitArray">The TextFitArray</param>
+        /// <remarks>
+        /// TextFitArray tries binary search by default. <br />
+        /// The precondition for TextFitArray to perform binary search is sorting in ascending order of MinLineSize. <br />
+        /// Because if MinLineSize is not sorted in ascending order, <br />
+        /// binary search cannot guarantee that it will always find the best value. <br />
+        /// In this case, the search sequentially starts from the largest PointSize. <br />
+        /// If TextFitArrayOption's MinLineSize is set to null or 0, <br />
+        /// TextFitArray is calculated without applying MinLineSize. <br />
+        /// If TextFitArray is enabled, TextLabel's MinLineSize property is ignored. <br />
+        /// See <see cref="Tizen.NUI.Text.TextFitArray"/> and <see cref="Tizen.NUI.Text.TextFitArrayOption"/>.
+        /// </remarks>
+        /// <example>
+        /// The following example demonstrates how to use the SetTextFitArray method. <br />
+        /// <code>
+        /// var textFitArray = new Tizen.NUI.Text.TextFitArray();
+        /// textFitArray.Enable = true;
+        /// textFitArray.OptionList = new List<Tizen.NUI.Text.TextFitArrayOption>()
+        /// {
+        ///     new Tizen.NUI.Text.TextFitArrayOption(12, 18),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(24, 40),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(28, 48),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(32, 56),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(50, 72),
+        /// };
+        /// label.SetTextFitArray(textFitArray);
+        /// </code>
+        /// <br />
+        /// The table below shows cases where binary search is possible and where it is not possible. <br />
+        /// <code>
+        /// [Binary search possible]
+        /// |            | List index  |  0 |  1 |  2 |  3 |
+        /// | OptionList | PointSize   | 24 | 28 | 32 | 48 |
+        /// |            | MinLineSize | 40 | 48 | 48 | 62 | << MinLineSize sorted in ascending order
+        ///                                    ^    ^
+        ///                                    same values ​are not a problem
+        ///
+        /// [Binary search not possible]
+        /// |            | List index  |  0 |  1 |  2 |  3 |
+        /// | OptionList | PointSize   | 24 | 28 | 32 | 48 |
+        /// |            | MinLineSize | 40 | 48 | 38 | 62 | << MinLineSize is not sorted in ascending order
+        ///                                         ^
+        /// </code>
+        /// </example>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void SetTextFitArray(TextFitArray textFitArray)
+        {
+            bool enable = textFitArray.Enable;
+            int optionListSize = textFitArray.OptionList?.Count ?? 0;
+
+            float[] pointSizeArray = new float[optionListSize];
+            float[] minLineSizeArray = new float[optionListSize];
+
+            for (int i = 0 ; i < optionListSize ; i ++)
+            {
+                TextFitArrayOption option = textFitArray.OptionList[i];
+                pointSizeArray[i] = option.PointSize;
+                minLineSizeArray[i] = option.MinLineSize ?? 0;
+            }
+
+            Interop.TextLabel.SetTextFitArray(SwigCPtr, enable, (uint)optionListSize, pointSizeArray, minLineSizeArray);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        /// <summary>
+        /// Get TextFitArray from TextLabel.
+        /// </summary>
+        /// <returns>The TextFitArray</returns>
+        /// <remarks>
+        /// See <see cref="Tizen.NUI.Text.TextFitArray"/> and <see cref="Tizen.NUI.Text.TextFitArrayOption"/>.
+        /// </remarks>
+        /// <example>
+        /// The following example demonstrates how to use the GetTextFitArray method. <br />
+        /// <code>
+        /// Tizen.NUI.Text.TextFitArray textFitArray = label.GetTextFitArray();
+        /// bool enable = textFitArray.Enable;
+        /// var optionList = textFitArray.OptionList;
+        /// foreach(Tizen.NUI.Text.TextFitArrayOption option in optionList)
+        /// {
+        ///     float pointSize = option.PointSize;
+        ///     float minLinesize = option.MinLineSize;
+        /// }
+        /// </code>
+        /// </example>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TextFitArray GetTextFitArray()
+        {
+            using PropertyMap textFitArrayMap = new PropertyMap(Interop.TextLabel.GetTextFitArray(SwigCPtr), true);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+            TextFitArray textFitArray;
+            textFitArray = TextUtils.GetMapToTextFitArray(textFitArrayMap);
+            return textFitArray;
+        }
+
         /// <summary>
         /// The MinLineSize property.<br />
         /// The height of the line in points. <br />
index d90ce64441f76ccc5d2c74744ae22137271fb22f..cf0454940f1c3b92fdc5a831aa5d1273aa1ae592 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 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.
@@ -737,6 +737,16 @@ namespace Tizen.NUI.BaseComponents
             return value;
         }
 
+        internal static PropertyArray GetArrayFromMap(PropertyMap map, string key)
+        {
+            PropertyArray value = new PropertyArray();
+            using (var propertyValue = map.Find(0, key))
+            {
+                if (null != propertyValue) propertyValue.Get(value);
+            }
+            return value;
+        }
+
         internal static int? GetNullableIntFromMap(PropertyMap map, int key)
         {
             using (var propertyValue = map.Find(key))
index 93edc25bdd9e8aafa14fb527eaf830b0c298ec02..b1255b0141894e8a1645655f311ff02233922f39 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 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.
@@ -1122,6 +1122,40 @@ namespace Tizen.NUI.BaseComponents
             return fontList;
         }
 
+        /// <summary>
+        /// This method converts a TextFitArray property map to a TextFitArray and returns it.
+        /// <param name="textFitArrayMap">The TextFitArray PropertyMap.</param>
+        /// <returns> A TextFitArray struct. </returns>
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static TextFitArray GetMapToTextFitArray(PropertyMap textFitArrayMap)
+        {
+            var textFitArray = new TextFitArray();
+            if (textFitArrayMap != null)
+            {
+                textFitArray.Enable = TextMapHelper.GetBoolFromMap(textFitArrayMap, "enable", false);
+                textFitArray.OptionList = new List<TextFitArrayOption>();
+
+                var pointSizeArray = TextMapHelper.GetArrayFromMap(textFitArrayMap, "pointSizeArray");
+                var minLineSizeArray = TextMapHelper.GetArrayFromMap(textFitArrayMap, "minLineSizeArray");
+
+                if (pointSizeArray != null && minLineSizeArray != null && pointSizeArray.Count() == minLineSizeArray.Count())
+                {
+                    for (uint i = 0 ; i < pointSizeArray.Count() ; i ++)
+                    {
+                        using (var pointSizeValue = pointSizeArray[i])
+                        using (var minLineSizeValue = minLineSizeArray[i])
+                        {
+                            minLineSizeValue.Get(out float minLineSize);
+                            pointSizeValue.Get(out float pointSize);
+                            textFitArray.OptionList.Add(new TextFitArrayOption(pointSize, minLineSize));
+                        }
+                    }
+                }
+            }
+            return textFitArray;
+        }
+
 #if PROFILE_TV
         private const float FontSizeScaleSmall = 0.8f;
         private const float FontSizeScaleNormal = 1.0f;
index dc6d731488b0c5ac28c8456bf10e358ac22b5a5d..a2116aff02eb0cdd2b2d746d2870abd9bf215957 100755 (executable)
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
 using Tizen.NUI;
 using Tizen.NUI.BaseComponents;
 using Tizen.NUI.Components;
@@ -8,10 +9,13 @@ namespace Tizen.NUI.Samples
     public class TextFitChangedSample : IExample
     {
         private TextLabel label;
+        private TextLabel labelFitArray;
 
         public void Activate()
         {
             Window window = NUIApplication.GetDefaultWindow();
+
+            // TextFit
             var fit = new TextFit();
             fit.Enable = true;
             fit.MinSize = 5.0f;
@@ -34,6 +38,39 @@ namespace Tizen.NUI.Samples
                 TextFit textfit = label.GetTextFit();
                 Tizen.Log.Error("NUI", $"FontSize : {textfit.FontSize}\n");
             };
+
+            // TextFitArray
+            labelFitArray = new TextLabel()
+            {
+                Text = "ABCDE",
+                Size = new Size(300, 100),
+                PointSize = 10,
+                Position = new Position(100, 250),
+                BackgroundColor = Color.Yellow,
+            };
+            window.Add(labelFitArray);
+
+            var textFitArray = new Tizen.NUI.Text.TextFitArray();
+            textFitArray.Enable = true;
+            textFitArray.OptionList = new List<Tizen.NUI.Text.TextFitArrayOption>()
+            {
+                new Tizen.NUI.Text.TextFitArrayOption(5, 10),
+                new Tizen.NUI.Text.TextFitArrayOption(10, 15),
+                new Tizen.NUI.Text.TextFitArrayOption(15, 15),
+                new Tizen.NUI.Text.TextFitArrayOption(20, 25),
+                new Tizen.NUI.Text.TextFitArrayOption(50, 70),
+                new Tizen.NUI.Text.TextFitArrayOption(60, 70),
+                new Tizen.NUI.Text.TextFitArrayOption(70, 70),
+            };
+            labelFitArray.SetTextFitArray(textFitArray);
+
+            var getFitArray = labelFitArray.GetTextFitArray();
+
+            Tizen.Log.Error("NUI", $"GetTextFitArray:enable:[{getFitArray.Enable}] \n");
+            for (int i = 0 ; i < getFitArray.OptionList.Count ; i ++)
+            {
+                Tizen.Log.Error("NUI", $"GetTextFitArray:option:[{getFitArray.OptionList[i].PointSize}, {getFitArray.OptionList[i].MinLineSize}] \n");
+            }
         }
 
         public void Deactivate()