You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.7 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Experimental.UIElements;
  5. namespace UnityEditor.PackageManager.UI
  6. {
  7. #if UNITY_2018_3_OR_NEWER
  8. internal class PopupField<T> : Experimental.UIElements.PopupField<T>
  9. {
  10. private Func<T, string> m_Callback;
  11. public override T value
  12. {
  13. get { return base.value; }
  14. set
  15. {
  16. base.value = value;
  17. if (m_Callback != null)
  18. m_TextElement.text = m_Callback(m_Value);
  19. else
  20. m_TextElement.text = m_Value.ToString();
  21. }
  22. }
  23. /// <summary>
  24. /// Callback that will return the string to be set in the field's label.
  25. /// </summary>
  26. /// <param name="callback"></param>
  27. public void SetLabelCallback(Func<T, string> callback)
  28. {
  29. m_Callback = callback;
  30. }
  31. public PopupField(List<T> choices, T defaultValue) :
  32. base(choices, defaultValue)
  33. {
  34. }
  35. public PopupField(List<T> choices, int defaultIndex) :
  36. base(choices, defaultIndex)
  37. {
  38. }
  39. }
  40. #else
  41. internal class PopupField<T> : BaseTextElement, INotifyValueChanged<T>
  42. {
  43. private readonly List<T> m_PossibleValues;
  44. private Func<T, string> m_Callback;
  45. private EventCallback<ChangeEvent<T>> m_valueCallback;
  46. private T m_Value;
  47. public T value
  48. {
  49. get { return m_Value; }
  50. set
  51. {
  52. if (EqualityComparer<T>.Default.Equals(m_Value, value))
  53. return;
  54. if (!m_PossibleValues.Contains(value))
  55. throw new ArgumentException(string.Format("Value {0} is not present in the list of possible values", value));
  56. m_Value = value;
  57. m_Index = m_PossibleValues.IndexOf(m_Value);
  58. if (m_Callback != null)
  59. text = m_Callback(m_Value);
  60. else
  61. text = m_Value.ToString();
  62. #if UNITY_2018_3_OR_NEWER
  63. MarkDirtyRepaint();
  64. #else
  65. Dirty(ChangeType.Repaint);
  66. #endif
  67. }
  68. }
  69. private int m_Index = -1;
  70. public int index
  71. {
  72. get { return m_Index; }
  73. set
  74. {
  75. if (value != m_Index)
  76. {
  77. if (value >= m_PossibleValues.Count || value < 0)
  78. throw new ArgumentException(string.Format("Index {0} is beyond the scope of possible value", value));
  79. m_Index = value;
  80. this.value = m_PossibleValues[m_Index];
  81. }
  82. }
  83. }
  84. /// <summary>
  85. /// Callback that will return the string to be set in the field's label.
  86. /// </summary>
  87. /// <param name="callback"></param>
  88. public void SetLabelCallback(Func<T, string> callback)
  89. {
  90. m_Callback = callback;
  91. }
  92. private PopupField(List<T> possibleValues)
  93. {
  94. if (possibleValues == null)
  95. throw new ArgumentNullException("possibleValues can't be null");
  96. m_PossibleValues = possibleValues;
  97. AddToClassList("popupField");
  98. }
  99. public PopupField(List<T> possibleValues, T defaultValue) :
  100. this(possibleValues)
  101. {
  102. if (defaultValue == null)
  103. throw new ArgumentNullException("defaultValue can't be null");
  104. if (!m_PossibleValues.Contains(defaultValue))
  105. throw new ArgumentException(string.Format("Default value {0} is not present in the list of possible values", defaultValue));
  106. // note: idx will be set when setting value
  107. value = defaultValue;
  108. }
  109. public PopupField(List<T> possibleValues, int defaultIndex) :
  110. this(possibleValues)
  111. {
  112. if (defaultIndex >= m_PossibleValues.Count || defaultIndex < 0)
  113. throw new ArgumentException(string.Format("Default Index {0} is beyond the scope of possible value", value));
  114. // note: value will be set when setting idx
  115. index = defaultIndex;
  116. }
  117. public void SetValueAndNotify(T newValue)
  118. {
  119. if (!EqualityComparer<T>.Default.Equals(newValue, value))
  120. {
  121. using (ChangeEvent<T> evt = ChangeEvent<T>.GetPooled(value, newValue))
  122. {
  123. value = newValue;
  124. if (m_valueCallback != null)
  125. m_valueCallback(evt);
  126. }
  127. }
  128. }
  129. public void OnValueChanged(EventCallback<ChangeEvent<T>> callback)
  130. {
  131. m_valueCallback = callback;
  132. RegisterCallback(callback);
  133. }
  134. protected override void ExecuteDefaultAction(EventBase evt)
  135. {
  136. base.ExecuteDefaultAction(evt);
  137. if (evt.GetEventTypeId() == MouseDownEvent.TypeId())
  138. OnMouseDown();
  139. }
  140. private void OnMouseDown()
  141. {
  142. var menu = new GenericMenu();
  143. foreach (T item in m_PossibleValues)
  144. {
  145. bool isSelected = EqualityComparer<T>.Default.Equals(item, value);
  146. menu.AddItem(new GUIContent(item.ToString()), isSelected,
  147. () => ChangeValueFromMenu(item));
  148. }
  149. var menuPosition = new Vector2(0.0f, layout.height);
  150. menuPosition = this.LocalToWorld(menuPosition);
  151. var menuRect = new Rect(menuPosition, Vector2.zero);
  152. menu.DropDown(menuRect);
  153. }
  154. private void ChangeValueFromMenu(T menuItem)
  155. {
  156. SetValueAndNotify(menuItem);
  157. }
  158. }
  159. #endif
  160. }