/* * Copyright(c) 2020 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace Tizen.NUI.BaseComponents { /// /// Class for describing the states of the view. /// [EditorBrowsable(EditorBrowsableState.Never)] public class ControlState : IEquatable { private static readonly Dictionary stateDictionary = new Dictionary(); //Default States /// /// All State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState All = Create("All"); /// /// Normal State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState Normal = Create("Normal"); /// /// Focused State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState Focused = Create("Focused"); /// /// Pressed State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState Pressed = Create("Pressed"); /// /// Disabled State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState Disabled = Create("Disabled"); /// /// Selected State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState Selected = Create("Selected"); /// /// DisabledSelected State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState DisabledSelected = Disabled + Selected; /// /// DisabledFocused State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState DisabledFocused = Disabled + Focused; /// /// SelectedFocused State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState SelectedFocused = Selected + Focused; /// /// Other State. /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly ControlState Other = Create("Other"); private List stateList = new List(); private readonly string name = ""; /// /// Gets or sets a value indicating whether it has combined states. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool IsCombined => stateList.Count > 1; /// /// Default Contructor. Please use or instead. /// // Do not open this constructor. This is only for xaml support. [EditorBrowsable(EditorBrowsableState.Never)] public ControlState() { } private ControlState(string name) : this() => this.name = name; /// /// Create an instance of the with state name. /// /// The state name. /// The instance which has single state. [EditorBrowsable(EditorBrowsableState.Never)] public static ControlState Create(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("name cannot be empty string", nameof(name)); if (stateDictionary.TryGetValue(name, out ControlState state)) return state; state = new ControlState(name); state.stateList.Add(state); stateDictionary.Add(name, state); return state; } /// /// Create an instance of the with combined states. /// /// The control state array. /// The instance which has combined state. [EditorBrowsable(EditorBrowsableState.Never)] public static ControlState Create(params ControlState[] states) { if (states.Length == 1) return states[0]; ControlState newState = new ControlState(); for (int i = 0; i < states.Length; i++) { if (states[i] == Normal) continue; if (states[i] == All) return All; newState.stateList.AddRange(states[i].stateList); } if (newState.stateList.Count == 0) return Normal; newState.stateList = newState.stateList.Distinct().ToList(); if (newState.stateList.Count == 1) { return newState.stateList[0]; } return newState; } /// /// Determines whether a state contains a specified state. /// /// The state to search for /// true if the state contain a specified state, otherwise, false. [EditorBrowsable(EditorBrowsableState.Never)] public bool Contains(ControlState state) { if (state == null) throw new ArgumentNullException(nameof(state)); if (!IsCombined) return ReferenceEquals(this, state); bool found; for (int i = 0; i < state.stateList.Count; i++) { found = false; for (int j = 0; j < stateList.Count; j++) { if (ReferenceEquals(state.stateList[i], stateList[j])) { found = true; break; } } if (!found) return false; } return true; } /// [EditorBrowsable(EditorBrowsableState.Never)] public bool Equals(ControlState other) { if (other is null || stateList.Count != other.stateList.Count) return false; return Contains(other); } /// [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object obj) => this.Equals(obj as ControlState); /// [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => (name.GetHashCode() * 397) ^ IsCombined.GetHashCode(); /// [EditorBrowsable(EditorBrowsableState.Never)] public override string ToString() { string name = ""; for (int i = 0; i < stateList.Count; i++) { name += ((i == 0) ? "" : ", ") + stateList[i].name; } return name; } /// /// Compares whether the two ControlStates are same or not. /// /// A on the left hand side. /// A on the right hand side. /// true if the ControlStates are equal; otherwise, false. [EditorBrowsable(EditorBrowsableState.Never)] public static bool operator ==(ControlState lhs, ControlState rhs) => lhs.Equals(rhs); /// /// Compares whether the two ControlStates are different or not. /// /// A on the left hand side. /// A on the right hand side. /// true if the ControlStates are not equal; otherwise, false. [EditorBrowsable(EditorBrowsableState.Never)] public static bool operator !=(ControlState lhs, ControlState rhs) => !lhs.Equals(rhs); /// /// The addition operator. /// /// A on the left hand side. /// A on the right hand side. /// The containing the result of the addition. [EditorBrowsable(EditorBrowsableState.Never)] public static ControlState operator +(ControlState lhs, ControlState rhs) => Create(lhs, rhs); /// /// The substraction operator. /// /// A on the left hand side. /// A on the right hand side. /// The containing the result of the substraction. [EditorBrowsable(EditorBrowsableState.Never)] public static ControlState operator -(ControlState lhs, ControlState rhs) { if (!lhs.IsCombined) { return ReferenceEquals(lhs, rhs) ? Normal : lhs; } var rest = lhs.stateList.Except(rhs.stateList); if (rest.Count() == 0) { return Normal; } if (rest.Count() == 1) { return rest.First(); } ControlState newState = new ControlState(); newState.stateList.AddRange(rest); return newState; } } /// /// The Key/Value pair structure. this is mutable to support for xaml. /// [EditorBrowsable(EditorBrowsableState.Never)] public struct StateValuePair : IEquatable> { /// /// The constructor with the specified state and value. /// /// The state /// The value associated with state. [EditorBrowsable(EditorBrowsableState.Never)] public StateValuePair(ControlState state, T value) { State = state; Value = value; } /// /// The state /// [EditorBrowsable(EditorBrowsableState.Never)] public ControlState State { get; set; } /// /// The value associated with state. /// [EditorBrowsable(EditorBrowsableState.Never)] public T Value { get; set; } /// [EditorBrowsable(EditorBrowsableState.Never)] public bool Equals(StateValuePair other) => (Value.Equals(other.Value)) && (State == other.State); /// [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object obj) { if (!(obj is StateValuePair)) return false; return Equals((StateValuePair)obj); } /// [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => (State.GetHashCode() * 397) ^ Value.GetHashCode(); /// /// Compares whether the two StateValuePair are different or not. /// /// A on the left hand side. /// A on the right hand side. /// true if the StateValuePair are equal; otherwise, false. [EditorBrowsable(EditorBrowsableState.Never)] public static bool operator ==(StateValuePair lhs, StateValuePair rhs) => lhs.Equals(rhs); /// /// Compares whether the two StateValuePair are same or not. /// /// A on the left hand side. /// A on the right hand side. /// true if the StateValuePair are not equal; otherwise, false. [EditorBrowsable(EditorBrowsableState.Never)] public static bool operator !=(StateValuePair lhs, StateValuePair rhs) => !(lhs == rhs); /// [EditorBrowsable(EditorBrowsableState.Never)] public override string ToString() => $"[{State}, {Value}]"; } }