From f35ca6fa89c4cc86c53f087daa6012d53c8f7765 Mon Sep 17 00:00:00 2001 From: YeongJong Lee Date: Fri, 3 Jul 2020 11:05:20 +0900 Subject: [PATCH] [NUI] add ControlState class to support combined and custom state (#1762) ### Custom State You can define your own control states. first, declare ControlState variable and initialize using `ControlState.Create`. ``` public class MyButton : Button { ... ControlState MyState = ControlState.Create("MyState"); ... } ``` And assign to `View.ControlState`. ``` void OnStateChanged(...) { ControlState = MyState; } ``` If you want to assign the value of custom state to `Selector`, use `Add(ControlState state, object value)`. ``` Selector textSelector = new Selector(); textSelector.Add(ControlState.Pressed, "Pressed!"); textSelector.Add(MyState, "MyText"); ``` or ``` Selector textSelector = new Selector() { { ControlState.Pressed, "Pressed!" }, { MyState, "MyText" } }; ``` ### Combined State To implement your own combined control states, you can use the `+` or `+=` operators. For example, `MyCombinedStateX` are all the same. ``` ControlState MyCombinedStateA = ControlState.Create(ControlState.Pressed, ControlState.Focused); ControlState MyCombinedStateB = ControlState.Pressed + ControlState.Focused; ``` Note that `Normal` and `All` state cannot be combined with other states. `Normal` state is ignored. however, `All` state will ignore other states. ``` ControlState.Create(ControlState.Pressed, ControlState.Focused, ControlState.Normal) == ControlState.Create(ControlState.Pressed, ControlState.Focused) ControlState.Create(ControlState.All, ControlState.Pressed, ControlState.Focused) == ControlState.Create(ControlState.All) ``` ### ControlState in Xaml It will support new initialization syntax. Legacy: ``` ``` New: ``` ``` However, it won't work because there is no converter of `ControlState`. The next step would be to implement `ControlState` converter. --- .../Controls/Button.Internal.cs | 29 +- src/Tizen.NUI.Components/Controls/Control.cs | 8 +- .../Controls/DropDown.DropDownItemView.cs | 4 +- .../Controls/Extension/LottieButtonExtension.cs | 8 +- src/Tizen.NUI.Components/Controls/Slider.cs | 6 +- src/Tizen.NUI.Components/Controls/Tab.cs | 2 +- .../PreloadStyle/OverlayAnimationButtonStyle.cs | 6 +- .../src/public/CircularProgress.cs | 6 +- .../src/public/BaseComponents/ControlState.cs | 315 +++++++++++++++++++++ .../src/public/BaseComponents/Style/Constants.cs | 29 ++ .../src/public/BaseComponents/Style/Selector.cs | 67 +++-- .../BaseComponents/Style/StateValueCollection.cs | 93 ++++++ src/Tizen.NUI/src/public/BaseComponents/View.cs | 5 +- .../src/public/BaseComponents/ViewEvent.cs | 6 +- 14 files changed, 514 insertions(+), 70 deletions(-) create mode 100644 src/Tizen.NUI/src/public/BaseComponents/ControlState.cs create mode 100644 src/Tizen.NUI/src/public/BaseComponents/Style/StateValueCollection.cs diff --git a/src/Tizen.NUI.Components/Controls/Button.Internal.cs b/src/Tizen.NUI.Components/Controls/Button.Internal.cs index 64c1504..68b7160 100755 --- a/src/Tizen.NUI.Components/Controls/Button.Internal.cs +++ b/src/Tizen.NUI.Components/Controls/Button.Internal.cs @@ -104,47 +104,48 @@ namespace Tizen.NUI.Components [EditorBrowsable(EditorBrowsableState.Never)] protected void UpdateState() { - ControlStates sourceState = ControlState; - ControlStates targetState; + ControlState sourceState = ControlState; + ControlState targetState; if (isEnabled) { if (isPressed) { // Pressed - targetState = ControlStates.Pressed; + targetState = ControlState.Pressed; } else { // Normal - targetState = ControlStates.Normal; + targetState = ControlState.Normal; // Selected - targetState |= (IsSelected ? ControlStates.Selected : 0); + if (IsSelected) targetState += ControlState.Selected; // Focused, SelectedFocused - targetState |= (IsFocused ? ControlStates.Focused : 0); + if (IsFocused) targetState += ControlState.Focused; } } else { // Disabled - targetState = ControlStates.Disabled; + targetState = ControlState.Disabled; - // DisabledSelected, DisabledFocused - targetState |= (IsSelected ? ControlStates.Selected : (IsFocused ? ControlStates.Focused : 0)); + // DisabledSelected + if (IsSelected) targetState += ControlState.Selected; + // DisabledFocused + else if (IsFocused) targetState += ControlState.Focused; } if (sourceState != targetState) { ControlState = targetState; - OnUpdate(); StateChangedEventArgs e = new StateChangedEventArgs { - PreviousState = sourceState, - CurrentState = targetState + PreviousState = ControlStatesExtension.FromControlStateClass(sourceState), + CurrentState = ControlStatesExtension.FromControlStateClass(targetState) }; stateChangeHander?.Invoke(this, e); @@ -356,14 +357,14 @@ namespace Tizen.NUI.Components { base.OnControlStateChanged(controlStateChangedInfo); - var stateEnabled = !((controlStateChangedInfo.CurrentState & ControlStates.Disabled) == ControlStates.Disabled); + var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled); if (isEnabled != stateEnabled) { isEnabled = stateEnabled; } - var statePressed = (controlStateChangedInfo.CurrentState & ControlStates.Pressed) == ControlStates.Pressed; + var statePressed = controlStateChangedInfo.CurrentState.Contains(ControlState.Pressed); if (isPressed != statePressed) { diff --git a/src/Tizen.NUI.Components/Controls/Control.cs b/src/Tizen.NUI.Components/Controls/Control.cs index 7fcde28..54e86c8 100755 --- a/src/Tizen.NUI.Components/Controls/Control.cs +++ b/src/Tizen.NUI.Components/Controls/Control.cs @@ -256,13 +256,13 @@ namespace Tizen.NUI.Components switch(state) { case PointStateType.Down: - ControlState = ControlStates.Pressed; + ControlState = ControlState.Pressed; break; case PointStateType.Interrupted: case PointStateType.Up: - if (ControlState == ControlStates.Pressed) + if (ControlState == ControlState.Pressed) { - ControlState = ControlStates.Normal; + ControlState = ControlState.Normal; } break; default: @@ -304,7 +304,7 @@ namespace Tizen.NUI.Components private void Initialize() { - ControlState = ControlStates.Normal; + ControlState = ControlState.Normal; RegisterDetectionOfSubstyleChanges(); diff --git a/src/Tizen.NUI.Components/Controls/DropDown.DropDownItemView.cs b/src/Tizen.NUI.Components/Controls/DropDown.DropDownItemView.cs index b9b95ab..62268a9 100755 --- a/src/Tizen.NUI.Components/Controls/DropDown.DropDownItemView.cs +++ b/src/Tizen.NUI.Components/Controls/DropDown.DropDownItemView.cs @@ -199,12 +199,12 @@ namespace Tizen.NUI.Components CreateCheckImage(); if (value) { - ControlState = ControlStates.Selected; + ControlState = ControlState.Selected; mCheck.Show(); } else { - ControlState = ControlStates.Normal; + ControlState = ControlState.Normal; mCheck.Hide(); } } diff --git a/src/Tizen.NUI.Components/Controls/Extension/LottieButtonExtension.cs b/src/Tizen.NUI.Components/Controls/Extension/LottieButtonExtension.cs index e885c1d..26d3ee6 100644 --- a/src/Tizen.NUI.Components/Controls/Extension/LottieButtonExtension.cs +++ b/src/Tizen.NUI.Components/Controls/Extension/LottieButtonExtension.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -70,12 +70,12 @@ namespace Tizen.NUI.Components.Extension var lottieStyle = (ILottieButtonStyle)button.Style; lottieView.URL = lottieStyle.LottieUrl; lottieView.StopBehavior = LottieAnimationView.StopBehaviorType.MaximumFrame; - lottieStyle.PlayRange?.GetValue(ControlStates.Normal)?.Show(lottieView, true); + lottieStyle.PlayRange?.GetValue(ControlState.Normal)?.Show(lottieView, true); } - internal static void UpdateLottieView(Button button, ControlStates previousState, LottieAnimationView lottieView) + internal static void UpdateLottieView(Button button, ControlState previousState, LottieAnimationView lottieView) { - ((ILottieButtonStyle)button.Style).PlayRange?.GetValue(button.ControlState)?.Show(lottieView, ((int)previousState & (int)ControlStates.Pressed) == 0); + ((ILottieButtonStyle)button.Style).PlayRange?.GetValue(button.ControlState)?.Show(lottieView, !previousState.Contains(ControlState.Pressed)); } } } diff --git a/src/Tizen.NUI.Components/Controls/Slider.cs b/src/Tizen.NUI.Components/Controls/Slider.cs index 07e7cf8..30b6f18 100755 --- a/src/Tizen.NUI.Components/Controls/Slider.cs +++ b/src/Tizen.NUI.Components/Controls/Slider.cs @@ -876,7 +876,7 @@ namespace Tizen.NUI.Components if (!isFocused && !isPressed) { - ControlState = ControlStates.Normal; + ControlState = ControlState.Normal; if (stateChangedHandler != null) { StateChangedArgs args = new StateChangedArgs(); @@ -886,7 +886,7 @@ namespace Tizen.NUI.Components } else if (isPressed) { - ControlState = ControlStates.Pressed; + ControlState = ControlState.Pressed; if (stateChangedHandler != null) { @@ -897,7 +897,7 @@ namespace Tizen.NUI.Components } else if (!isPressed && isFocused) { - ControlState = ControlStates.Focused; + ControlState = ControlState.Focused; if (stateChangedHandler != null) { diff --git a/src/Tizen.NUI.Components/Controls/Tab.cs b/src/Tizen.NUI.Components/Controls/Tab.cs index 276b14e..a48d3ed 100755 --- a/src/Tizen.NUI.Components/Controls/Tab.cs +++ b/src/Tizen.NUI.Components/Controls/Tab.cs @@ -758,7 +758,7 @@ namespace Tizen.NUI.Components } set { - ControlState = value ? ControlStates.Selected : ControlStates.Normal; + ControlState = value ? ControlState.Selected : ControlState.Normal; isSelected = value; } } diff --git a/src/Tizen.NUI.Components/PreloadStyle/OverlayAnimationButtonStyle.cs b/src/Tizen.NUI.Components/PreloadStyle/OverlayAnimationButtonStyle.cs index 0cf4924..9961a77 100644 --- a/src/Tizen.NUI.Components/PreloadStyle/OverlayAnimationButtonStyle.cs +++ b/src/Tizen.NUI.Components/PreloadStyle/OverlayAnimationButtonStyle.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright(c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -104,7 +104,7 @@ namespace Tizen.NUI.Components [EditorBrowsable(EditorBrowsableState.Never)] public override void OnControlStateChanged(Button button, View.ControlStateChangedEventArgs args) { - if (button.ControlState != ControlStates.Pressed) + if (button.ControlState != ControlState.Pressed) { return; } @@ -162,4 +162,4 @@ namespace Tizen.NUI.Components PressAnimation = null; } } -} \ No newline at end of file +} diff --git a/src/Tizen.NUI.Wearable/src/public/CircularProgress.cs b/src/Tizen.NUI.Wearable/src/public/CircularProgress.cs index 631b561..efc0da1 100755 --- a/src/Tizen.NUI.Wearable/src/public/CircularProgress.cs +++ b/src/Tizen.NUI.Wearable/src/public/CircularProgress.cs @@ -345,13 +345,13 @@ namespace Tizen.NUI.Wearable isEnabled = value; if (isEnabled) { - ControlState = ControlStates.Normal; + ControlState = ControlState.Normal; UpdateTrackVisualColor(new Color(0.0f, 0.16f, 0.30f, 1.0f)); // #002A4D } else { - ControlState = ControlStates.Disabled; + ControlState = ControlState.Disabled; UpdateTrackVisualColor(new Color(0.25f, 0.25f, 0.25f, 1.0f)); // #404040 } @@ -421,7 +421,7 @@ namespace Tizen.NUI.Wearable { base.OnControlStateChanged(controlStateChangedInfo); - var stateEnabled = !((controlStateChangedInfo.CurrentState & ControlStates.Disabled) == ControlStates.Disabled); + var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled); if (isEnabled != stateEnabled) { diff --git a/src/Tizen.NUI/src/public/BaseComponents/ControlState.cs b/src/Tizen.NUI/src/public/BaseComponents/ControlState.cs new file mode 100644 index 0000000..06aa976 --- /dev/null +++ b/src/Tizen.NUI/src/public/BaseComponents/ControlState.cs @@ -0,0 +1,315 @@ +/* + * 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(); + + 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 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}]"; + } +} \ No newline at end of file diff --git a/src/Tizen.NUI/src/public/BaseComponents/Style/Constants.cs b/src/Tizen.NUI/src/public/BaseComponents/Style/Constants.cs index 6d04a79..068967a 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/Style/Constants.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/Style/Constants.cs @@ -16,6 +16,7 @@ */ using System.ComponentModel; +using Tizen.NUI.BaseComponents; namespace Tizen.NUI.Components { @@ -84,4 +85,32 @@ namespace Tizen.NUI.Components [EditorBrowsable(EditorBrowsableState.Never)] DisabledSelected = Disabled | Selected, } + + //FIXME: Please remove this Extension class when ControlStates is removed. + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class ControlStatesExtension + { + public static ControlStates FromControlStateClass(ControlState controlState) + { + if (controlState == ControlState.Normal) + return ControlStates.Normal; + if (controlState == ControlState.Focused) + return ControlStates.Focused; + if (controlState == ControlState.Disabled) + return ControlStates.Disabled; + if (controlState == ControlState.Selected) + return ControlStates.Selected; + if (controlState == ControlState.Pressed) + return ControlStates.Pressed; + if (controlState == ControlState.DisabledFocused) + return ControlStates.DisabledFocused; + if (controlState == ControlState.SelectedFocused) + return ControlStates.SelectedFocused; + if (controlState == ControlState.DisabledSelected) + return ControlStates.DisabledSelected; + + return ControlStates.Normal; + } + } } + diff --git a/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs b/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs index a804baf..7a486b5 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs @@ -27,7 +27,7 @@ namespace Tizen.NUI.BaseComponents /// 6 /// 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 : BindableObject + public class Selector : StateValueCollection { /// 6 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. @@ -70,8 +70,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T Normal { - get; - set; + get => Find(x => x.State == ControlState.Normal).Value; + set => Add(ControlState.Normal, value); } /// /// Pressed State. @@ -81,8 +81,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T Pressed { - get; - set; + get => Find(x => x.State == ControlState.Pressed).Value; + set => Add(ControlState.Pressed, value); } /// /// Focused State. @@ -92,8 +92,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T Focused { - get; - set; + get => Find(x => x.State == ControlState.Focused).Value; + set => Add(ControlState.Focused, value); } /// /// Selected State. @@ -103,8 +103,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T Selected { - get; - set; + get => Find(x => x.State == ControlState.Selected).Value; + set => Add(ControlState.Selected, value); } /// /// Disabled State. @@ -114,8 +114,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T Disabled { - get; - set; + get => Find(x => x.State == ControlState.Disabled).Value; + set => Add(ControlState.Disabled, value); } /// /// DisabledFocused State. @@ -125,8 +125,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T DisabledFocused { - get; - set; + get => Find(x => x.State == ControlState.DisabledFocused).Value; + set => Add(ControlState.DisabledFocused, value); } /// /// SelectedFocused State. @@ -135,8 +135,8 @@ namespace Tizen.NUI.BaseComponents /// 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; - set; + get => Find(x => x.State == ControlState.SelectedFocused).Value; + set => Add(ControlState.SelectedFocused, value); } /// /// DisabledSelected State. @@ -146,8 +146,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T DisabledSelected { - get; - set; + get => Find(x => x.State == ControlState.DisabledSelected).Value; + set => Add(ControlState.DisabledSelected, value); } /// @@ -158,8 +158,8 @@ namespace Tizen.NUI.BaseComponents [EditorBrowsable(EditorBrowsableState.Never)] public T Other { - get; - set; + get => Find(x => x.State == ControlState.Other).Value; + set => Add(ControlState.Other, value); } /// /// Get value by State. @@ -167,7 +167,7 @@ namespace Tizen.NUI.BaseComponents /// 6 /// 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 T GetValue(ControlStates state) + public T GetValue(ControlState state) { if(All != null) { @@ -175,25 +175,32 @@ namespace Tizen.NUI.BaseComponents } switch(state) { - case ControlStates.Normal: + case null: + case var s when s == ControlState.Normal: return Normal != null? Normal : Other; - case ControlStates.Focused: + case var s when s == ControlState.Focused: return Focused != null? Focused : Other; - case ControlStates.Pressed: + case var s when s == ControlState.Pressed: return Pressed != null? Pressed : Other; - case ControlStates.Disabled: + case var s when s == ControlState.Disabled: return Disabled != null? Disabled : Other; - case ControlStates.Selected: - return Selected != null? Selected : Other; - case ControlStates.DisabledFocused: + case var s when s == ControlState.Selected: + return Selected != null? Selected : Other; + case var s when s == ControlState.DisabledFocused: return DisabledFocused != null? DisabledFocused : (Disabled != null ? Disabled : Other); - case ControlStates.DisabledSelected: + case var s when s == ControlState.DisabledSelected: return DisabledSelected != null ? DisabledSelected : (Disabled != null ? Disabled : Other); - case ControlStates.SelectedFocused: + case var s when s == ControlState.SelectedFocused: return SelectedFocused != null ? SelectedFocused : (Selected != null ? Selected : Other); default: { - // TODO Handle combined states + StateValuePair value = Find(x => x.State == state); + if (value.Value != null) + return value.Value; + + value = Find(x => state.Contains(x.State)); + if (value.Value != null) + return value.Value; return Other; } } diff --git a/src/Tizen.NUI/src/public/BaseComponents/Style/StateValueCollection.cs b/src/Tizen.NUI/src/public/BaseComponents/Style/StateValueCollection.cs new file mode 100644 index 0000000..b2e005e --- /dev/null +++ b/src/Tizen.NUI/src/public/BaseComponents/Style/StateValueCollection.cs @@ -0,0 +1,93 @@ +/* + * 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; +using System.Collections.Generic; +using System.ComponentModel; + +namespace Tizen.NUI.BaseComponents +{ + /// + /// The StateValueCollection class, which is related by , it is abstract class for . + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public abstract class StateValueCollection : ICollection> + { + + [EditorBrowsable(EditorBrowsableState.Never)] + internal List> StateValueList { get; } = new List>(); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public int Count => StateValueList.Count; + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool IsReadOnly => ((ICollection>)StateValueList).IsReadOnly; + + /// + /// Add a with state and value. + /// + /// The state. + /// The value associated with state. + [EditorBrowsable(EditorBrowsableState.Never)] + public void Add(ControlState state, T value) => Add(new StateValuePair(state, value)); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public void Add(StateValuePair item) + { + // To prevent a state from having multiple values, remove existing state-value pair. + int index = StateValueList.FindIndex(x => x.State == item.State); + if (index != -1) + StateValueList.RemoveAt(index); + + StateValueList.Add(item); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public void Clear() => StateValueList.Clear(); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Contains(StateValuePair item) => StateValueList.Contains(item); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public void CopyTo(StateValuePair[] array, int arrayIndex) => StateValueList.CopyTo(array, arrayIndex); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Remove(StateValuePair item) => StateValueList.Remove(item); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public IEnumerator> GetEnumerator() => StateValueList.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => StateValueList.GetEnumerator(); + + /// + /// Searches for a StateValuePair that matches the conditions defined by the specified + /// predicate, and returns the first occurrence within the entire + /// + /// The delegate that defines the conditions of the element to search for. + /// The first element that matches the conditions defined by the specified predicate, + /// if found; otherwise, the default value for type . + public StateValuePair Find(Predicate> match) => StateValueList.Find(match); + } +} \ No newline at end of file diff --git a/src/Tizen.NUI/src/public/BaseComponents/View.cs b/src/Tizen.NUI/src/public/BaseComponents/View.cs index 401b48d..621ae79 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/View.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/View.cs @@ -171,14 +171,13 @@ namespace Tizen.NUI.BaseComponents internal event EventHandler ControlStateChangeEventInternal; - private ControlStates controlStates; + private ControlState controlStates = ControlState.Normal; /// /// Get/Set the control state. /// - /// 6 /// 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 ControlStates ControlState + public ControlState ControlState { get { diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs index fb27aaa..e587b2b 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs @@ -1068,7 +1068,7 @@ namespace Tizen.NUI.BaseComponents /// The previous control state. /// The current control state. [EditorBrowsable(EditorBrowsableState.Never)] - public ControlStateChangedEventArgs(ControlStates previousState, ControlStates currentState) + public ControlStateChangedEventArgs(ControlState previousState, ControlState currentState) { PreviousState = previousState; CurrentState = currentState; @@ -1078,13 +1078,13 @@ namespace Tizen.NUI.BaseComponents /// The previous control state. /// [EditorBrowsable(EditorBrowsableState.Never)] - public ControlStates PreviousState { get; } + public ControlState PreviousState { get; } /// /// The current control state. /// [EditorBrowsable(EditorBrowsableState.Never)] - public ControlStates CurrentState { get; } + public ControlState CurrentState { get; } } private EventHandlerWithReturnType WindowWheelEventHandler; -- 2.7.4