using System;
using UnityEngine;
namespace UnityEditor.TestTools.TestRunner.GUI.Controls
{
///
/// A flag enum content provider to be used with the control.
///
/// The flag enum type.
internal class FlagEnumContentProvider : ISelectionDropDownContentProvider where T : Enum
{
private readonly Action m_ValueChangedCallback;
private readonly T[] m_Values;
internal Func DisplayNameGenerator = ObjectNames.NicifyVariableName;
private T m_CurrentValue;
///
/// Creates a new instance of the class.
///
/// The initial selection value.
/// The callback to be invoked on selection change.
///
/// Thrown if the generic enum parameter type is not integer based
/// or if the initial selection value is empty.
///
/// Thrown if the provided change callback is null.
public FlagEnumContentProvider(T initialValue, Action 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;
}
}
}