using AtomUI.Controls.Primitives; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Threading; using Avalonia.VisualTree; using Shouldly; using Xunit; using AtomUIMenu = AtomUI.Desktop.Controls.Menu; using AtomUIMenuItem = AtomUI.Desktop.Controls.MenuItem; using AtomUIPopup = AtomUI.Desktop.Controls.Popup; using AtomUIWindow = AtomUI.Desktop.Controls.Window; namespace AtomUI.Desktop.Controls.Tests.Menu; public class MenuPinnedOpenTests { static MenuPinnedOpenTests() { AvaloniaTestApp.EnsureInitialized(); } [Fact] public void Popup_Pin_Opens_Menu_Active_Submenu_And_Physical_Popup() { var parentItem = new AtomUIMenuItem { Header = "File" }; parentItem.Items.Add(new AtomUIMenuItem { Header = "Open" }); var menu = new AtomUIMenu { IsMotionEnabled = false, Width = 320 }; menu.Items.Add(parentItem); var window = ShowInWindow(menu); try { menu.IsPopupPinnedOpen = true; Dispatcher.UIThread.RunJobs(); var popup = FindPopup(parentItem); menu.IsOpen.ShouldBeTrue(); parentItem.IsSubMenuOpen.ShouldBeTrue(); popup.IsPopupPinnedOpen.ShouldBeTrue(); popup.IsOpen.ShouldBeTrue(); } finally { window.Close(); Dispatcher.UIThread.RunJobs(); } } [Fact] public void Popup_Pin_Rejects_Menu_Close_Requests() { var parentItem = new AtomUIMenuItem { Header = "File" }; parentItem.Items.Add(new AtomUIMenuItem { Header = "Open" }); var menu = new AtomUIMenu { IsMotionEnabled = false, Width = 320 }; menu.Items.Add(parentItem); var window = ShowInWindow(menu); try { menu.IsPopupPinnedOpen = true; Dispatcher.UIThread.RunJobs(); var popup = FindPopup(parentItem); menu.Close(); Dispatcher.UIThread.RunJobs(); menu.IsOpen.ShouldBeTrue(); parentItem.IsSubMenuOpen.ShouldBeTrue(); popup.IsOpen.ShouldBeTrue(); menu.CloseImmediately(); Dispatcher.UIThread.RunJobs(); menu.IsOpen.ShouldBeTrue(); parentItem.IsSubMenuOpen.ShouldBeTrue(); popup.IsOpen.ShouldBeTrue(); } finally { window.Close(); Dispatcher.UIThread.RunJobs(); } } [Fact] public void Popup_Pin_Rejects_Active_Submenu_Collapse() { var parentItem = new AtomUIMenuItem { Header = "File" }; parentItem.Items.Add(new AtomUIMenuItem { Header = "Open" }); var menu = new AtomUIMenu { IsMotionEnabled = false, Width = 320 }; menu.Items.Add(parentItem); var window = ShowInWindow(menu); try { menu.IsPopupPinnedOpen = true; Dispatcher.UIThread.RunJobs(); parentItem.SetCurrentValue(MenuItem.IsSubMenuOpenProperty, false); Dispatcher.UIThread.RunJobs(); parentItem.IsSubMenuOpen.ShouldBeTrue(); FindPopup(parentItem).IsOpen.ShouldBeTrue(); } finally { window.Close(); Dispatcher.UIThread.RunJobs(); } } [Fact] public void Popup_Pin_Closes_For_Detach_And_Reopens_After_Reattach() { var parentItem = new AtomUIMenuItem { Header = "File" }; parentItem.Items.Add(new AtomUIMenuItem { Header = "Open" }); var menu = new AtomUIMenu { IsMotionEnabled = false, Width = 320 }; menu.Items.Add(parentItem); var window = ShowInWindow(menu); try { menu.IsPopupPinnedOpen = true; Dispatcher.UIThread.RunJobs(); var popup = FindPopup(parentItem); var windowContent = window.Content; window.Content = null; Dispatcher.UIThread.RunJobs(); menu.IsOpen.ShouldBeFalse(); parentItem.IsSubMenuOpen.ShouldBeFalse(); parentItem.IsPopupPinnedOpen.ShouldBeFalse(); popup.IsPopupPinnedOpen.ShouldBeFalse(); popup.IsOpen.ShouldBeFalse(); window.Content = windowContent; Dispatcher.UIThread.RunJobs(); menu.IsOpen.ShouldBeTrue(); parentItem.IsSubMenuOpen.ShouldBeTrue(); popup.IsOpen.ShouldBeTrue(); } finally { window.Close(); Dispatcher.UIThread.RunJobs(); } } [Fact] public void Popup_Unpin_Leaves_Menu_Open_And_Restores_Normal_Close() { var parentItem = new AtomUIMenuItem { Header = "File" }; parentItem.Items.Add(new AtomUIMenuItem { Header = "Open" }); var menu = new AtomUIMenu { IsMotionEnabled = false, Width = 320 }; menu.Items.Add(parentItem); var window = ShowInWindow(menu); try { menu.IsPopupPinnedOpen = true; Dispatcher.UIThread.RunJobs(); var popup = FindPopup(parentItem); menu.IsPopupPinnedOpen = false; Dispatcher.UIThread.RunJobs(); menu.IsOpen.ShouldBeTrue(); parentItem.IsSubMenuOpen.ShouldBeTrue(); parentItem.IsPopupPinnedOpen.ShouldBeFalse(); popup.IsPopupPinnedOpen.ShouldBeFalse(); popup.IsOpen.ShouldBeTrue(); menu.Close(); Dispatcher.UIThread.RunJobs(); menu.IsOpen.ShouldBeFalse(); parentItem.IsSubMenuOpen.ShouldBeFalse(); popup.IsOpen.ShouldBeFalse(); } finally { window.Close(); Dispatcher.UIThread.RunJobs(); } } [Fact] public void Popup_Pin_Releases_Removed_Item_And_Transfers_To_The_Next_Submenu() { var firstItem = new AtomUIMenuItem { Header = "File" }; firstItem.Items.Add(new AtomUIMenuItem { Header = "Open" }); var secondItem = new AtomUIMenuItem { Header = "Edit" }; secondItem.Items.Add(new AtomUIMenuItem { Header = "Copy" }); var menu = new AtomUIMenu { IsMotionEnabled = false, Width = 320 }; menu.Items.Add(firstItem); menu.Items.Add(secondItem); var window = ShowInWindow(menu); try { menu.IsPopupPinnedOpen = true; Dispatcher.UIThread.RunJobs(); var firstPopup = FindPopup(firstItem); firstPopup.IsOpen.ShouldBeTrue(); menu.Items.Remove(firstItem); Dispatcher.UIThread.RunJobs(); window.UpdateLayout(); firstItem.IsPopupPinnedOpen.ShouldBeFalse(); firstItem.IsSubMenuOpen.ShouldBeFalse(); firstPopup.IsPopupPinnedOpen.ShouldBeFalse(); firstPopup.IsOpen.ShouldBeFalse(); secondItem.IsPopupPinnedOpen.ShouldBeTrue(); secondItem.IsSubMenuOpen.ShouldBeTrue(); FindPopup(secondItem).IsOpen.ShouldBeTrue(); } finally { window.Close(); Dispatcher.UIThread.RunJobs(); } } private static AtomUIPopup FindPopup(Control root) { return root.GetVisualDescendants() .OfType() .Single(item => item.Name == "PART_Popup"); } private static AtomUIWindow ShowInWindow(Control content) { var overlayPanel = new ScopeAwareOverlayLayerPanel { Width = 420, Height = 240 }; overlayPanel.Children.Add(content); var visualLayerManager = new VisualLayerManager { Child = overlayPanel }; var window = new AtomUIWindow { Width = 420, Height = 240, Content = visualLayerManager }; window.Show(); Dispatcher.UIThread.RunJobs(); return window; } }