2 * Copyright(c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Collections.Generic;
20 using System.ComponentModel;
23 namespace Tizen.NUI.BaseComponents
26 /// Class for describing the states of the view.
28 [EditorBrowsable(EditorBrowsableState.Never)]
29 public class ControlState : IEquatable<ControlState>
31 private static readonly Dictionary<string, ControlState> stateDictionary = new Dictionary<string, ControlState>();
36 [EditorBrowsable(EditorBrowsableState.Never)]
37 public static readonly ControlState All = Create("All");
41 [EditorBrowsable(EditorBrowsableState.Never)]
42 public static readonly ControlState Normal = Create("Normal");
46 [EditorBrowsable(EditorBrowsableState.Never)]
47 public static readonly ControlState Focused = Create("Focused");
51 [EditorBrowsable(EditorBrowsableState.Never)]
52 public static readonly ControlState Pressed = Create("Pressed");
56 [EditorBrowsable(EditorBrowsableState.Never)]
57 public static readonly ControlState Disabled = Create("Disabled");
61 [EditorBrowsable(EditorBrowsableState.Never)]
62 public static readonly ControlState Selected = Create("Selected");
64 /// DisabledSelected State.
66 [EditorBrowsable(EditorBrowsableState.Never)]
67 public static readonly ControlState DisabledSelected = Disabled + Selected;
69 /// DisabledFocused State.
71 [EditorBrowsable(EditorBrowsableState.Never)]
72 public static readonly ControlState DisabledFocused = Disabled + Focused;
74 /// SelectedFocused State.
76 [EditorBrowsable(EditorBrowsableState.Never)]
77 public static readonly ControlState SelectedFocused = Selected + Focused;
81 [EditorBrowsable(EditorBrowsableState.Never)]
82 public static readonly ControlState Other = Create("Other");
84 private List<ControlState> stateList = new List<ControlState>();
85 private readonly string name = "";
88 /// Gets or sets a value indicating whether it has combined states.
90 [EditorBrowsable(EditorBrowsableState.Never)]
91 public bool IsCombined => stateList.Count > 1;
94 /// Default Contructor. Please use <see cref="Create(string)"/> or <see cref="Create(ControlState[])"/> instead.
96 // Do not open this constructor. This is only for xaml support.
97 [EditorBrowsable(EditorBrowsableState.Never)]
98 public ControlState() { }
100 private ControlState(string name) : this() => this.name = name;
103 /// Create an instance of the <see cref="ControlState"/> with state name.
105 /// <param name="name">The state name.</param>
106 /// <returns>The <see cref="ControlState"/> instance which has single state.</returns>
107 [EditorBrowsable(EditorBrowsableState.Never)]
108 public static ControlState Create(string name)
111 throw new ArgumentNullException(nameof(name));
112 if (string.IsNullOrWhiteSpace(name))
113 throw new ArgumentException("name cannot be empty string", nameof(name));
115 if (stateDictionary.TryGetValue(name, out ControlState state))
118 state = new ControlState(name);
119 state.stateList.Add(state);
120 stateDictionary.Add(name, state);
125 /// Create an instance of the <see cref="ControlState"/> with combined states.
127 /// <param name="states">The control state array.</param>
128 /// <returns>The <see cref="ControlState"/> instance which has combined state.</returns>
129 [EditorBrowsable(EditorBrowsableState.Never)]
130 public static ControlState Create(params ControlState[] states)
132 if (states.Length == 1)
135 ControlState newState = new ControlState();
136 for (int i = 0; i < states.Length; i++)
138 if (states[i] == Normal)
141 if (states[i] == All)
144 newState.stateList.AddRange(states[i].stateList);
147 if (newState.stateList.Count == 0)
150 newState.stateList = newState.stateList.Distinct().ToList();
152 if (newState.stateList.Count == 1)
154 return newState.stateList[0];
161 /// Determines whether a state contains a specified state.
163 /// <param name="state">The state to search for</param>
164 /// <returns>true if the state contain a specified state, otherwise, false.</returns>
165 [EditorBrowsable(EditorBrowsableState.Never)]
166 public bool Contains(ControlState state)
169 throw new ArgumentNullException(nameof(state));
172 return ReferenceEquals(this, state);
175 for (int i = 0; i < state.stateList.Count; i++)
178 for (int j = 0; j < stateList.Count; j++)
180 if (ReferenceEquals(state.stateList[i], stateList[j]))
186 if (!found) return false;
193 [EditorBrowsable(EditorBrowsableState.Never)]
194 public bool Equals(ControlState other)
196 if (other is null || stateList.Count != other.stateList.Count)
199 return Contains(other);
203 [EditorBrowsable(EditorBrowsableState.Never)]
204 public override bool Equals(object obj) => this.Equals(obj as ControlState);
207 [EditorBrowsable(EditorBrowsableState.Never)]
208 public override int GetHashCode() => (name.GetHashCode() * 397) ^ IsCombined.GetHashCode();
211 [EditorBrowsable(EditorBrowsableState.Never)]
212 public override string ToString()
215 for (int i = 0; i < stateList.Count; i++)
217 name += ((i == 0) ? "" : ", ") + stateList[i].name;
223 /// Compares whether the two ControlStates are same or not.
225 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
226 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
227 /// <returns>true if the ControlStates are equal; otherwise, false.</returns>
228 [EditorBrowsable(EditorBrowsableState.Never)]
229 public static bool operator ==(ControlState lhs, ControlState rhs)
231 // Check for null on left side.
236 // null == null = true.
240 // Only the left side is null.
243 // Equals handles case of null on right side.
244 return lhs.Equals(rhs);
248 /// Compares whether the two ControlStates are different or not.
250 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
251 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
252 /// <returns>true if the ControlStates are not equal; otherwise, false.</returns>
253 [EditorBrowsable(EditorBrowsableState.Never)]
254 public static bool operator !=(ControlState lhs, ControlState rhs) => !(lhs == rhs);
257 /// The addition operator.
259 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
260 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
261 /// <returns>The <see cref="ControlState"/> containing the result of the addition.</returns>
262 [EditorBrowsable(EditorBrowsableState.Never)]
263 public static ControlState operator +(ControlState lhs, ControlState rhs) => Create(lhs, rhs);
266 /// The substraction operator.
268 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
269 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
270 /// <returns>The <see cref="ControlState"/> containing the result of the substraction.</returns>
271 [EditorBrowsable(EditorBrowsableState.Never)]
272 public static ControlState operator -(ControlState lhs, ControlState rhs)
276 return ReferenceEquals(lhs, rhs) ? Normal : lhs;
279 var rest = lhs.stateList.Except(rhs.stateList);
281 if (rest.Count() == 0)
286 if (rest.Count() == 1)
291 ControlState newState = new ControlState();
292 newState.stateList.AddRange(rest);
298 /// The Key/Value pair structure. this is mutable to support for xaml.
300 [EditorBrowsable(EditorBrowsableState.Never)]
301 public struct StateValuePair<T> : IEquatable<StateValuePair<T>>
304 /// The constructor with the specified state and value.
306 /// <param name="state">The state</param>
307 /// <param name="value">The value associated with state.</param>
308 [EditorBrowsable(EditorBrowsableState.Never)]
309 public StateValuePair(ControlState state, T value)
318 [EditorBrowsable(EditorBrowsableState.Never)]
319 public ControlState State { get; set; }
321 /// The value associated with state.
323 [EditorBrowsable(EditorBrowsableState.Never)]
324 public T Value { get; set; }
327 [EditorBrowsable(EditorBrowsableState.Never)]
328 public bool Equals(StateValuePair<T> other) => (Value.Equals(other.Value)) && (State == other.State);
331 [EditorBrowsable(EditorBrowsableState.Never)]
332 public override bool Equals(object obj)
334 if (!(obj is StateValuePair<T>))
337 return Equals((StateValuePair<T>)obj);
341 [EditorBrowsable(EditorBrowsableState.Never)]
342 public override int GetHashCode() => (State.GetHashCode() * 397) ^ Value.GetHashCode();
346 /// Compares whether the two StateValuePair are different or not.
348 /// <param name="lhs">A <see cref="StateValuePair{T}"/> on the left hand side.</param>
349 /// <param name="rhs">A <see cref="StateValuePair{T}"/> on the right hand side.</param>
350 /// <returns>true if the StateValuePair are equal; otherwise, false.</returns>
351 [EditorBrowsable(EditorBrowsableState.Never)]
352 public static bool operator ==(StateValuePair<T> lhs, StateValuePair<T> rhs) => lhs.Equals(rhs);
355 /// Compares whether the two StateValuePair are same or not.
357 /// <param name="lhs">A <see cref="StateValuePair{T}"/> on the left hand side.</param>
358 /// <param name="rhs">A <see cref="StateValuePair{T}"/> on the right hand side.</param>
359 /// <returns>true if the StateValuePair are not equal; otherwise, false.</returns>
360 [EditorBrowsable(EditorBrowsableState.Never)]
361 public static bool operator !=(StateValuePair<T> lhs, StateValuePair<T> rhs) => !(lhs == rhs);
364 [EditorBrowsable(EditorBrowsableState.Never)]
365 public override string ToString() => $"[{State}, {Value}]";