A game about forced loneliness, made by TACStudios
at master 118 lines 3.9 kB view raw
1using System; 2using UnityEngine; 3 4namespace UnityEditor.TestTools.TestRunner.GUI.Controls 5{ 6 /// <summary> 7 /// A flag enum content provider to be used with the <see cref="SelectionDropDown" /> control. 8 /// </summary> 9 /// <typeparam name="T">The flag enum type.</typeparam> 10 internal class FlagEnumContentProvider<T> : ISelectionDropDownContentProvider where T : Enum 11 { 12 private readonly Action<T> m_ValueChangedCallback; 13 private readonly T[] m_Values; 14 internal Func<string, string> DisplayNameGenerator = ObjectNames.NicifyVariableName; 15 private T m_CurrentValue; 16 17 /// <summary> 18 /// Creates a new instance of the <see cref="FlagEnumContentProvider{T}" /> class. 19 /// </summary> 20 /// <param name="initialValue">The initial selection value.</param> 21 /// <param name="valueChangedCallback">The callback to be invoked on selection change.</param> 22 /// <exception cref="ArgumentException"> 23 /// Thrown if the generic enum parameter type is not integer based 24 /// or if the initial selection value is empty. 25 /// </exception> 26 /// <exception cref="ArgumentNullException">Thrown if the provided change callback is null.</exception> 27 public FlagEnumContentProvider(T initialValue, Action<T> valueChangedCallback) 28 { 29 if (Enum.GetUnderlyingType(typeof(T)) != typeof(int)) 30 { 31 throw new ArgumentException("Argument underlying type must be integer."); 32 } 33 34 if ((int)(object)initialValue == 0) 35 { 36 throw new ArgumentException("The initial value must not be an empty set.", nameof(initialValue)); 37 } 38 39 if (valueChangedCallback == null) 40 { 41 throw new ArgumentNullException(nameof(valueChangedCallback), "The value change callback must not be null."); 42 } 43 44 m_CurrentValue = initialValue; 45 m_Values = (T[])Enum.GetValues(typeof(T)); 46 m_ValueChangedCallback = valueChangedCallback; 47 } 48 49 public int Count => m_Values.Length; 50 public bool IsMultiSelection => true; 51 52 public string GetName(int index) 53 { 54 return ValidateIndexBounds(index) ? DisplayNameGenerator(m_Values[index].ToString()) : string.Empty; 55 } 56 57 public int[] SeparatorIndices => new int[0]; 58 59 public bool IsSelected(int index) 60 { 61 return ValidateIndexBounds(index) && IsSet(m_Values[index]); 62 } 63 64 public void SelectItem(int index) 65 { 66 if (!ValidateIndexBounds(index)) 67 { 68 return; 69 } 70 71 if (ChangeValue(m_Values[index])) 72 { 73 m_ValueChangedCallback(m_CurrentValue); 74 } 75 } 76 77 private bool ChangeValue(T flag) 78 { 79 var value = flag; 80 var count = GetSetCount(); 81 82 if (IsSet(value)) 83 { 84 if (count == 1) 85 { 86 return false; 87 } 88 89 m_CurrentValue = FlagEnumUtility.RemoveFlag(m_CurrentValue, flag); 90 return true; 91 } 92 93 m_CurrentValue = FlagEnumUtility.SetFlag(m_CurrentValue, flag); 94 return true; 95 } 96 97 private bool IsSet(T flag) 98 { 99 return FlagEnumUtility.HasFlag(m_CurrentValue, flag); 100 } 101 102 private int GetSetCount() 103 { 104 return BitUtility.GetCardinality((int)(object)m_CurrentValue); 105 } 106 107 private bool ValidateIndexBounds(int index) 108 { 109 if (index < 0 || index >= Count) 110 { 111 Debug.LogError($"Requesting item index {index} from a collection of size {Count}"); 112 return false; 113 } 114 115 return true; 116 } 117 } 118}