Rasagar/Library/PackageCache/com.unity.test-framework/UnityEditor.TestRunner/GUI/Controls/FlagEnumContentProvider.cs
2024-08-26 23:07:20 +03:00

119 lines
3.8 KiB
C#

using System;
using UnityEngine;
namespace UnityEditor.TestTools.TestRunner.GUI.Controls
{
/// <summary>
/// A flag enum content provider to be used with the <see cref="SelectionDropDown" /> control.
/// </summary>
/// <typeparam name="T">The flag enum type.</typeparam>
internal class FlagEnumContentProvider<T> : ISelectionDropDownContentProvider where T : Enum
{
private readonly Action<T> m_ValueChangedCallback;
private readonly T[] m_Values;
internal Func<string, string> DisplayNameGenerator = ObjectNames.NicifyVariableName;
private T m_CurrentValue;
/// <summary>
/// Creates a new instance of the <see cref="FlagEnumContentProvider{T}" /> class.
/// </summary>
/// <param name="initialValue">The initial selection value.</param>
/// <param name="valueChangedCallback">The callback to be invoked on selection change.</param>
/// <exception cref="ArgumentException">
/// Thrown if the generic enum parameter type is not integer based
/// or if the initial selection value is empty.
/// </exception>
/// <exception cref="ArgumentNullException">Thrown if the provided change callback is null.</exception>
public FlagEnumContentProvider(T initialValue, Action<T> valueChangedCallback)
{
if (Enum.GetUnderlyingType(typeof(T)) != typeof(int))
{
throw new ArgumentException("Argument underlying type must be integer.");
}
if ((int)(object)initialValue == 0)
{
throw new ArgumentException("The initial value must not be an empty set.", nameof(initialValue));
}
if (valueChangedCallback == null)
{
throw new ArgumentNullException(nameof(valueChangedCallback), "The value change callback must not be null.");
}
m_CurrentValue = initialValue;
m_Values = (T[])Enum.GetValues(typeof(T));
m_ValueChangedCallback = valueChangedCallback;
}
public int Count => m_Values.Length;
public bool IsMultiSelection => true;
public string GetName(int index)
{
return ValidateIndexBounds(index) ? DisplayNameGenerator(m_Values[index].ToString()) : string.Empty;
}
public int[] SeparatorIndices => new int[0];
public bool IsSelected(int index)
{
return ValidateIndexBounds(index) && IsSet(m_Values[index]);
}
public void SelectItem(int index)
{
if (!ValidateIndexBounds(index))
{
return;
}
if (ChangeValue(m_Values[index]))
{
m_ValueChangedCallback(m_CurrentValue);
}
}
private bool ChangeValue(T flag)
{
var value = flag;
var count = GetSetCount();
if (IsSet(value))
{
if (count == 1)
{
return false;
}
m_CurrentValue = FlagEnumUtility.RemoveFlag(m_CurrentValue, flag);
return true;
}
m_CurrentValue = FlagEnumUtility.SetFlag(m_CurrentValue, flag);
return true;
}
private bool IsSet(T flag)
{
return FlagEnumUtility.HasFlag(m_CurrentValue, flag);
}
private int GetSetCount()
{
return BitUtility.GetCardinality((int)(object)m_CurrentValue);
}
private bool ValidateIndexBounds(int index)
{
if (index < 0 || index >= Count)
{
Debug.LogError($"Requesting item index {index} from a collection of size {Count}");
return false;
}
return true;
}
}
}