[NUI] Add ControlStateTypeConverter for xaml (#2002)
authorYeongJong Lee <cleanlyj@naver.com>
Wed, 23 Sep 2020 03:24:33 +0000 (12:24 +0900)
committerGitHub <noreply@github.com>
Wed, 23 Sep 2020 03:24:33 +0000 (12:24 +0900)
* [NUI] rename from StateValuePair to SelectorItem

* [NUI] add ControlStateTypeConverter for xaml

Custom ConstrolState is now available in xaml.

 ### Sample
XamlPage.xaml
```xaml
<View x:Class="NUIXamlTemplate1.XamlPage"
      xmlns="http://tizen.org/Tizen.NUI/2018/XAML"
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      xmlns:c="clr-namespace:Tizen.NUI.Components;assembly=Tizen.NUI.Components"
      xmlns:local="clr-namespace:NUIXamlTemplate1">
    <local:MyButton x:Name="MyButton">
        <x:Arguments>
            <c:ButtonStyle Size="100, 100">
                <c:ButtonStyle.BackgroundColor>
                    <Selector x:TypeArguments="Color" Normal="1, 1, 0, 1" Pressed="0.77, 0.88, 1, 1" Disabled="0.88, 0.88, 0.88, 1">
                        <SelectorItem x:TypeArguments="Color" State="MyState" Value="0,0,1,1" />
                        <SelectorItem x:TypeArguments="Color" State="MyState,Focused" Value="0,1,1,1" />
                    </Selector>
                </c:ButtonStyle.BackgroundColor>
            </c:ButtonStyle>
        </x:Arguments>
    </local:MyButton>
</View>
```

MyButton.cs
```cs
public class MyButton : Button
{
    public MyButton(ButtonStyle buttonStyle) : base(buttonStyle) {}
    public void SetControlState(ControlState s) => ControlState = s;
}
```

```cs
protected override void OnCreate()
{
    base.OnCreate();
    Window.Instance.BackgroundColor = new Color(227 / 255f, 255 / 255f, 227 / 255f, 1.0f);
    Window.Instance.KeyEvent += OnKeyEvent;

    View root = new View();
    root.WidthSpecification = LayoutParamPolicies.MatchParent;
    root.HeightSpecification = LayoutParamPolicies.MatchParent;
    root.Layout = new AbsoluteLayout();
    Window.Instance.GetDefaultLayer().Add(root);

    XamlPage xamlPage = new XamlPage();
    root.Add(xamlPage);

    ControlState MyState = ControlState.Create("MyState");

    Button button = new Button() { Position2D = new Position2D(100, 100) };
    bool flag = false;
    button.Clicked += (object sender, ClickedEventArgs e) =>
    {
        if (!flag)
        {
            xamlPage.MyButton.SetControlState(MyState);
            flag = true;
        }
        else
        {
            xamlPage.MyButton.SetControlState(ControlState.Focused + MyState);
            flag = false;
        }
    };
    root.Add(button);
}
```

Co-authored-by: dongsug-song <35130733+dongsug-song@users.noreply.github.com>
src/Tizen.NUI/src/public/BaseComponents/ControlState.cs
src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs

index 5d60fc1..cfbbfb1 100644 (file)
@@ -26,6 +26,7 @@ namespace Tizen.NUI.BaseComponents
     /// Class for describing the states of the view.
     /// </summary>
     [EditorBrowsable(EditorBrowsableState.Never)]
+    [Binding.TypeConverter(typeof(ControlStateTypeConverter))]
     public class ControlState : IEquatable<ControlState>
     {
         private static readonly Dictionary<string, ControlState> stateDictionary = new Dictionary<string, ControlState>();
@@ -90,12 +91,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public bool IsCombined => stateList.Count > 1;
 
-        /// <summary>
-        /// Default Contructor. Please use <see cref="Create(string)"/> or <see cref="Create(ControlState[])"/> instead.
-        /// </summary>
-        // Do not open this constructor. This is only for xaml support.
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public ControlState() { }
+        private ControlState() { }
 
         private ControlState(string name) : this() => this.name = name;
 
@@ -259,7 +255,7 @@ namespace Tizen.NUI.BaseComponents
             {
                 return ReferenceEquals(lhs, rhs) ? Normal : lhs;
             }
-            
+
             var rest = lhs.stateList.Except(rhs.stateList);
 
             if (rest.Count() == 0)
@@ -276,76 +272,26 @@ namespace Tizen.NUI.BaseComponents
             newState.stateList.AddRange(rest);
             return newState;
         }
-    }
 
-    /// <summary>
-    /// The Key/Value pair structure. this is mutable to support for xaml.
-    /// </summary>
-    [EditorBrowsable(EditorBrowsableState.Never)]
-    public struct StateValuePair<T> : IEquatable<StateValuePair<T>>
-    {
-        /// <summary>
-        /// The constructor with the specified state and value.
-        /// </summary>
-        /// <param name="state">The state</param>
-        /// <param name="value">The value associated with state.</param>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public StateValuePair(ControlState state, T value)
+        class ControlStateTypeConverter : Binding.TypeConverter
         {
-            State = state;
-            Value = value;
-        }
-
-        /// <summary>
-        /// The state
-        /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public ControlState State { get; set; }
-        /// <summary>
-        /// The value associated with state.
-        /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public T Value { get; set; }
-
-        ///  <inheritdoc/>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public bool Equals(StateValuePair<T> other) => (Value.Equals(other.Value)) && (State == other.State);
+            public override object ConvertFromInvariantString(string value)
+            {
+                if (value != null)
+                {
+                    value = value.Trim();
 
-        ///  <inheritdoc/>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override bool Equals(object obj)
-        {
-            if (!(obj is StateValuePair<T>))
-                return false;
+                    ControlState convertedState = new ControlState();
+                    string[] parts = value.Split(',');
+                    foreach (string part in parts)
+                    {
+                        convertedState += Create(part);
+                    }
+                    return convertedState;
+                }
 
-            return Equals((StateValuePair<T>)obj);
+                throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(ControlState)}");
+            }
         }
-
-        ///  <inheritdoc/>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override int GetHashCode() => (State.GetHashCode() * 397) ^ Value.GetHashCode();
-
-
-        /// <summary>
-        /// Compares whether the two StateValuePair are different or not.
-        /// </summary>
-        /// <param name="lhs">A <see cref="StateValuePair{T}"/> on the left hand side.</param>
-        /// <param name="rhs">A <see cref="StateValuePair{T}"/> on the right hand side.</param>
-        /// <returns>true if the StateValuePair are equal; otherwise, false.</returns>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public static bool operator ==(StateValuePair<T> lhs, StateValuePair<T> rhs) => lhs.Equals(rhs);
-
-        /// <summary>
-        /// Compares whether the two StateValuePair are same or not.
-        /// </summary>
-        /// <param name="lhs">A <see cref="StateValuePair{T}"/> on the left hand side.</param>
-        /// <param name="rhs">A <see cref="StateValuePair{T}"/> on the right hand side.</param>
-        /// <returns>true if the StateValuePair are not equal; otherwise, false.</returns>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public static bool operator !=(StateValuePair<T> lhs, StateValuePair<T> rhs) => !(lhs == rhs);
-
-        ///  <inheritdoc/>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override string ToString() => $"[{State}, {Value}]";
     }
 }
\ No newline at end of file
index 8b155fe..7f67f83 100755 (executable)
@@ -36,7 +36,7 @@ namespace Tizen.NUI.BaseComponents
         /// The list for adding state-value pair.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public IList<StateValuePair<T>> StateValueList { get; private set; } = new List<StateValuePair<T>>();
+        public IList<SelectorItem<T>> StateValueList { get; private set; } = new List<SelectorItem<T>>();
 
         /// <summary>
         /// Adds the specified state and value to the <see cref="StateValueList"/>.
@@ -44,14 +44,14 @@ namespace Tizen.NUI.BaseComponents
         /// <param name="state">The state.</param>
         /// <param name="value">The value associated with state.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public void Add(ControlState state, T value) => StateValueList.Add(new StateValuePair<T>(state, value));
+        public void Add(ControlState state, T value) => StateValueList.Add(new SelectorItem<T>(state, value));
 
         /// <summary>
         /// Adds the specified state and value to the <see cref="StateValueList"/>.
         /// </summary>
         /// <param name="stateValuePair"></param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public void Add(StateValuePair<T> stateValuePair) => StateValueList.Add(stateValuePair);
+        public void Add(SelectorItem<T> stateValuePair) => StateValueList.Add(stateValuePair);
 
         /// <since_tizen> 6 </since_tizen>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
@@ -100,7 +100,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Normal
         {
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.Normal).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.Normal).Value;
             set => Add(ControlState.Normal, value);
         }
         /// <summary>
@@ -112,7 +112,7 @@ namespace Tizen.NUI.BaseComponents
         public T Pressed
         {
 
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.Pressed).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.Pressed).Value;
             set => Add(ControlState.Pressed, value);
         }
         /// <summary>
@@ -123,7 +123,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Focused
         {
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.Focused).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.Focused).Value;
             set => Add(ControlState.Focused, value);
         }
         /// <summary>
@@ -134,7 +134,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Selected
         {
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.Selected).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.Selected).Value;
             set => Add(ControlState.Selected, value);
         }
         /// <summary>
@@ -146,7 +146,7 @@ namespace Tizen.NUI.BaseComponents
         public T Disabled
         {
 
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.Disabled).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.Disabled).Value;
             set => Add(ControlState.Disabled, value);
         }
         /// <summary>
@@ -157,7 +157,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T DisabledFocused
         {
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.DisabledFocused).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.DisabledFocused).Value;
             set => Add(ControlState.DisabledFocused, value);
         }
         /// <summary>
@@ -167,7 +167,7 @@ namespace Tizen.NUI.BaseComponents
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         public T SelectedFocused
         {
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.SelectedFocused).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.SelectedFocused).Value;
             set => Add(ControlState.SelectedFocused, value);
         }
         /// <summary>
@@ -179,7 +179,7 @@ namespace Tizen.NUI.BaseComponents
         public T DisabledSelected
         {
 
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.DisabledSelected).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.DisabledSelected).Value;
             set => Add(ControlState.DisabledSelected, value);
         }
 
@@ -191,7 +191,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Other
         {
-            get => ((List<StateValuePair<T>>)StateValueList).FindLast(x => x.State == ControlState.Other).Value;
+            get => ((List<SelectorItem<T>>)StateValueList).FindLast(x => x.State == ControlState.Other).Value;
             set => Add(ControlState.Other, value);
         }
         /// <summary>
@@ -212,7 +212,7 @@ namespace Tizen.NUI.BaseComponents
 
             result = default;
 
-            int index = ((List<StateValuePair<T>>)StateValueList).FindLastIndex(x => x.State == state);
+            int index = ((List<SelectorItem<T>>)StateValueList).FindLastIndex(x => x.State == state);
             if (index >= 0)
             {
                 result = StateValueList[index].Value;
@@ -221,7 +221,7 @@ namespace Tizen.NUI.BaseComponents
 
             if (state.IsCombined)
             {
-                index = ((List<StateValuePair<T>>)StateValueList).FindLastIndex(x => state.Contains(x.State));
+                index = ((List<SelectorItem<T>>)StateValueList).FindLastIndex(x => state.Contains(x.State));
                 if (index >= 0)
                 {
                     result = StateValueList[index].Value;
@@ -229,7 +229,7 @@ namespace Tizen.NUI.BaseComponents
                 }
             }
 
-            index = ((List<StateValuePair<T>>)StateValueList).FindLastIndex(x => x.State == ControlState.Other);
+            index = ((List<SelectorItem<T>>)StateValueList).FindLastIndex(x => x.State == ControlState.Other);
             if (index >= 0)
             {
                 result = StateValueList[index].Value;
@@ -286,12 +286,12 @@ namespace Tizen.NUI.BaseComponents
             if (cloneable)
             {
                 All = (T)((ICloneable)other.All)?.Clone();
-                StateValueList = ((List<StateValuePair<T>>)other.StateValueList).ConvertAll(m => new StateValuePair<T>(m.State, (T)((ICloneable)m.Value)?.Clone()));
+                StateValueList = ((List<SelectorItem<T>>)other.StateValueList).ConvertAll(m => new SelectorItem<T>(m.State, (T)((ICloneable)m.Value)?.Clone()));
             }
             else
             {
                 All = other.All;
-                StateValueList = ((List<StateValuePair<T>>)other.StateValueList).ConvertAll(m => m);
+                StateValueList = ((List<SelectorItem<T>>)other.StateValueList).ConvertAll(m => m);
             }
         }
 
@@ -427,6 +427,48 @@ namespace Tizen.NUI.BaseComponents
         }
     }
 
+
+    /// <summary>
+    /// The selector item that have Key-Value pair. it can be added to <see cref="Selector{T}.StateValueList"/>.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class SelectorItem<T>
+    {
+        /// <summary>
+        /// The default constructor.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public SelectorItem() {}
+
+        /// <summary>
+        /// The constructor with the specified state and value.
+        /// </summary>
+        /// <param name="state">The state</param>
+        /// <param name="value">The value associated with state.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public SelectorItem(ControlState state, T value)
+        {
+            State = state;
+            Value = value;
+        }
+
+        /// <summary>
+        /// The state
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public ControlState State { get; set; }
+
+        /// <summary>
+        /// The value associated with state.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public T Value { get; set; }
+
+        ///  <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override string ToString() => $"[{State}, {Value}]";
+    }
+
     /// <summary>
     /// Extension class for <see cref="Selector{T}"/>.
     /// </summary>
@@ -440,9 +482,9 @@ namespace Tizen.NUI.BaseComponents
         /// <param name="state">The state.</param>
         /// <param name="value">The value associated with state.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static void Add<T>(this IList<StateValuePair<T>> list, ControlState state, T value)
+        public static void Add<T>(this IList<SelectorItem<T>> list, ControlState state, T value)
         {
-            list.Add(new StateValuePair<T>(state, value));
+            list.Add(new SelectorItem<T>(state, value));
         }
     }
 }