// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using System.Linq; namespace FlaxEngine.GUI { /// /// Dropdown menu control allows to choose one item from the provided collection of options. /// /// public class Dropdown : ContainerControl { /// /// The root control used by the to show the items collections and track item selecting event. /// /// [HideInEditor] protected class DropdownRoot : Panel { /// /// Occurs when popup lost focus. /// public Action LostFocus; /// /// The selected control. Used to scroll to the control on popup creation. /// public ContainerControl SelectedControl = null; /// /// The main panel used to hold the items. /// public Panel MainPanel = null; /// public override void OnEndContainsFocus() { base.OnEndContainsFocus(); // Dont lose focus when using panel. Does prevent LostFocus even from being called if clicking inside of the panel. if (MainPanel != null && MainPanel.IsMouseOver && !MainPanel.ContainsFocus) { MainPanel.Focus(); return; } // Call event after this 'focus contains flag' propagation ends to prevent focus issues if (LostFocus != null) Scripting.RunOnUpdate(LostFocus); } private static DropdownLabel FindItem(Control control) { if (control is DropdownLabel item) return item; if (control is ContainerControl containerControl) { foreach (var child in containerControl.Children) { item = FindItem(child); if (item != null) return item; } } return null; } /// public override Control OnNavigate(NavDirection direction, Float2 location, Control caller, List visited) { if (IsFocused) { // Dropdown root is focused if (direction == NavDirection.Down) { // Pick the first item return FindItem(this); } // Close popup Defocus(); return null; } return base.OnNavigate(direction, location, caller, visited); } /// public override void OnSubmit() { Defocus(); base.OnSubmit(); } /// public override bool OnKeyDown(KeyboardKeys key) { if (key == KeyboardKeys.Escape) { Defocus(); return true; } return base.OnKeyDown(key); } /// public override bool OnMouseDown(Float2 location, MouseButton button) { if (base.OnMouseDown(location, button)) return true; // Close on click outside the popup if (!new Rectangle(Float2.Zero, Size).Contains(ref location)) { Defocus(); return true; } return false; } /// public override bool OnTouchDown(Float2 location, int pointerId) { if (base.OnTouchDown(location, pointerId)) return true; // Close on touch outside the popup if (!new Rectangle(Float2.Zero, Size).Contains(ref location)) { Defocus(); return true; } return false; } /// public override void OnDestroy() { LostFocus = null; MainPanel = null; SelectedControl = null; base.OnDestroy(); } } [HideInEditor] private class DropdownLabel : Label { public Action