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 [Binding.TypeConverter(typeof(ControlStateTypeConverter))]
30 public class ControlState : IEquatable<ControlState>
32 private static readonly Dictionary<string, ControlState> stateDictionary = new Dictionary<string, ControlState>();
37 [EditorBrowsable(EditorBrowsableState.Never)]
38 public static readonly ControlState All = Create("All");
42 [EditorBrowsable(EditorBrowsableState.Never)]
43 public static readonly ControlState Normal = Create("Normal");
47 [EditorBrowsable(EditorBrowsableState.Never)]
48 public static readonly ControlState Focused = Create("Focused");
52 [EditorBrowsable(EditorBrowsableState.Never)]
53 public static readonly ControlState Pressed = Create("Pressed");
57 [EditorBrowsable(EditorBrowsableState.Never)]
58 public static readonly ControlState Disabled = Create("Disabled");
62 [EditorBrowsable(EditorBrowsableState.Never)]
63 public static readonly ControlState Selected = Create("Selected");
65 /// DisabledSelected State.
67 [EditorBrowsable(EditorBrowsableState.Never)]
68 public static readonly ControlState DisabledSelected = Disabled + Selected;
70 /// DisabledFocused State.
72 [EditorBrowsable(EditorBrowsableState.Never)]
73 public static readonly ControlState DisabledFocused = Disabled + Focused;
75 /// SelectedFocused State.
77 [EditorBrowsable(EditorBrowsableState.Never)]
78 public static readonly ControlState SelectedFocused = Selected + Focused;
82 [EditorBrowsable(EditorBrowsableState.Never)]
83 public static readonly ControlState Other = Create("Other");
85 private List<ControlState> stateList = new List<ControlState>();
86 private readonly string name = "";
89 /// Gets or sets a value indicating whether it has combined states.
91 [EditorBrowsable(EditorBrowsableState.Never)]
92 public bool IsCombined => stateList.Count > 1;
94 private ControlState() { }
96 private ControlState(string name) : this() => this.name = name;
99 /// Create an instance of the <see cref="ControlState"/> with state name.
101 /// <param name="name">The state name.</param>
102 /// <returns>The <see cref="ControlState"/> instance which has single state.</returns>
103 [EditorBrowsable(EditorBrowsableState.Never)]
104 public static ControlState Create(string name)
107 throw new ArgumentNullException(nameof(name));
108 if (string.IsNullOrWhiteSpace(name))
109 throw new ArgumentException("name cannot be empty string", nameof(name));
111 if (stateDictionary.TryGetValue(name, out ControlState state))
114 state = new ControlState(name);
115 state.stateList.Add(state);
116 stateDictionary.Add(name, state);
121 /// Create an instance of the <see cref="ControlState"/> with combined states.
123 /// <param name="states">The control state array.</param>
124 /// <returns>The <see cref="ControlState"/> instance which has combined state.</returns>
125 [EditorBrowsable(EditorBrowsableState.Never)]
126 public static ControlState Create(params ControlState[] states)
128 if (states.Length == 1)
131 ControlState newState = new ControlState();
132 for (int i = 0; i < states.Length; i++)
134 if (states[i] == Normal)
137 if (states[i] == All)
140 newState.stateList.AddRange(states[i].stateList);
143 if (newState.stateList.Count == 0)
146 newState.stateList = newState.stateList.Distinct().ToList();
148 if (newState.stateList.Count == 1)
150 return newState.stateList[0];
157 /// Determines whether a state contains a specified state.
159 /// <param name="state">The state to search for</param>
160 /// <returns>true if the state contain a specified state, otherwise, false.</returns>
161 [EditorBrowsable(EditorBrowsableState.Never)]
162 public bool Contains(ControlState state)
165 throw new ArgumentNullException(nameof(state));
168 return ReferenceEquals(this, state);
171 for (int i = 0; i < state.stateList.Count; i++)
174 for (int j = 0; j < stateList.Count; j++)
176 if (ReferenceEquals(state.stateList[i], stateList[j]))
182 if (!found) return false;
189 [EditorBrowsable(EditorBrowsableState.Never)]
190 public bool Equals(ControlState other)
192 if (other is null || stateList.Count != other.stateList.Count)
195 return Contains(other);
199 [EditorBrowsable(EditorBrowsableState.Never)]
200 public override bool Equals(object obj) => this.Equals(obj as ControlState);
203 [EditorBrowsable(EditorBrowsableState.Never)]
204 public override int GetHashCode() => (name.GetHashCode() * 397) ^ IsCombined.GetHashCode();
207 [EditorBrowsable(EditorBrowsableState.Never)]
208 public override string ToString()
211 for (int i = 0; i < stateList.Count; i++)
213 name += ((i == 0) ? "" : ", ") + stateList[i].name;
219 /// Compares whether the two ControlStates are same or not.
221 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
222 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
223 /// <returns>true if the ControlStates are equal; otherwise, false.</returns>
224 [EditorBrowsable(EditorBrowsableState.Never)]
225 public static bool operator ==(ControlState lhs, ControlState rhs) => lhs.Equals(rhs);
228 /// Compares whether the two ControlStates are different or not.
230 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
231 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
232 /// <returns>true if the ControlStates are not equal; otherwise, false.</returns>
233 [EditorBrowsable(EditorBrowsableState.Never)]
234 public static bool operator !=(ControlState lhs, ControlState rhs) => !lhs.Equals(rhs);
237 /// The addition operator.
239 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
240 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
241 /// <returns>The <see cref="ControlState"/> containing the result of the addition.</returns>
242 [EditorBrowsable(EditorBrowsableState.Never)]
243 public static ControlState operator +(ControlState lhs, ControlState rhs) => Create(lhs, rhs);
246 /// The substraction operator.
248 /// <param name="lhs">A <see cref="ControlState"/> on the left hand side.</param>
249 /// <param name="rhs">A <see cref="ControlState"/> on the right hand side.</param>
250 /// <returns>The <see cref="ControlState"/> containing the result of the substraction.</returns>
251 [EditorBrowsable(EditorBrowsableState.Never)]
252 public static ControlState operator -(ControlState lhs, ControlState rhs)
256 return ReferenceEquals(lhs, rhs) ? Normal : lhs;
259 var rest = lhs.stateList.Except(rhs.stateList);
261 if (rest.Count() == 0)
266 if (rest.Count() == 1)
271 ControlState newState = new ControlState();
272 newState.stateList.AddRange(rest);
276 class ControlStateTypeConverter : Binding.TypeConverter
278 public override object ConvertFromInvariantString(string value)
282 value = value.Trim();
284 ControlState convertedState = new ControlState();
285 string[] parts = value.Split(',');
286 foreach (string part in parts)
288 convertedState += Create(part);
290 return convertedState;
293 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(ControlState)}");