/*
- * 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
{
/// <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 isCloneable = typeof(ICloneable).IsAssignableFrom(typeof(T));
+ 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.
public static implicit operator Selector<T>(T value)
[EditorBrowsable(EditorBrowsableState.Never)]
public Selector(T value) : this()
{
- All = isCloneable ? (T)((ICloneable)value)?.Clone() : value;
+ All = cloneable ? (T)((ICloneable)value)?.Clone() : value;
}
/// Copy constructor
Clone(value);
}
- internal Selector(SelectorChangedCallback<T> cb) : this()
- {
- callback = cb;
- }
-
- internal Selector(SelectorChangedCallback<T> cb, T value) : this(value)
- {
- callback = cb;
- }
-
- internal Selector(SelectorChangedCallback<T> cb, Selector<T> value) : this(value)
- {
- callback = cb;
- }
-
- internal delegate void SelectorChangedCallback<T>(Selector<T> value);
- private SelectorChangedCallback<T> callback = null;
-
/// <summary>
/// All State.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public T Normal
{
- get
- {
- return Find(x => x.State == ControlState.Normal).Value;
- }
- set
- {
- Add(ControlState.Normal, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.Normal).Value;
+ set => Add(ControlState.Normal, value);
}
/// <summary>
/// Pressed State.
[EditorBrowsable(EditorBrowsableState.Never)]
public T Pressed
{
- get
- {
- return Find(x => x.State == ControlState.Pressed).Value;
- }
- set
- {
- Add(ControlState.Pressed, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.Pressed).Value;
+ set => Add(ControlState.Pressed, value);
}
/// <summary>
/// Focused State.
[EditorBrowsable(EditorBrowsableState.Never)]
public T Focused
{
- get
- {
- return Find(x => x.State == ControlState.Focused).Value;
- }
- set
- {
- Add(ControlState.Focused, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.Focused).Value;
+ set => Add(ControlState.Focused, value);
}
/// <summary>
/// Selected State.
[EditorBrowsable(EditorBrowsableState.Never)]
public T Selected
{
- get
- {
- return Find(x => x.State == ControlState.Selected).Value;
- }
- set
- {
- Add(ControlState.Selected, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.Selected).Value;
+ set => Add(ControlState.Selected, value);
}
/// <summary>
/// Disabled State.
[EditorBrowsable(EditorBrowsableState.Never)]
public T Disabled
{
- get
- {
- return Find(x => x.State == ControlState.Disabled).Value;
- }
- set
- {
- Add(ControlState.Disabled, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.Disabled).Value;
+ set => Add(ControlState.Disabled, value);
}
/// <summary>
/// DisabledFocused State.
[EditorBrowsable(EditorBrowsableState.Never)]
public T DisabledFocused
{
- get
- {
- return Find(x => x.State == ControlState.DisabledFocused).Value;
- }
- set
- {
- Add(ControlState.DisabledFocused, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.DisabledFocused).Value;
+ set => Add(ControlState.DisabledFocused, value);
}
/// <summary>
/// SelectedFocused State.
/// 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
- {
- return Find(x => x.State == ControlState.SelectedFocused).Value;
- }
- set
- {
- Add(ControlState.SelectedFocused, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.SelectedFocused).Value;
+ set => Add(ControlState.SelectedFocused, value);
}
/// <summary>
/// DisabledSelected State.
[EditorBrowsable(EditorBrowsableState.Never)]
public T DisabledSelected
{
- get
- {
- return Find(x => x.State == ControlState.DisabledSelected).Value;
- }
- set
- {
- Add(ControlState.DisabledSelected, value);
- callback?.Invoke(this);
- }
+ get => SelectorItems.Find(x => x.State == ControlState.DisabledSelected).Value;
+ set => Add(ControlState.DisabledSelected, value);
}
/// <summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public T Other
{
- get
- {
- return Find(x => x.State == ControlState.Other).Value;
- }
- set
- {
- Add(ControlState.Other, value);
- callback?.Invoke(this);
- }
+ 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>
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/>
{
string result = $"[All, {All}]";
- foreach (var item in StateValueList)
+ foreach (var item in SelectorItems)
{
result += $", {item}";
}
/// <summary>
/// Clone itself.
- /// If type T implements ISelectorItem, it calls Clone() method to clone values, otherwise use operator=.
+ /// If type T implements ICloneable, it calls Clone() method to clone values, otherwise use operator=.
/// </summary>
/// <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.
}
/// <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 (isCloneable)
+ 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;
}
}
/// <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;
/// <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();
[EditorBrowsable(EditorBrowsableState.Never)]
public void Reset(View view)
{
- view.ControlStateChangeEventInternal -= OnViewControlState;
+ if (view != null)
+ {
+ view.ControlStateChangeEventInternal -= OnViewControlState;
+ }
selector?.Clear();
selector = null;
dirty = false;
}
}
}
+
+ /// <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));
+ }
+ }
}