diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneDropdown.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneDropdown.cs index c1d247b409..9b6e604ffa 100644 --- a/osu.Framework.Tests/Visual/UserInterface/TestSceneDropdown.cs +++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneDropdown.cs @@ -312,6 +312,42 @@ void checkOrder(int index, string item) => AddAssert($"item #{index + 1} is '{it () => Is.EqualTo(item)); } + [Test] + public void TestKeyboardSelectionOrder() + { + TestDropdown testDropdown = null!; + BindableList bindableList = null!; + + AddStep("setup dropdown", () => testDropdown = createDropdown()); + + AddStep("bind source", () => testDropdown.ItemSource = bindableList = new BindableList()); + + AddStep("add items to bindable", () => bindableList.AddRange(new[] { "one", "two", "three" }.Select(s => new TestModel(s)))); + + AddStep("hover dropdown", () => InputManager.MoveMouseTo(testDropdown.Header)); + + AddStep("select first item", () => InputManager.Keys(PlatformAction.MoveToListStart)); + AddAssert("'one' is selected", () => testDropdown.Current.Value?.Identifier == "one"); + + AddStep("select next item", () => + { + InputManager.Key(Key.Down); + }); + AddAssert("'two' is selected", () => testDropdown.Current.Value?.Identifier == "two"); + + AddStep("add 'three-halves'", () => bindableList.Add("three-halves")); + AddStep("move 'three-halves'", () => bindableList.Move(3, 1)); + + AddStep("select previous item", () => + { + InputManager.Key(Key.Up); + }); + AddAssert("'three-halves' is selected", () => testDropdown.Current.Value?.Identifier == "three-halves"); + + AddStep("select last item", () => InputManager.Keys(PlatformAction.MoveToListEnd)); + AddAssert("'three' is selected", () => testDropdown.Current.Value?.Identifier == "three"); + } + [Test] public void TestExternalManagement() { diff --git a/osu.Framework/Graphics/UserInterface/Dropdown.cs b/osu.Framework/Graphics/UserInterface/Dropdown.cs index 5a17242c4c..ef57cfea7e 100644 --- a/osu.Framework/Graphics/UserInterface/Dropdown.cs +++ b/osu.Framework/Graphics/UserInterface/Dropdown.cs @@ -289,7 +289,7 @@ private void selectionKeyPressed(DropdownHeader.DropdownSelectionAction action) if (!MenuItems.Any()) return; - var dropdownMenuItems = MenuItems.ToList(); + var dropdownMenuItems = Menu.VisibleMenuItems.Select(item => (DropdownMenuItem)item.Item).ToList(); switch (action) { @@ -505,7 +505,7 @@ private void clearPreselection(MenuState obj) PreselectItem(null); } - protected internal IEnumerable VisibleMenuItems => Children.OfType().Where(i => i.MatchingFilter); + protected internal IEnumerable VisibleMenuItems => Children.OrderBy(itemsFlow.GetLayoutPosition).OfType().Where(i => i.MatchingFilter); protected internal IEnumerable MenuItemsInView => VisibleMenuItems.Where(item => !item.IsMaskedAway); public DrawableDropdownMenuItem PreselectedItem => VisibleMenuItems.FirstOrDefault(c => c.IsPreSelected)