// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osuTK.Input; namespace osu.Framework.Testing { /// /// A test scene that provides a set of helper functions and structures for testing a . /// public abstract class MenuTestScene : ManualInputManagerTestScene { protected MenuStructure Menus; [SetUp] public new void SetUp() => Schedule(() => { Menu menu; Child = new Container { RelativeSizeAxes = Axes.Both, Child = menu = CreateMenu(), }; Menus = new MenuStructure(menu); }); /// /// Click an item in a menu. /// /// The level of menu our click targets. /// The item to click in the menu. protected void ClickItem(int menuIndex, int itemIndex) { InputManager.MoveMouseTo(Menus.GetSubStructure(menuIndex).GetMenuItems()[itemIndex]); InputManager.Click(MouseButton.Left); } protected abstract Menu CreateMenu(); /// /// Helper class used to retrieve various internal properties/items from a . /// protected class MenuStructure { private readonly Menu menu; public MenuStructure(Menu menu) { this.menu = menu; } /// /// Retrieves the s of the represented by this . /// public IReadOnlyList GetMenuItems() => menu.ChildrenOfType>().First().Children; /// /// Finds the index in the represented by this that /// has set to . /// public int GetSelectedIndex() { var items = GetMenuItems(); for (int i = 0; i < items.Count; i++) { var state = (MenuItemState)(items[i]?.GetType().GetProperty("State")?.GetValue(items[i]) ?? MenuItemState.NotSelected); if (state == MenuItemState.Selected) return i; } return -1; } /// /// Sets the at the specified index to a specified state. /// /// The index of the to set the state of. /// The state to be set. public void SetSelectedState(int index, MenuItemState state) { var item = GetMenuItems()[index]; item.GetType().GetProperty("State")?.SetValue(item, state); } /// /// Retrieves the sub- at an index-offset from the current . /// /// The sub- index. An index of 0 is the represented by this . public Menu GetSubMenu(int index) { var currentMenu = menu; for (int i = 0; i < index; i++) { if (currentMenu == null) break; var container = (CompositeDrawable)currentMenu.InternalChildren[1]; // ReSharper disable once ArrangeRedundantParentheses // Broken resharper inspection (https://youtrack.jetbrains.com/issue/RIDER-19843) currentMenu = (container.InternalChildren.Count > 0 ? container.InternalChildren[0] : null) as Menu; } return currentMenu; } /// /// Generates a new for the a sub-. /// /// The sub- index to generate the for. An index of 0 is the represented by this . public MenuStructure GetSubStructure(int index) => new MenuStructure(GetSubMenu(index)); } } }