[NUI] Add license, delete unnecessary code(public)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / Style / Selector.cs
index ebf5b1f..34c44a6 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2021 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.
  *
  */
 using System;
+using System.Collections.Generic;
 using System.ComponentModel;
 using Tizen.NUI.Binding;
-using Tizen.NUI.Components;
 
 namespace Tizen.NUI.BaseComponents
 {
     /// <summary>
     /// Selector class, which is related by Control State, it is base class for other Selector.
     /// </summary>
+    /// <typeparam name="T">The property type of the selector. if it's reference type, it should be of type <see cref="ICloneable"/> that implement deep copy in <see cref="ICloneable.Clone"/>.</typeparam>
     /// <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.
     [EditorBrowsable(EditorBrowsableState.Never)]
-    public class Selector<T> : StateValueCollection<T>
+    public class Selector<T>
     {
-        private readonly bool cloneable = typeof(T).IsAssignableFrom(typeof(ICloneable));
+        private readonly bool cloneable = typeof(ICloneable).IsAssignableFrom(typeof(T));
+
+        /// <summary>
+        /// The list for adding <see cref="SelectorItem{T}"/>.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        List<SelectorItem<T>> SelectorItems { get; set; } = new List<SelectorItem<T>>();
+
+        /// <summary>
+        /// Adds the specified state and value to the <see cref="SelectorItems"/>.
+        /// </summary>
+        /// <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)
+        {
+            SelectorItems.Add(new SelectorItem<T>(state, value));
+            All = default;
+        }
+
+        /// <summary>
+        /// Adds the specified state and value to the <see cref="SelectorItems"/>.
+        /// </summary>
+        /// <param name="selectorItem">The selector item class that stores a state-value pair.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void Add(SelectorItem<T> selectorItem)
+        {
+            // To prevent a state from having multiple values, remove existing state-value pair.
+            int index = SelectorItems.FindIndex(x => x.State == selectorItem.State);
+            if (index != -1)
+                SelectorItems.RemoveAt(index);
+
+            SelectorItems.Add(selectorItem);
+        }
 
         /// <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.
@@ -58,7 +92,6 @@ namespace Tizen.NUI.BaseComponents
             Clone(value);
         }
 
-
         /// <summary>
         /// All State.
         /// </summary>
@@ -78,7 +111,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Normal
         {
-            get => Find(x => x.State == ControlState.Normal).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.Normal).Value;
             set => Add(ControlState.Normal, value);
         }
         /// <summary>
@@ -89,7 +122,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Pressed
         {
-            get => Find(x => x.State == ControlState.Pressed).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.Pressed).Value;
             set => Add(ControlState.Pressed, value);
         }
         /// <summary>
@@ -100,7 +133,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Focused
         {
-            get => Find(x => x.State == ControlState.Focused).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.Focused).Value;
             set => Add(ControlState.Focused, value);
         }
         /// <summary>
@@ -111,7 +144,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Selected
         {
-            get => Find(x => x.State == ControlState.Selected).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.Selected).Value;
             set => Add(ControlState.Selected, value);
         }
         /// <summary>
@@ -122,7 +155,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Disabled
         {
-            get => Find(x => x.State == ControlState.Disabled).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.Disabled).Value;
             set => Add(ControlState.Disabled, value);
         }
         /// <summary>
@@ -133,7 +166,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T DisabledFocused
         {
-            get => Find(x => x.State == ControlState.DisabledFocused).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.DisabledFocused).Value;
             set => Add(ControlState.DisabledFocused, value);
         }
         /// <summary>
@@ -143,7 +176,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 => Find(x => x.State == ControlState.SelectedFocused).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.SelectedFocused).Value;
             set => Add(ControlState.SelectedFocused, value);
         }
         /// <summary>
@@ -154,7 +187,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T DisabledSelected
         {
-            get => Find(x => x.State == ControlState.DisabledSelected).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.DisabledSelected).Value;
             set => Add(ControlState.DisabledSelected, value);
         }
 
@@ -166,12 +199,20 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Other
         {
-            get => Find(x => x.State == ControlState.Other).Value;
+            get => SelectorItems.Find(x => x.State == ControlState.Other).Value;
             set => Add(ControlState.Other, value);
         }
+
+        /// <summary>
+        /// Gets the number of elements.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public int Count => SelectorItems.Count;
+
         /// <summary>
         /// Get value by State.
         /// </summary>
+        /// <exception cref="ArgumentNullException"> Thrown when state is null. </exception>
         /// <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.
         /// <returns>True if the selector has a given state value, false otherwise.</returns>
@@ -185,41 +226,50 @@ namespace Tizen.NUI.BaseComponents
                 return true;
             }
 
+            if (state == null)
+                throw new ArgumentNullException(nameof(state));
+
             result = default;
 
-            int index = StateValueList.FindIndex(x => x.State == state);
+            int index = SelectorItems.FindIndex(x => x.State == state);
             if (index >= 0)
             {
-                result = StateValueList[index].Value;
+                result = SelectorItems[index].Value;
                 return true;
             }
 
+            if (null == state)
+            {
+                throw new ArgumentNullException(nameof(state));
+            }
             if (state.IsCombined)
             {
-                index = StateValueList.FindIndex(x => state.Contains(x.State));
+                index = SelectorItems.FindIndex(x => state.Contains(x.State));
                 if (index >= 0)
                 {
-                    result = StateValueList[index].Value;
+                    result = SelectorItems[index].Value;
                     return true;
                 }
             }
 
-            index = StateValueList.FindIndex(x => x.State == ControlState.Other);
+            index = SelectorItems.FindIndex(x => x.State == ControlState.Other);
             if (index >= 0)
             {
-                result = StateValueList[index].Value;
+                result = SelectorItems[index].Value;
                 return true;
             }
 
             return false;
         }
 
-        /// <inheritdoc/>
+        /// <summary>
+        /// Removes all elements.
+        /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public override void Clear()
+        public void Clear()
         {
             All = default;
-            base.Clear();
+            SelectorItems.Clear();
         }
 
         /// <inheritdoc/>
@@ -228,7 +278,7 @@ namespace Tizen.NUI.BaseComponents
         {
             string result = $"[All, {All}]";
 
-            foreach (var item in StateValueList)
+            foreach (var item in SelectorItems)
             {
                 result += $", {item}";
             }
@@ -251,34 +301,48 @@ namespace Tizen.NUI.BaseComponents
         }
 
         /// <summary>
+        /// Clone with type converter.
+        /// </summary>
+        /// <exception cref="ArgumentNullException"> Thrown when converter is null. </exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Selector<TOut> Clone<TOut>(Converter<T, TOut> converter)
+        {
+            if (converter == null) throw new ArgumentNullException(nameof(converter));
+
+            Selector<TOut> result = new Selector<TOut>();
+            result.All = converter(All);
+            result.SelectorItems = SelectorItems.ConvertAll<SelectorItem<TOut>>(m => new SelectorItem<TOut>(m.State, converter(m.Value)));
+
+            return result;
+        }
+
+        /// <summary>
         /// Copy values from other selector.
         /// </summary>
+        /// <exception cref="ArgumentNullException"> Thrown when other is null. </exception>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void Clone(Selector<T> other)
         {
-            Clear();
+            if (null == other)
+            {
+                throw new ArgumentNullException(nameof(other));
+            }
 
             if (cloneable)
             {
                 All = (T)((ICloneable)other.All)?.Clone();
-                foreach (var item in other.StateValueList)
-                {
-                    AddWithoutCheck(new StateValuePair<T>(item.State, (T)((ICloneable)item.Value)?.Clone()));
-                }
+                SelectorItems = other.SelectorItems.ConvertAll(m => new SelectorItem<T>(m.State, (T)((ICloneable)m.Value)?.Clone()));
             }
             else
             {
                 All = other.All;
-                foreach (var item in other.StateValueList)
-                {
-                    AddWithoutCheck(item);
-                }
+                SelectorItems = other.SelectorItems.ConvertAll(m => m);
             }
         }
 
         internal bool HasMultiValue()
         {
-            return StateValueList.Count > 1;
+            return SelectorItems.Count > 1;
         }
     }
 
@@ -314,10 +378,15 @@ namespace Tizen.NUI.BaseComponents
         /// <summary>
         /// Return the containing selector. It can be null.
         /// </summary>
+        /// <exception cref="ArgumentNullException"> Thrown when view is null. </exception>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public Selector<T> Get(View view)
         {
             if (!dirty) return selector;
+            if (null == view)
+            {
+                throw new ArgumentNullException(nameof(view));
+            }
 
             T value = default;
 
@@ -342,14 +411,20 @@ namespace Tizen.NUI.BaseComponents
         /// <param name="view">The View that is affected by this TriggerableSelector.</param>
         /// <param name="otherSelector">The copy target.</param>
         /// <param name="updateView">Whether it updates the target view after update the selector or not.</param>
+        /// <exception cref="ArgumentNullException"> Thrown when view is null. </exception>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void Update(View view, Selector<T> otherSelector, bool updateView = false)
         {
             Reset(view);
 
+            if (null == view)
+            {
+                throw new ArgumentNullException(nameof(view));
+            }
+
             if (otherSelector == null)
             {
-                return;   
+                return;
             }
 
             selector = otherSelector.Clone();
@@ -392,7 +467,10 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void Reset(View view)
         {
-            view.ControlStateChangeEventInternal -= OnViewControlState;
+            if (view != null)
+            {
+                view.ControlStateChangeEventInternal -= OnViewControlState;
+            }
             selector?.Clear();
             selector = null;
             dirty = false;
@@ -407,4 +485,67 @@ namespace Tizen.NUI.BaseComponents
             }
         }
     }
+
+    /// <summary>
+    /// The selector item class that stores a state-value pair.
+    /// </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>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public static class SelectorExtensions
+    {
+        /// <summary>
+        /// Adds the specified state and value to the <see cref="Selector{T}.SelectorItems"/>.
+        /// </summary>
+        /// <param name="list">The list for adding state-value pair.</param>
+        /// <param name="state">The state.</param>
+        /// <param name="value">The value associated with state.</param>
+        /// <exception cref="ArgumentNullException"> Thrown when given list is null. </exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static void Add<T>(this IList<SelectorItem<T>> list, ControlState state, T value)
+        {
+            if (list == null) throw new ArgumentNullException(nameof(list));
+
+            list.Add(new SelectorItem<T>(state, value));
+        }
+    }
 }