2 * Copyright(c) 2019 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.
18 using System.ComponentModel;
19 using Tizen.NUI.Binding;
20 using Tizen.NUI.Components;
22 namespace Tizen.NUI.BaseComponents
25 /// Selector class, which is related by Control State, it is base class for other Selector.
27 /// <since_tizen> 6 </since_tizen>
28 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
29 [EditorBrowsable(EditorBrowsableState.Never)]
30 public class Selector<T> : StateValueCollection<T>
32 private readonly bool cloneable = typeof(T).IsAssignableFrom(typeof(ICloneable));
34 /// <since_tizen> 6 </since_tizen>
35 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
36 public static implicit operator Selector<T>(T value)
38 return new Selector<T>(value);
41 /// Default Contructor
42 [EditorBrowsable(EditorBrowsableState.Never)]
48 [EditorBrowsable(EditorBrowsableState.Never)]
49 public Selector(T value) : this()
51 All = cloneable ? (T)((ICloneable)value)?.Clone() : value;
55 [EditorBrowsable(EditorBrowsableState.Never)]
56 public Selector(Selector<T> value) : this()
65 /// <since_tizen> 6 </since_tizen>
66 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
67 [EditorBrowsable(EditorBrowsableState.Never)]
76 /// <since_tizen> 6 </since_tizen>
77 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
78 [EditorBrowsable(EditorBrowsableState.Never)]
81 get => Find(x => x.State == ControlState.Normal).Value;
82 set => Add(ControlState.Normal, value);
87 /// <since_tizen> 6 </since_tizen>
88 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
89 [EditorBrowsable(EditorBrowsableState.Never)]
92 get => Find(x => x.State == ControlState.Pressed).Value;
93 set => Add(ControlState.Pressed, value);
98 /// <since_tizen> 6 </since_tizen>
99 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
100 [EditorBrowsable(EditorBrowsableState.Never)]
103 get => Find(x => x.State == ControlState.Focused).Value;
104 set => Add(ControlState.Focused, value);
109 /// <since_tizen> 6 </since_tizen>
110 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
111 [EditorBrowsable(EditorBrowsableState.Never)]
114 get => Find(x => x.State == ControlState.Selected).Value;
115 set => Add(ControlState.Selected, value);
120 /// <since_tizen> 6 </since_tizen>
121 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
122 [EditorBrowsable(EditorBrowsableState.Never)]
125 get => Find(x => x.State == ControlState.Disabled).Value;
126 set => Add(ControlState.Disabled, value);
129 /// DisabledFocused State.
131 /// <since_tizen> 6 </since_tizen>
132 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
133 [EditorBrowsable(EditorBrowsableState.Never)]
134 public T DisabledFocused
136 get => Find(x => x.State == ControlState.DisabledFocused).Value;
137 set => Add(ControlState.DisabledFocused, value);
140 /// SelectedFocused State.
142 /// <since_tizen> 6 </since_tizen>
143 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
144 public T SelectedFocused
146 get => Find(x => x.State == ControlState.SelectedFocused).Value;
147 set => Add(ControlState.SelectedFocused, value);
150 /// DisabledSelected State.
152 /// <since_tizen> 6 </since_tizen>
153 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
154 [EditorBrowsable(EditorBrowsableState.Never)]
155 public T DisabledSelected
157 get => Find(x => x.State == ControlState.DisabledSelected).Value;
158 set => Add(ControlState.DisabledSelected, value);
164 /// <since_tizen> 6 </since_tizen>
165 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
166 [EditorBrowsable(EditorBrowsableState.Never)]
169 get => Find(x => x.State == ControlState.Other).Value;
170 set => Add(ControlState.Other, value);
173 /// Get value by State.
175 /// <since_tizen> 6 </since_tizen>
176 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
177 /// <returns>True if the selector has a given state value, false otherwise.</returns>
178 [EditorBrowsable(EditorBrowsableState.Never)]
179 public bool GetValue(ControlState state, out T result)
190 int index = StateValueList.FindIndex(x => x.State == state);
193 result = StateValueList[index].Value;
197 if (state.IsCombined)
199 index = StateValueList.FindIndex(x => state.Contains(x.State));
202 result = StateValueList[index].Value;
207 index = StateValueList.FindIndex(x => x.State == ControlState.Other);
210 result = StateValueList[index].Value;
218 [EditorBrowsable(EditorBrowsableState.Never)]
219 public override void Clear()
226 [EditorBrowsable(EditorBrowsableState.Never)]
227 public override string ToString()
229 string result = $"[All, {All}]";
231 foreach (var item in StateValueList)
233 result += $", {item}";
241 /// If type T implements ICloneable, it calls Clone() method to clone values, otherwise use operator=.
243 /// <since_tizen> 6 </since_tizen>
244 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
245 [EditorBrowsable(EditorBrowsableState.Never)]
246 public Selector<T> Clone()
248 var cloned = new Selector<T>();
254 /// Copy values from other selector.
256 [EditorBrowsable(EditorBrowsableState.Never)]
257 public void Clone(Selector<T> other)
263 All = (T)((ICloneable)other.All)?.Clone();
264 foreach (var item in other.StateValueList)
266 AddWithoutCheck(new StateValuePair<T>(item.State, (T)((ICloneable)item.Value)?.Clone()));
272 foreach (var item in other.StateValueList)
274 AddWithoutCheck(item);
279 internal bool HasMultiValue()
281 return StateValueList.Count > 1;
286 /// This will be attached to a View to detect ControlState change.
288 [EditorBrowsable(EditorBrowsableState.Never)]
289 public class TriggerableSelector<T>
292 /// Create an TriggerableSelector.
294 [EditorBrowsable(EditorBrowsableState.Never)]
295 public delegate T ValueGetter(View view);
297 private readonly BindableProperty targetBindableProperty;
298 private readonly ValueGetter propertyGetter;
299 private bool dirty = true;
300 private Selector<T> selector;
303 /// Create an TriggerableSelector.
305 /// <param name="targetBindableProperty">The TriggerableSelector will change this bindable property value when the view's ControlState has changed.</param>
306 /// <param name="propertyGetter">It is optional value in case the target bindable property getter is not proper to use.</param>
307 [EditorBrowsable(EditorBrowsableState.Never)]
308 public TriggerableSelector(BindableProperty targetBindableProperty, ValueGetter propertyGetter = null)
310 this.targetBindableProperty = targetBindableProperty;
311 this.propertyGetter = propertyGetter;
315 /// Return the containing selector. It can be null.
317 [EditorBrowsable(EditorBrowsableState.Never)]
318 public Selector<T> Get(View view)
320 if (!dirty) return selector;
324 if (propertyGetter != null)
326 value = propertyGetter(view);
330 value = (T)view.GetValue(targetBindableProperty);
333 Selector<T> converted = value == null ? null : new Selector<T>(value);
334 Update(view, converted);
340 /// Update containing selector from the other selector.
342 /// <param name="view">The View that is affected by this TriggerableSelector.</param>
343 /// <param name="otherSelector">The copy target.</param>
344 /// <param name="updateView">Whether it updates the target view after update the selector or not.</param>
345 [EditorBrowsable(EditorBrowsableState.Never)]
346 public void Update(View view, Selector<T> otherSelector, bool updateView = false)
350 if (otherSelector == null)
355 selector = otherSelector.Clone();
357 if (otherSelector.HasMultiValue())
359 view.ControlStateChangeEventInternal += OnViewControlState;
362 if (updateView && otherSelector.GetValue(view.ControlState, out var value))
364 view.SetValue(targetBindableProperty, value);
369 /// Update containing selector value from a single value.
370 /// Note that, it updates lazily if possible.
371 /// If you need to udpate directly, please use <seealso cref="Update" />.
373 /// <param name="view">The View that is affected by this TriggerableSelector.</param>
374 /// <param name="value">The copy target.</param>
375 [EditorBrowsable(EditorBrowsableState.Never)]
376 public void UpdateIfNeeds(View view, T value)
378 if (selector != null && selector.HasMultiValue())
380 Selector<T> converted = value == null ? null : new Selector<T>(value);
381 Update(view, converted);
389 /// Reset selector and listeners.
391 /// <param name="view">The View that is affected by this TriggerableSelector.</param>
392 [EditorBrowsable(EditorBrowsableState.Never)]
393 public void Reset(View view)
395 view.ControlStateChangeEventInternal -= OnViewControlState;
401 private void OnViewControlState(object obj, View.ControlStateChangedEventArgs controlStateChangedInfo)
403 View view = obj as View;
404 if (null != view && selector.GetValue(controlStateChangedInfo.CurrentState, out var value))
406 view.SetValue(targetBindableProperty, value);