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; } } }