Skip to content

Commit

Permalink
[NUI] Add value type: control state
Browse files Browse the repository at this point in the history
Introduce the value type of ControlState. It replaces ControlState implementation.

Signed-off-by: Jiyun Yang <[email protected]>
  • Loading branch information
rabbitfor committed Jan 6, 2025
1 parent 19d0c1b commit b6011e4
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 87 deletions.
194 changes: 194 additions & 0 deletions src/Tizen.NUI/src/devel/LControlState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
* Copyright(c) 2025 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.Text;
using System.ComponentModel;

namespace Tizen.NUI.BaseComponents
{
/// <summary>
/// Defines a value type of control state.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly struct LControlState
{
/// <summary>
/// The All state is used in a selector class. It represents all states, so if this state is defined in a selector, the other states are ignored.
/// </summary>
public static readonly LControlState All = new LControlState(ControlStateUtility.FullMask);
/// <summary>
/// Normal State.
/// </summary>
public static readonly LControlState Normal = new LControlState(0UL);
/// <summary>
/// Focused State.
/// </summary>
public static readonly LControlState Focused = new LControlState(nameof(Focused));
/// <summary>
/// Pressed State.
/// </summary>
public static readonly LControlState Pressed = new LControlState(nameof(Pressed));
/// <summary>
/// Disabled State.
/// </summary>
public static readonly LControlState Disabled = new LControlState(nameof(Disabled));
/// <summary>
/// Selected State.
/// </summary>
public static readonly LControlState Selected = new LControlState(nameof(Selected));

/// <summary>
/// SelectedPressed State.
/// </summary>
public static readonly LControlState SelectedPressed = Selected + Pressed;

/// <summary>
/// DisabledSelected State.
/// </summary>
public static readonly LControlState DisabledSelected = Disabled + Selected;

/// <summary>
/// DisabledFocused State.
/// </summary>
public static readonly LControlState DisabledFocused = Disabled + Focused;

/// <summary>
/// SelectedFocused State.
/// </summary>
public static readonly LControlState SelectedFocused = Selected + Focused;

/// <summary>
/// This is used in a selector class. It represents all other states except for states that are already defined in a selector.
/// </summary>
public static readonly LControlState Other = new LControlState(nameof(Other));

private readonly ulong bitFlags;

private LControlState(ulong bitMask)
{
bitFlags = bitMask;
}

private LControlState(string name) : this(ControlStateUtility.Register(name))
{
}

/// <summary>
/// Gets or sets a value indicating whether it has combined states.
/// </summary>
internal bool IsCombined => (bitFlags != 0UL) && ((bitFlags & (bitFlags - 1UL)) != 0UL);

/// <summary>
/// Create an instance of the <see cref="LControlState"/> with state name.
/// </summary>
/// <param name="name">The state name.</param>
/// <returns>The <see cref="LControlState"/> instance which has single state.</returns>
/// <exception cref="ArgumentNullException">Thrown when the given name is null.</exception>
/// <exception cref="ArgumentException">Thrown when the given name is invalid.</exception>
public static LControlState Create(string name)
{
return new LControlState(name);
}

/// <summary>
/// Determines whether a state contains a specified state.
/// </summary>
/// <param name="state">The state to search for</param>
/// <returns>true if the state contain a specified state, otherwise, false.</returns>
public bool Contains(LControlState state) => (bitFlags & state.bitFlags) == state.bitFlags;

/// <summary>
/// Checks if there is a intersection part between this and the other.
/// </summary>
/// <param name="other">The other state to check.</param>
/// <returns>True if an intersection exists, otherwise false.</returns>
public bool HasIntersectionWith(LControlState other) => (bitFlags & other.bitFlags) != 0L;

/// <inheritdoc/>
public override string ToString()
{
var sbuilder = new StringBuilder();
var states = ControlStateUtility.RegisteredStates();

if (bitFlags == 0UL)
{
return nameof(Normal);
}

foreach (var (name, bitMask) in states)
{
if ((bitFlags & bitMask) > 0)
{
if (sbuilder.Length != 0) sbuilder.Append(", ");
sbuilder.Append(name);
}
}

return sbuilder.ToString();
}

/// <summary>
/// Compares whether the two ControlStates are same or not.
/// </summary>
/// <param name="lhs">A <see cref="LControlState"/> on the left hand side.</param>
/// <param name="rhs">A <see cref="LControlState"/> on the right hand side.</param>
/// <returns>true if the ControlStates are equal; otherwise, false.</returns>
public static bool operator ==(LControlState lhs, LControlState rhs) => lhs.Equals(rhs);

/// <summary>
/// Compares whether the two ControlStates are different or not.
/// </summary>
/// <param name="lhs">A <see cref="LControlState"/> on the left hand side.</param>
/// <param name="rhs">A <see cref="LControlState"/> on the right hand side.</param>
/// <returns>true if the ControlStates are not equal; otherwise, false.</returns>
public static bool operator !=(LControlState lhs, LControlState rhs) => !lhs.Equals(rhs);

/// <summary>
/// The addition operator.
/// </summary>
/// <param name="lhs">A <see cref="LControlState"/> on the left hand side.</param>
/// <param name="rhs">A <see cref="LControlState"/> on the right hand side.</param>
/// <returns>The <see cref="LControlState"/> containing the result of the addition.</returns>
public static LControlState operator +(LControlState lhs, LControlState rhs) => new LControlState(lhs.bitFlags | rhs.bitFlags);

/// <summary>
/// The substraction operator.
/// </summary>
/// <param name="lhs">A <see cref="LControlState"/> on the left hand side.</param>
/// <param name="rhs">A <see cref="LControlState"/> on the right hand side.</param>
/// <returns>The <see cref="LControlState"/> containing the result of the substraction.</returns>
public static LControlState operator -(LControlState lhs, LControlState rhs) => new LControlState(lhs.bitFlags & ~(rhs.bitFlags));

public bool Equals(LControlState other) => bitFlags == other.bitFlags;

/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is LControlState otherState)
{
return Equals(otherState);
}
return base.Equals(obj);
}

/// <inheritdoc/>
public override int GetHashCode() => bitFlags.GetHashCode();

internal ControlState ToReferenceType() => new ControlState(this);
}
}
Loading

0 comments on commit b6011e4

Please sign in to comment.