using System; using UnityEngine; namespace UnityEditor.TestTools.TestRunner.GUI.Controls { /// /// A DropDown editor control accepting -based content providers. /// internal class SelectionDropDown : PopupWindowContent { private static readonly int k_ControlId = typeof(SelectionDropDown).GetHashCode(); private readonly ISelectionDropDownContentProvider m_ContentProvider; private readonly Vector2 m_ContentSize; private Vector2 m_ScrollPosition = Vector2.zero; /// /// Creates a new instance of the editor control. /// /// The content provider to use. public SelectionDropDown(ISelectionDropDownContentProvider contentProvider) { m_ContentProvider = contentProvider; var width = CalculateContentWidth(); var height = CalculateContentHeight(); m_ContentSize = new Vector2(width, height); } public override void OnOpen() { base.OnOpen(); editorWindow.wantsMouseMove = true; editorWindow.wantsMouseEnterLeaveWindow = true; } public override void OnClose() { GUIUtility.hotControl = 0; base.OnClose(); } public override Vector2 GetWindowSize() { return m_ContentSize; } public override void OnGUI(Rect rect) { var evt = Event.current; var contentRect = new Rect(Styles.TopMargin, 0, 1, m_ContentSize.y); m_ScrollPosition = UnityEngine.GUI.BeginScrollView(rect, m_ScrollPosition, contentRect); { var yPos = Styles.TopMargin; for (var i = 0; i < m_ContentProvider.Count; ++i) { var itemRect = new Rect(0, yPos, rect.width, Styles.LineHeight); var separatorOffset = 0f; switch (evt.type) { case EventType.Repaint: var content = new GUIContent(m_ContentProvider.GetName(i)); var hover = itemRect.Contains(evt.mousePosition); var on = m_ContentProvider.IsSelected(i); Styles.MenuItem.Draw(itemRect, content, hover, false, on, false); separatorOffset = DrawSeparator(i, itemRect); break; case EventType.MouseDown: if (evt.button == 0 && itemRect.Contains(evt.mousePosition)) { m_ContentProvider.SelectItem(i); if (!m_ContentProvider.IsMultiSelection) { editorWindow.Close(); } evt.Use(); } break; case EventType.MouseEnterWindow: GUIUtility.hotControl = k_ControlId; evt.Use(); break; case EventType.MouseLeaveWindow: GUIUtility.hotControl = 0; evt.Use(); break; case EventType.MouseUp: case EventType.MouseMove: evt.Use(); break; } yPos += Styles.LineHeight + separatorOffset; } } UnityEngine.GUI.EndScrollView(); } private float CalculateContentWidth() { var maxItemWidth = 0f; for (var i = 0; i < m_ContentProvider.Count; ++i) { var itemContent = new GUIContent(m_ContentProvider.GetName(i)); var itemWidth = Styles.MenuItem.CalcSize(itemContent).x; maxItemWidth = Mathf.Max(itemWidth, maxItemWidth); } return maxItemWidth; } private float CalculateContentHeight() { return m_ContentProvider.Count * Styles.LineHeight + m_ContentProvider.SeparatorIndices.Length * Styles.SeparatorHeight + Styles.TopMargin + Styles.BottomMargin; } private float DrawSeparator(int i, Rect itemRect) { if (Array.IndexOf(m_ContentProvider.SeparatorIndices, i) < 0) { return 0f; } var separatorRect = GetSeparatorRect(itemRect); DrawRect(separatorRect, Styles.SeparatorColor); return Styles.SeparatorHeight; } private static Rect GetSeparatorRect(Rect itemRect) { var x = itemRect.x + Styles.SeparatorMargin; var y = itemRect.y + itemRect.height + Styles.SeparatorHeight * 0.15f; var width = itemRect.width - 2 * Styles.SeparatorMargin; const float height = 1f; return new Rect(x, y, width, height); } private static void DrawRect(Rect rect, Color color) { var originalColor = UnityEngine.GUI.color; UnityEngine.GUI.color *= color; UnityEngine.GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture); UnityEngine.GUI.color = originalColor; } private static class Styles { public const float LineHeight = EditorGUI.kSingleLineHeight; public const float TopMargin = 3f; public const float BottomMargin = 1f; public const float SeparatorHeight = 4f; public const float SeparatorMargin = 3f; public static readonly GUIStyle MenuItem = "MenuItem"; public static readonly Color SeparatorColor = EditorGUIUtility.isProSkin ? new Color(0.32f, 0.32f, 0.32f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f); } } }