From c15d9bcc575f93410f35e90b84dabfe2c041aaa8 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Thu, 20 Oct 2022 08:15:54 -0600 Subject: [PATCH 01/10] refactoring menutests --- Terminal.Gui/Views/Menu.cs | 10 +- UICatalog/Scenarios/CsvEditor.cs | 10 +- UnitTests/ContextMenuTests.cs | 8 +- UnitTests/MenuTests.cs | 167 +++++++++++++++++-------------- UnitTests/PosTests.cs | 4 +- 5 files changed, 109 insertions(+), 90 deletions(-) diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 804ddb5ed..abab9c711 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -1024,6 +1024,8 @@ namespace Terminal.Gui { isCleaning = false; } + static int leftPadding = 1; + static int rightPadding = 1; /// public override void Redraw (Rect bounds) { @@ -1033,7 +1035,7 @@ namespace Terminal.Gui { Driver.AddRune (' '); Move (1, 0); - int pos = 1; + int pos = 0; for (int i = 0; i < Menus.Length; i++) { var menu = Menus [i]; @@ -1050,8 +1052,8 @@ namespace Terminal.Gui { hotColor = GetNormalColor (); normalColor = GetNormalColor (); } - DrawHotString (menu.Help.IsEmpty ? $" {menu.Title} " : $" {menu.Title} {menu.Help} ", hotColor, normalColor); - pos += 1 + menu.TitleLength + (menu.Help.ConsoleWidth > 0 ? menu.Help.ConsoleWidth + 2 : 0) + 2; + DrawHotString (menu.Help.IsEmpty ? $" {menu.Title} " : $" {menu.Title} ({menu.Help}) ", hotColor, normalColor); + pos += leftPadding + menu.TitleLength + (menu.Help.ConsoleWidth > 0 ? menu.Help.ConsoleWidth + 3 : 0) + rightPadding; } PositionCursor (); } @@ -1073,7 +1075,7 @@ namespace Terminal.Gui { } return; } else { - pos += 1 + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + 2; + pos += leftPadding + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 3 : 0) + rightPadding; } } } diff --git a/UICatalog/Scenarios/CsvEditor.cs b/UICatalog/Scenarios/CsvEditor.cs index e344b2325..ab83b487d 100644 --- a/UICatalog/Scenarios/CsvEditor.cs +++ b/UICatalog/Scenarios/CsvEditor.cs @@ -43,12 +43,14 @@ namespace UICatalog.Scenarios { Height = Dim.Fill (1), }; - var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_File", new MenuItem [] { + var fileMenu = new MenuBarItem ("_File", new MenuItem [] { new MenuItem ("_Open CSV", "", () => Open()), new MenuItem ("_Save", "", () => Save()), - new MenuItem ("_Quit", "", () => Quit()), - }), + new MenuItem ("_Quit", "Quits The App", () => Quit()), + }); + //fileMenu.Help = "Help"; + var menu = new MenuBar (new MenuBarItem [] { + fileMenu, new MenuBarItem ("_Edit", new MenuItem [] { new MenuItem ("_New Column", "", () => AddColumn()), new MenuItem ("_New Row", "", () => AddRow()), diff --git a/UnitTests/ContextMenuTests.cs b/UnitTests/ContextMenuTests.cs index a0c88168a..aab102b6c 100644 --- a/UnitTests/ContextMenuTests.cs +++ b/UnitTests/ContextMenuTests.cs @@ -592,7 +592,7 @@ namespace Terminal.Gui.Core { Assert.Equal (new Point (9, 3), tf.ContextMenu.Position); Application.Top.Redraw (Application.Top.Bounds); var expected = @" - File Edit + File Edit Label: TextField @@ -612,7 +612,7 @@ namespace Terminal.Gui.Core { "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 32, 17), pos); + Assert.Equal (new Rect (1, 0, 32, 17), pos); } [Fact, AutoInitShutdown] @@ -656,7 +656,7 @@ namespace Terminal.Gui.Core { Assert.Equal (new Point (10, 5), tf.ContextMenu.Position); Application.Top.Redraw (Application.Top.Bounds); var expected = @" - File Edit + File Edit ┌ Window ──────────────────────────────────┐ │ │ │ │ @@ -676,7 +676,7 @@ namespace Terminal.Gui.Core { "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 44, 17), pos); + Assert.Equal (new Rect (1, 0, 44, 17), pos); } [Fact, AutoInitShutdown] diff --git a/UnitTests/MenuTests.cs b/UnitTests/MenuTests.cs index 77c336b8a..cedb32aec 100644 --- a/UnitTests/MenuTests.cs +++ b/UnitTests/MenuTests.cs @@ -1074,11 +1074,11 @@ Edit Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); var expected = @" - File Edit + File Edit "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 1), pos); + Assert.Equal (new Rect (1, 0, 11, 1), pos); Assert.True (menu.ProcessKey (new (Key.N, null))); Application.MainLoop.MainIteration (); @@ -1088,11 +1088,11 @@ Edit Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit + File Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 1), pos); + Assert.Equal (new Rect (1, 0, 11, 1), pos); Assert.True (menu.ProcessKey (new (Key.CursorRight, null))); Assert.True (menu.ProcessKey (new (Key.C, null))); @@ -1124,14 +1124,14 @@ Edit Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); var expected = @" - File Edit -┌──────┐ -│ New │ -└──────┘ + File Edit +┌──────┐ +│ New │ +└──────┘ "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 4), pos); + Assert.Equal (new Rect (1, 0, 11, 4), pos); Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.N, null))); Application.MainLoop.MainIteration (); @@ -1141,7 +1141,7 @@ Edit Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit + File Edit ┌───────┐ │ Copy │ └───────┘ @@ -1158,89 +1158,104 @@ Edit [Fact, AutoInitShutdown] public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKeys () { - // With HotKeys + var firstMenuBarText = "File"; + var firstMenuBarItemText = "New"; + var secondMenuBarText = "Edit"; + var secondMenuBarItemText = "Copy"; + + // Define expected MenuBar + // " File New " + var expectedMenuBarText = " " + firstMenuBarText + " " + " " + secondMenuBarText + " "; + + // Define expected menu frame + // "┌──────┐" + // "│ New │" + // "└──────┘" + var d = ((FakeDriver)Application.Driver); + // BUGBUG: The extra 4 spaces on these should not be there + var expectedFirstTopRow = $"{d.ULCorner}{new String (d.HLine.ToString () [0], firstMenuBarItemText.Length + 3)}{d.URCorner} "; + var expectedFirstBottomRow = $"{d.LLCorner}{new String (d.HLine.ToString () [0], firstMenuBarItemText.Length + 3)}{d.LRCorner} "; + + var expectedSecondTopRow = $"{d.ULCorner}{new String (d.HLine.ToString () [0], secondMenuBarItemText.Length + 3)}{d.URCorner}"; + var expectedSecondBottomRow = $"{d.LLCorner}{new String (d.HLine.ToString () [0], secondMenuBarItemText.Length + 3)}{d.LRCorner}"; + + var expectedClosed = " " + firstMenuBarText + " " + " " + secondMenuBarText + "" + "\n"; + + var expectedFirstMenuOpen = " " + firstMenuBarText + " " + " " + secondMenuBarText + "" + "\n" + + expectedFirstTopRow + "\n" + + $"{d.VLine} {firstMenuBarItemText} {d.VLine}" + " \n" + + expectedFirstBottomRow + "\n"; + + var expectedSecondMenuOpen = " " + firstMenuBarText + " " + " " + secondMenuBarText + " " + "\n" + + new String (' ', firstMenuBarItemText.Length + 4) + expectedSecondTopRow + "\n" + + new String (' ', firstMenuBarItemText.Length + 4) + $"{d.VLine} {secondMenuBarItemText} {d.VLine}" + "\n" + + new String (' ', firstMenuBarItemText.Length + 4) + expectedSecondBottomRow + "\n"; + + // Test without HotKeys first var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_File", new MenuItem [] { - new MenuItem ("_New", "", null) + new MenuBarItem (firstMenuBarText, new MenuItem [] { + new MenuItem (firstMenuBarItemText, "", null) }), - new MenuBarItem ("_Edit", new MenuItem [] { - new MenuItem ("_Copy", "", null) + new MenuBarItem (secondMenuBarText, new MenuItem [] { + new MenuItem (secondMenuBarItemText, "", null) }) }); Application.Top.Add (menu); + // Open first Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - var expected = @" - File Edit -┌──────┐ -│ New │ -└──────┘ -"; - - var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 4), pos); + var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedFirstMenuOpen, output); + Assert.Equal (1, pos.X); + Assert.Equal (0, pos.Y); + // Open second Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.CursorRight, null))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit - ┌───────┐ - │ Copy │ - └───────┘ -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 16, 4), pos); + pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedSecondMenuOpen, output); + // Close menu Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit -"; + pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedClosed, output); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 1), pos); + Application.Top.Remove (menu); - // Without HotKeys + // Now test WITH HotKeys menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("File", new MenuItem [] { - new MenuItem ("New", "", null) + new MenuBarItem ("_" + firstMenuBarText, new MenuItem [] { + new MenuItem ("_" + firstMenuBarItemText, "", null) }), - new MenuBarItem ("Edit", new MenuItem [] { - new MenuItem ("Copy", "", null) + new MenuBarItem ("_" + secondMenuBarText, new MenuItem [] { + new MenuItem ("_" + secondMenuBarItemText, "", null) }) }); + Application.Top.Add (menu); + + // Open first Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit -┌──────┐ -│ New │ -└──────┘ -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 4), pos); + pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedFirstMenuOpen, output); + Assert.Equal (1, pos.X); + Assert.Equal (0, pos.Y); + // Open second Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.CursorRight, null))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit - ┌───────┐ - │ Copy │ - └───────┘ -"; + pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedSecondMenuOpen, output); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 16, 4), pos); + // Close menu + Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); + Assert.False (menu.IsMenuOpen); + Application.Top.Redraw (Application.Top.Bounds); + pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedClosed, output); } [Fact, AutoInitShutdown] @@ -1261,24 +1276,24 @@ Edit Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); var expected = @" - File Edit + File Edit ┌──────┐ │ New │ └──────┘ "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 4), pos); + Assert.Equal (new Rect (1, 0, 11, 4), pos); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit + File Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 13, 1), pos); + Assert.Equal (new Rect (1, 0, 11, 1), pos); } [Fact] @@ -1320,7 +1335,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); var expected = @" - File Edit Format + File Edit Format ┌──────┐ │ New │ └──────┘ @@ -1334,7 +1349,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); @@ -1345,7 +1360,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format ┌───────┐ │ Wrap │ └───────┘ @@ -1359,7 +1374,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); @@ -1370,7 +1385,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format ┌──────┐ │ New │ └──────┘ @@ -1384,7 +1399,7 @@ Edit Assert.True (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); @@ -1414,7 +1429,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); var expected = @" - File Edit Format + File Edit Format ┌──────┐ │ New │ └──────┘ @@ -1428,7 +1443,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); @@ -1439,7 +1454,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format ┌───────┐ │ Wrap │ └───────┘ @@ -1453,7 +1468,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); @@ -1464,7 +1479,7 @@ Edit Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format ┌──────┐ │ New │ └──────┘ @@ -1478,7 +1493,7 @@ Edit Assert.True (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); expected = @" - File Edit Format + File Edit Format "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); diff --git a/UnitTests/PosTests.cs b/UnitTests/PosTests.cs index b3efecf0b..528a722eb 100644 --- a/UnitTests/PosTests.cs +++ b/UnitTests/PosTests.cs @@ -247,7 +247,7 @@ namespace Terminal.Gui.Core { win.Frame.Right, win.Frame.Bottom)); Assert.Equal (new Rect (0, 20, 78, 1), label.Frame); var expected = @" - Menu + Menu ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ │ @@ -310,7 +310,7 @@ namespace Terminal.Gui.Core { win.Frame.Right, win.Frame.Bottom)); Assert.Equal (new Rect (0, 20, 78, 1), label.Frame); var expected = @" - Menu + Menu ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ │ From eb7fe9f126778ee7169db36b6176bae223926f58 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Thu, 20 Oct 2022 15:38:50 -0600 Subject: [PATCH 02/10] further progress --- Terminal.Gui/Views/Menu.cs | 1 + UnitTests/MenuTests.cs | 264 +++++++++++++++++-------------------- 2 files changed, 124 insertions(+), 141 deletions(-) diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index abab9c711..bc4eb3876 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -1068,6 +1068,7 @@ namespace Terminal.Gui { for (int i = 0; i < Menus.Length; i++) { if (i == selected) { pos++; + // BUGBUG: This if is not needed if (IsMenuOpen) Move (pos + 1, 0); else { diff --git a/UnitTests/MenuTests.cs b/UnitTests/MenuTests.cs index cedb32aec..9b65cd4d5 100644 --- a/UnitTests/MenuTests.cs +++ b/UnitTests/MenuTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Xunit; using Xunit.Abstractions; +using static Terminal.Gui.Views.MenuTests; namespace Terminal.Gui.Views { public class MenuTests { @@ -1100,21 +1101,67 @@ Edit Assert.True (copyAction); } + // Defines the expected strings for a Menu + // + // File Edit + // New Copy + public class ExpectedMenu : MenuBar { + FakeDriver d = ((FakeDriver)Application.Driver); + + public string expectedMenuBarText => " " + Menus [0].Title.ToString () + " " + " " + Menus [1].Title.ToString () + " "; + + // The expected strings when the menu is closed + public string expectedClosed => " " + Menus [0].Title.ToString () + " " + " " + Menus [1].Title.ToString () + "" + "\n"; + + // left padding for the sub menu + public string padding (int i) => i > 0 ? new string (' ', Menus [i].Children [0].TitleLength + 4) : ""; + + // Define expected menu frame + // "┌──────┐" + // "│ New │" + // "└──────┘" + // BUGBUG: The extra 4 spaces on these should not be there + public string expectedTopRow (int i) => $"{d.ULCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.URCorner} \n"; + public string expectedMenuItemRow (int i) => $"{d.VLine} {Menus [i].Children[0].Title} {d.VLine}" + " \n"; + public string expectedBottomRow (int i) => $"{d.LLCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.LRCorner} \n"; + + // The fulll expected string for an open sub menu + public string expectedSubMenuOpen (int i) => expectedClosed + + padding (i) + expectedTopRow(i) + + padding (i) + expectedMenuItemRow (i) + + padding (i) + expectedBottomRow (i); + + public ExpectedMenu (MenuBarItem [] menus) : base (menus) + { + } + } + [Fact, AutoInitShutdown] public void HotKey_MenuBar_ProcessHotKey_Menu_ProcessKey () { var newAction = false; var copyAction = false; - var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_File", new MenuItem [] { - new MenuItem ("_New", "", () => newAction = true) + // Define the expected menu + var twoMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { + new MenuBarItem ("File", new MenuItem [] { + new MenuItem ("New", "", null) }), - new MenuBarItem ("_Edit", new MenuItem [] { - new MenuItem ("_Copy", "", () => copyAction = true) + new MenuBarItem ("Edit", new MenuItem [] { + new MenuItem ("Copy", "", null) }) }); + // The real menu + var menu = new MenuBar (new MenuBarItem [] { + new MenuBarItem ("_" + twoMenuItemMenu.Menus[0].Title, new MenuItem [] { + new MenuItem ("_" + twoMenuItemMenu.Menus[0].Children[0].Title, "", () => newAction = true) + }), + new MenuBarItem ("_" + twoMenuItemMenu.Menus[1].Title, new MenuItem [] { + new MenuItem ("_" + twoMenuItemMenu.Menus[1].Children[0].Title, "", () => copyAction = true) + }), + }); + Application.Top.Add (menu); Assert.False (newAction); @@ -1123,15 +1170,7 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.AltMask | Key.F, new KeyModifiers () { Alt = true }))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - var expected = @" - File Edit -┌──────┐ -│ New │ -└──────┘ -"; - - var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 0, 11, 4), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedSubMenuOpen(0), output); Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.N, null))); Application.MainLoop.MainIteration (); @@ -1140,15 +1179,7 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.AltMask | Key.E, new KeyModifiers () { Alt = true }))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit - ┌───────┐ - │ Copy │ - └───────┘ -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 16, 4), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedSubMenuOpen (1), output); Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.C, null))); Application.MainLoop.MainIteration (); @@ -1158,46 +1189,23 @@ Edit [Fact, AutoInitShutdown] public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKeys () { - var firstMenuBarText = "File"; - var firstMenuBarItemText = "New"; - var secondMenuBarText = "Edit"; - var secondMenuBarItemText = "Copy"; - - // Define expected MenuBar - // " File New " - var expectedMenuBarText = " " + firstMenuBarText + " " + " " + secondMenuBarText + " "; - - // Define expected menu frame - // "┌──────┐" - // "│ New │" - // "└──────┘" - var d = ((FakeDriver)Application.Driver); - // BUGBUG: The extra 4 spaces on these should not be there - var expectedFirstTopRow = $"{d.ULCorner}{new String (d.HLine.ToString () [0], firstMenuBarItemText.Length + 3)}{d.URCorner} "; - var expectedFirstBottomRow = $"{d.LLCorner}{new String (d.HLine.ToString () [0], firstMenuBarItemText.Length + 3)}{d.LRCorner} "; - - var expectedSecondTopRow = $"{d.ULCorner}{new String (d.HLine.ToString () [0], secondMenuBarItemText.Length + 3)}{d.URCorner}"; - var expectedSecondBottomRow = $"{d.LLCorner}{new String (d.HLine.ToString () [0], secondMenuBarItemText.Length + 3)}{d.LRCorner}"; - - var expectedClosed = " " + firstMenuBarText + " " + " " + secondMenuBarText + "" + "\n"; - - var expectedFirstMenuOpen = " " + firstMenuBarText + " " + " " + secondMenuBarText + "" + "\n" + - expectedFirstTopRow + "\n" + - $"{d.VLine} {firstMenuBarItemText} {d.VLine}" + " \n" + - expectedFirstBottomRow + "\n"; - - var expectedSecondMenuOpen = " " + firstMenuBarText + " " + " " + secondMenuBarText + " " + "\n" + - new String (' ', firstMenuBarItemText.Length + 4) + expectedSecondTopRow + "\n" + - new String (' ', firstMenuBarItemText.Length + 4) + $"{d.VLine} {secondMenuBarItemText} {d.VLine}" + "\n" + - new String (' ', firstMenuBarItemText.Length + 4) + expectedSecondBottomRow + "\n"; - + // Define the expected menu + var twoMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { + new MenuBarItem ("File", new MenuItem [] { + new MenuItem ("12", "", null) + }), + new MenuBarItem ("Edit", new MenuItem [] { + new MenuItem ("Copy", "", null) + }) + }); + // Test without HotKeys first var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem (firstMenuBarText, new MenuItem [] { - new MenuItem (firstMenuBarItemText, "", null) + new MenuBarItem (twoMenuItemMenu.Menus[0].Title, new MenuItem [] { + new MenuItem (twoMenuItemMenu.Menus[0].Children[0].Title, "", null) }), - new MenuBarItem (secondMenuBarText, new MenuItem [] { - new MenuItem (secondMenuBarItemText, "", null) + new MenuBarItem (twoMenuItemMenu.Menus[1].Title, new MenuItem [] { + new MenuItem (twoMenuItemMenu.Menus[1].Children[0].Title, "", null) }) }); @@ -1207,32 +1215,30 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedFirstMenuOpen, output); - Assert.Equal (1, pos.X); - Assert.Equal (0, pos.Y); - + GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (0), output); + // Open second Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.CursorRight, null))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedSecondMenuOpen, output); - + GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (1), output); + // Close menu Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedClosed, output); Application.Top.Remove (menu); // Now test WITH HotKeys menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_" + firstMenuBarText, new MenuItem [] { - new MenuItem ("_" + firstMenuBarItemText, "", null) + new MenuBarItem ("_" + twoMenuItemMenu.Menus[0].Title, new MenuItem [] { + new MenuItem ("_" + twoMenuItemMenu.Menus[0].Children[0].Title, "", null) + }), + new MenuBarItem ("_" + twoMenuItemMenu.Menus[1].Title, new MenuItem [] { + new MenuItem ("_" + twoMenuItemMenu.Menus[1].Children[0].Title, "", null) }), - new MenuBarItem ("_" + secondMenuBarText, new MenuItem [] { - new MenuItem ("_" + secondMenuBarItemText, "", null) - }) }); Application.Top.Add (menu); @@ -1241,59 +1247,56 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedFirstMenuOpen, output); - Assert.Equal (1, pos.X); - Assert.Equal (0, pos.Y); + GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (0), output); // Open second Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.CursorRight, null))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedSecondMenuOpen, output); + GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (1), output); // Close menu Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedClosed, output); } [Fact, AutoInitShutdown] public void MenuBar_ButtonPressed_Open_The_Menu_ButtonPressed_Again_Close_The_Menu () { - var menu = new MenuBar (new MenuBarItem [] { + // Define the expected menu + var twoMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { - new MenuItem ("New", "", null) + new MenuItem ("Open", "", null) }), new MenuBarItem ("Edit", new MenuItem [] { new MenuItem ("Copy", "", null) }) }); + // Test without HotKeys first + var menu = new MenuBar (new MenuBarItem [] { + new MenuBarItem ("_" + twoMenuItemMenu.Menus[0].Title, new MenuItem [] { + new MenuItem ("_" + twoMenuItemMenu.Menus[0].Children[0].Title, "", null) + }), + new MenuBarItem ("_" + twoMenuItemMenu.Menus[1].Title, new MenuItem [] { + new MenuItem ("_" + twoMenuItemMenu.Menus[1].Children[0].Title, "", null) + }), + }); + Application.Top.Add (menu); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - var expected = @" - File Edit -┌──────┐ -│ New │ -└──────┘ -"; - var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 0, 11, 4), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedSubMenuOpen (0), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (1, 0, 11, 1), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedClosed, output); } [Fact] @@ -1315,16 +1318,33 @@ Edit [Fact, AutoInitShutdown] public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () { - var menu = new MenuBar (new MenuBarItem [] { + // File Edit Format + //┌──────┐ ┌───────┐ + //│ New │ │ Wrap │ + //└──────┘ └───────┘ + + // Define the expected menu + var threeMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { - new MenuItem ("New", "", null) - }), - new MenuBarItem ("Edit", new MenuItem [] { + new MenuItem ("New", "", null) }), + new MenuBarItem ("Edit", new MenuItem [] {}), new MenuBarItem ("Format", new MenuItem [] { new MenuItem ("Wrap", "", null) }) }); + + var menu = new MenuBar (new MenuBarItem [] { + new MenuBarItem (threeMenuItemMenu.Menus[0].Title, new MenuItem [] { + new MenuItem (threeMenuItemMenu.Menus[0].Children[0].Title, "", null) + }), + new MenuBarItem (threeMenuItemMenu.Menus[1].Title, new MenuItem [] {}), + new MenuBarItem (threeMenuItemMenu.Menus[2].Title, new MenuItem [] { + new MenuItem (threeMenuItemMenu.Menus[2].Children[0].Title, "", null) + }) + }); + + var tf = new TextField () { Y = 2, Width = 10 }; Application.Top.Add (menu, tf); @@ -1334,76 +1354,38 @@ Edit Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - var expected = @" - File Edit Format -┌──────┐ -│ New │ -└──────┘ -"; - - var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 4), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (0), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 8, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 1), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (1), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 15, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format - ┌───────┐ - │ Wrap │ - └───────┘ -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 23, 4), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (2), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 8, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 1), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedClosed, output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -┌──────┐ -│ New │ -└──────┘ -"; + GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (0), output); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 4), pos); Assert.True (menu.MouseEvent (new MouseEvent () { X = 8, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 1), pos); + GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedClosed, output); } [Fact, AutoInitShutdown] From 40df03d3e33a7600d8c5b3b36e418bf36f37abed Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Thu, 20 Oct 2022 17:56:08 -0600 Subject: [PATCH 03/10] Finished refactoring tests --- Terminal.Gui/Core/ContextMenu.cs | 2 +- Terminal.Gui/Views/Menu.cs | 2 +- UICatalog/Scenarios/Notepad.cs | 6 +- UnitTests/MenuTests.cs | 336 +++++++++++++++++-------------- 4 files changed, 194 insertions(+), 152 deletions(-) diff --git a/Terminal.Gui/Core/ContextMenu.cs b/Terminal.Gui/Core/ContextMenu.cs index 726fc52c6..c51b2eea2 100644 --- a/Terminal.Gui/Core/ContextMenu.cs +++ b/Terminal.Gui/Core/ContextMenu.cs @@ -116,7 +116,7 @@ namespace Terminal.Gui { Y = position.Y, Width = 0, Height = 0, - UseSubMenusSingleFrame = UseSubMenusSingleFrame + UseSubMenusSingleFrame = UseSubMenusSingleFrame // BUGBUG: This line of code does nothing }; menuBar.isContextMenuLoading = true; diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index bc4eb3876..979ad0b66 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -1224,7 +1224,7 @@ namespace Terminal.Gui { } for (int i = 0; i < index; i++) - pos += 1 + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + 2; + pos += Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + 2; openMenu = new Menu (this, Frame.X + pos, Frame.Y + 1, Menus [index]); openCurrentMenu = openMenu; openCurrentMenu.previousSubFocused = openMenu; diff --git a/UICatalog/Scenarios/Notepad.cs b/UICatalog/Scenarios/Notepad.cs index 03f230b13..7fcd5c087 100644 --- a/UICatalog/Scenarios/Notepad.cs +++ b/UICatalog/Scenarios/Notepad.cs @@ -32,7 +32,11 @@ namespace UICatalog.Scenarios { new MenuItem ("Save _As", "", () => SaveAs()), new MenuItem ("_Close", "", () => Close()), new MenuItem ("_Quit", "", () => Quit()), - }) + }), + new MenuBarItem ("_Edit", new MenuItem [] {}), + new MenuBarItem ("_Help", new MenuItem [] { + new MenuItem ("_About", "", null) + }) }); Top.Add (menu); diff --git a/UnitTests/MenuTests.cs b/UnitTests/MenuTests.cs index 9b65cd4d5..5f14632d1 100644 --- a/UnitTests/MenuTests.cs +++ b/UnitTests/MenuTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Xunit; using Xunit.Abstractions; using static Terminal.Gui.Views.MenuTests; @@ -706,16 +707,15 @@ Edit Application.Top.Redraw (Application.Top.Bounds); var expected = @" - Numbers + Numbers "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -724,12 +724,11 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); Assert.True (Application.Top.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│┌─────────────┐ @@ -739,12 +738,11 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 25, 7), pos); Assert.True (Application.Top.Subviews [2].ProcessKey (new KeyEvent (Key.CursorLeft, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -753,16 +751,14 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); Assert.True (Application.Top.Subviews [1].ProcessKey (new KeyEvent (Key.Esc, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); } [Fact, AutoInitShutdown] @@ -786,11 +782,11 @@ Edit Application.Top.Redraw (Application.Top.Bounds); var expected = @" - Numbers + Numbers "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); + Assert.Equal (new Rect (1, 0, 8, 1), pos); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, @@ -800,7 +796,7 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -809,7 +805,7 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); + Assert.Equal (new Rect (1, 0, 10, 6), pos); Assert.False (menu.MouseEvent (new MouseEvent () { X = 1, @@ -819,7 +815,7 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│┌─────────────┐ @@ -829,7 +825,7 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 25, 7), pos); + Assert.Equal (new Rect (1, 0, 25, 7), pos); Assert.False (menu.MouseEvent (new MouseEvent () { X = 1, @@ -839,7 +835,7 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -848,7 +844,7 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); + Assert.Equal (new Rect (1, 0, 10, 6), pos); Assert.False (menu.MouseEvent (new MouseEvent () { X = 70, @@ -858,11 +854,11 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); + Assert.Equal (new Rect (1, 0, 8, 1), pos); } [Fact, AutoInitShutdown] @@ -888,16 +884,16 @@ Edit Application.Top.Redraw (Application.Top.Bounds); var expected = @" - Numbers + Numbers "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); + Assert.Equal (new Rect (1, 0, 8, 1), pos); Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -906,13 +902,13 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); + Assert.Equal (new Rect (1, 0, 10, 6), pos); Assert.True (Application.Top.Subviews [1].ProcessKey (new KeyEvent (Key.CursorDown, null))); Assert.True (Application.Top.Subviews [1].ProcessKey (new KeyEvent (Key.Enter, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌─────────────┐ │◄ Two │ ├─────────────┤ @@ -922,12 +918,12 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 15, 7), pos); + Assert.Equal (new Rect (1, 0, 15, 7), pos); Assert.True (Application.Top.Subviews [2].ProcessKey (new KeyEvent (Key.Enter, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -936,16 +932,16 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); + Assert.Equal (new Rect (1, 0, 10, 6), pos); Assert.True (Application.Top.Subviews [1].ProcessKey (new KeyEvent (Key.Esc, null))); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); + Assert.Equal (new Rect (1, 0, 8, 1), pos); } [Fact, AutoInitShutdown] @@ -971,11 +967,11 @@ Edit Application.Top.Redraw (Application.Top.Bounds); var expected = @" - Numbers + Numbers "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); + Assert.Equal (new Rect (1, 0, 8, 1), pos); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, @@ -985,7 +981,7 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -994,7 +990,7 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); + Assert.Equal (new Rect (1, 0, 10, 6), pos); Assert.False (menu.MouseEvent (new MouseEvent () { X = 1, @@ -1004,7 +1000,7 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌─────────────┐ │◄ Two │ ├─────────────┤ @@ -1014,7 +1010,7 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 15, 7), pos); + Assert.Equal (new Rect (1, 0, 15, 7), pos); Assert.False (menu.MouseEvent (new MouseEvent () { X = 1, @@ -1024,7 +1020,7 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers ┌────────┐ │ One │ │ Two ►│ @@ -1033,7 +1029,7 @@ Edit "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 10, 6), pos); + Assert.Equal (new Rect (1, 0, 10, 6), pos); Assert.False (menu.MouseEvent (new MouseEvent () { X = 70, @@ -1043,11 +1039,11 @@ Edit })); Application.Top.Redraw (Application.Top.Bounds); expected = @" - Numbers + Numbers "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 9, 1), pos); + Assert.Equal (new Rect (1, 0, 8, 1), pos); } [Fact, AutoInitShutdown] @@ -1108,34 +1104,103 @@ Edit public class ExpectedMenu : MenuBar { FakeDriver d = ((FakeDriver)Application.Driver); - public string expectedMenuBarText => " " + Menus [0].Title.ToString () + " " + " " + Menus [1].Title.ToString () + " "; + public string expectedMenuBarText { + get { + string txt = string.Empty; + foreach (var m in Menus) { + + txt += " " + m.Title.ToString () + " "; + } + return txt; + } + } // The expected strings when the menu is closed - public string expectedClosed => " " + Menus [0].Title.ToString () + " " + " " + Menus [1].Title.ToString () + "" + "\n"; + public string expectedClosed => expectedMenuBarText + "\n"; // left padding for the sub menu - public string padding (int i) => i > 0 ? new string (' ', Menus [i].Children [0].TitleLength + 4) : ""; + public string padding (int i) + { + int n = 0; + while (i > 0){ + n += Menus [i-1].TitleLength + 2; + i--; + } + return new string (' ', n); + } // Define expected menu frame // "┌──────┐" // "│ New │" // "└──────┘" // BUGBUG: The extra 4 spaces on these should not be there - public string expectedTopRow (int i) => $"{d.ULCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.URCorner} \n"; - public string expectedMenuItemRow (int i) => $"{d.VLine} {Menus [i].Children[0].Title} {d.VLine}" + " \n"; - public string expectedBottomRow (int i) => $"{d.LLCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.LRCorner} \n"; + public string expectedTopRow (int i) => $"{d.ULCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.URCorner} \n"; + public string expectedMenuItemRow (int i) => $"{d.VLine} {Menus [i].Children [0].Title} {d.VLine}" + " \n"; + public string expectedBottomRow (int i) => $"{d.LLCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.LRCorner} \n"; // The fulll expected string for an open sub menu - public string expectedSubMenuOpen (int i) => expectedClosed + - padding (i) + expectedTopRow(i) + + public string expectedSubMenuOpen (int i) => expectedClosed + + (Menus [i].Children.Length > 0 ? + padding (i) + expectedTopRow (i) + padding (i) + expectedMenuItemRow (i) + - padding (i) + expectedBottomRow (i); - + padding (i) + expectedBottomRow (i) + : + ""); + public ExpectedMenu (MenuBarItem [] menus) : base (menus) { } } + [Fact, AutoInitShutdown] + public void MenuBar_Submenus_Alignment_Correct () + { + // Define the expected menu + var expectedMenu = new ExpectedMenu (new MenuBarItem [] { + new MenuBarItem ("File", new MenuItem [] { + new MenuItem ("Really Long Sub Menu", "", null) + }), + new MenuBarItem ("123", new MenuItem [] { + new MenuItem ("Copy", "", null) + }), + new MenuBarItem ("Format", new MenuItem [] { + new MenuItem ("Word Wrap", "", null) + }), + new MenuBarItem ("Help", new MenuItem [] { + new MenuItem ("About", "", null) + }), + new MenuBarItem ("1", new MenuItem [] { + new MenuItem ("2", "", null) + }), + new MenuBarItem ("3", new MenuItem [] { + new MenuItem ("2", "", null) + }), + new MenuBarItem ("Last one", new MenuItem [] { + new MenuItem ("Test", "", null) + }) + }); + + MenuBarItem [] items = new MenuBarItem [expectedMenu.Menus.Length]; + for (var i = 0; i < expectedMenu.Menus.Length; i++) { + items [i] = new MenuBarItem (expectedMenu.Menus [i].Title, new MenuItem [] { + new MenuItem (expectedMenu.Menus [i].Children [0].Title, "", null) + }); + } + var menu = new MenuBar (items); + + Application.Top.Add (menu); + + Application.Top.Redraw (Application.Top.Bounds); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + + for (var i = 0; i < expectedMenu.Menus.Length; i++) { + menu.OpenMenu (i); + Assert.True (menu.IsMenuOpen); + Application.Top.Redraw (Application.Top.Bounds); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (i), output); + } + } + [Fact, AutoInitShutdown] public void HotKey_MenuBar_ProcessHotKey_Menu_ProcessKey () { @@ -1143,7 +1208,7 @@ Edit var copyAction = false; // Define the expected menu - var twoMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenu (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("New", "", null) }), @@ -1154,11 +1219,11 @@ Edit // The real menu var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_" + twoMenuItemMenu.Menus[0].Title, new MenuItem [] { - new MenuItem ("_" + twoMenuItemMenu.Menus[0].Children[0].Title, "", () => newAction = true) + new MenuBarItem ("_" + expectedMenu.Menus[0].Title, new MenuItem [] { + new MenuItem ("_" + expectedMenu.Menus[0].Children[0].Title, "", () => newAction = true) }), - new MenuBarItem ("_" + twoMenuItemMenu.Menus[1].Title, new MenuItem [] { - new MenuItem ("_" + twoMenuItemMenu.Menus[1].Children[0].Title, "", () => copyAction = true) + new MenuBarItem ("_" + expectedMenu.Menus[1].Title, new MenuItem [] { + new MenuItem ("_" + expectedMenu.Menus[1].Children[0].Title, "", () => copyAction = true) }), }); @@ -1170,7 +1235,7 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.AltMask | Key.F, new KeyModifiers () { Alt = true }))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedSubMenuOpen(0), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (0), output); Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.N, null))); Application.MainLoop.MainIteration (); @@ -1179,7 +1244,7 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.AltMask | Key.E, new KeyModifiers () { Alt = true }))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedSubMenuOpen (1), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (1), output); Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.C, null))); Application.MainLoop.MainIteration (); @@ -1190,7 +1255,7 @@ Edit public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKeys () { // Define the expected menu - var twoMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenu (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("12", "", null) }), @@ -1198,14 +1263,14 @@ Edit new MenuItem ("Copy", "", null) }) }); - + // Test without HotKeys first var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem (twoMenuItemMenu.Menus[0].Title, new MenuItem [] { - new MenuItem (twoMenuItemMenu.Menus[0].Children[0].Title, "", null) + new MenuBarItem (expectedMenu.Menus[0].Title, new MenuItem [] { + new MenuItem (expectedMenu.Menus[0].Children[0].Title, "", null) }), - new MenuBarItem (twoMenuItemMenu.Menus[1].Title, new MenuItem [] { - new MenuItem (twoMenuItemMenu.Menus[1].Children[0].Title, "", null) + new MenuBarItem (expectedMenu.Menus[1].Title, new MenuItem [] { + new MenuItem (expectedMenu.Menus[1].Children[0].Title, "", null) }) }); @@ -1215,29 +1280,29 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (0), output); - + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (0), output); + // Open second Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.CursorRight, null))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (1), output); - + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (1), output); + // Close menu Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); Application.Top.Remove (menu); // Now test WITH HotKeys menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_" + twoMenuItemMenu.Menus[0].Title, new MenuItem [] { - new MenuItem ("_" + twoMenuItemMenu.Menus[0].Children[0].Title, "", null) + new MenuBarItem ("_" + expectedMenu.Menus[0].Title, new MenuItem [] { + new MenuItem ("_" + expectedMenu.Menus[0].Children[0].Title, "", null) }), - new MenuBarItem ("_" + twoMenuItemMenu.Menus[1].Title, new MenuItem [] { - new MenuItem ("_" + twoMenuItemMenu.Menus[1].Children[0].Title, "", null) + new MenuBarItem ("_" + expectedMenu.Menus[1].Title, new MenuItem [] { + new MenuItem ("_" + expectedMenu.Menus[1].Children[0].Title, "", null) }), }); @@ -1247,26 +1312,26 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (0), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (0), output); // Open second Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.CursorRight, null))); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedSubMenuOpen (1), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (1), output); // Close menu Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (twoMenuItemMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); } [Fact, AutoInitShutdown] public void MenuBar_ButtonPressed_Open_The_Menu_ButtonPressed_Again_Close_The_Menu () { // Define the expected menu - var twoMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenu (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("Open", "", null) }), @@ -1277,26 +1342,26 @@ Edit // Test without HotKeys first var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem ("_" + twoMenuItemMenu.Menus[0].Title, new MenuItem [] { - new MenuItem ("_" + twoMenuItemMenu.Menus[0].Children[0].Title, "", null) + new MenuBarItem ("_" + expectedMenu.Menus[0].Title, new MenuItem [] { + new MenuItem ("_" + expectedMenu.Menus[0].Children[0].Title, "", null) }), - new MenuBarItem ("_" + twoMenuItemMenu.Menus[1].Title, new MenuItem [] { - new MenuItem ("_" + twoMenuItemMenu.Menus[1].Children[0].Title, "", null) + new MenuBarItem ("_" + expectedMenu.Menus[1].Title, new MenuItem [] { + new MenuItem ("_" + expectedMenu.Menus[1].Children[0].Title, "", null) }), }); - + Application.Top.Add (menu); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.True (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedSubMenuOpen (0), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (0), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (twoMenuItemMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); } [Fact] @@ -1324,7 +1389,7 @@ Edit //└──────┘ └───────┘ // Define the expected menu - var threeMenuItemMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenu (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("New", "", null) }), @@ -1335,72 +1400,81 @@ Edit }); var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem (threeMenuItemMenu.Menus[0].Title, new MenuItem [] { - new MenuItem (threeMenuItemMenu.Menus[0].Children[0].Title, "", null) + new MenuBarItem (expectedMenu.Menus[0].Title, new MenuItem [] { + new MenuItem (expectedMenu.Menus[0].Children[0].Title, "", null) }), - new MenuBarItem (threeMenuItemMenu.Menus[1].Title, new MenuItem [] {}), - new MenuBarItem (threeMenuItemMenu.Menus[2].Title, new MenuItem [] { - new MenuItem (threeMenuItemMenu.Menus[2].Children[0].Title, "", null) + new MenuBarItem (expectedMenu.Menus[1].Title, new MenuItem [] {}), + new MenuBarItem (expectedMenu.Menus[2].Title, new MenuItem [] { + new MenuItem (expectedMenu.Menus[2].Children[0].Title, "", null) }) }); - var tf = new TextField () { Y = 2, Width = 10 }; Application.Top.Add (menu, tf); - Application.Begin (Application.Top); + Assert.True (tf.HasFocus); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (0), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (0), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 8, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (1), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (1), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 15, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (2), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (2), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 8, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedSubMenuOpen (0), output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (0), output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 8, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsWithFrameAre (threeMenuItemMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); } [Fact, AutoInitShutdown] public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Keyboard () { - var menu = new MenuBar (new MenuBarItem [] { + var expectedMenu = new ExpectedMenu (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("New", "", null) }), - new MenuBarItem ("Edit", new MenuItem [] { - }), + new MenuBarItem ("Edit", Array.Empty ()), new MenuBarItem ("Format", new MenuItem [] { new MenuItem ("Wrap", "", null) }) }); + + MenuBarItem [] items = new MenuBarItem [expectedMenu.Menus.Length]; + for (var i = 0; i < expectedMenu.Menus.Length; i++) { + items [i] = new MenuBarItem (expectedMenu.Menus [i].Title, expectedMenu.Menus [i].Children.Length > 0 + ? new MenuItem [] { + new MenuItem (expectedMenu.Menus [i].Children [0].Title, "", null), + } + : Array.Empty ()); + } + var menu = new MenuBar (items); + var tf = new TextField () { Y = 2, Width = 10 }; Application.Top.Add (menu, tf); @@ -1410,76 +1484,40 @@ Edit Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - var expected = @" - File Edit Format -┌──────┐ -│ New │ -└──────┘ -"; - - var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 4), pos); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen(0), output); + // Right - Edit has no sub menu; this tests that no sub menu shows Assert.True (menu.openMenu.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 1), pos); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (1), output); + // Right - Format Assert.True (menu.openMenu.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format - ┌───────┐ - │ Wrap │ - └───────┘ -"; + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (2), output); - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 23, 4), pos); + // Left - Edit + Assert.True (menu.openMenu.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()))); + Assert.True (menu.IsMenuOpen); + Assert.False (tf.HasFocus); + Application.Top.Redraw (Application.Top.Bounds); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (1), output); Assert.True (menu.openMenu.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()))); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 1), pos); - - Assert.True (menu.openMenu.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ()))); - Assert.True (menu.IsMenuOpen); - Assert.False (tf.HasFocus); - Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -┌──────┐ -│ New │ -└──────┘ -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 4), pos); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedSubMenuOpen (0), output); Assert.True (menu.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - expected = @" - File Edit Format -"; - - pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rect (2, 0, 22, 1), pos); + GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); } } } From 5aebe14a6470826bda06b34ce6905107954226d4 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Thu, 20 Oct 2022 17:57:35 -0600 Subject: [PATCH 04/10] removed test code from Notepad --- UICatalog/Scenarios/Notepad.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/UICatalog/Scenarios/Notepad.cs b/UICatalog/Scenarios/Notepad.cs index 7fcd5c087..03f230b13 100644 --- a/UICatalog/Scenarios/Notepad.cs +++ b/UICatalog/Scenarios/Notepad.cs @@ -32,11 +32,7 @@ namespace UICatalog.Scenarios { new MenuItem ("Save _As", "", () => SaveAs()), new MenuItem ("_Close", "", () => Close()), new MenuItem ("_Quit", "", () => Quit()), - }), - new MenuBarItem ("_Edit", new MenuItem [] {}), - new MenuBarItem ("_Help", new MenuItem [] { - new MenuItem ("_About", "", null) - }) + }) }); Top.Add (menu); From d93a247a4df602938d1735950fc9227348c8249c Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Fri, 21 Oct 2022 08:12:26 -0600 Subject: [PATCH 05/10] documenting behavior --- Terminal.Gui/Views/Menu.cs | 21 +++++++++++-- UICatalog/UICatalog.cs | 2 +- UnitTests/MenuTests.cs | 60 +++++++++++++++++++++++--------------- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 979ad0b66..8685119bc 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -141,6 +141,12 @@ namespace Terminal.Gui { return CanExecute == null ? true : CanExecute (); } + // ┌──────────────────────────────┐ + // │ Quit Quit UI Catalog Ctrl+Q │ + // └──────────────────────────────┘ + // ┌─────────────────┐ + // │ ◌ TopLevel Alt+T │ + // └─────────────────┘ internal int Width => 1 + TitleLength + (Help.ConsoleWidth > 0 ? Help.ConsoleWidth + 2 : 0) + (Checked || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio) ? 2 : 0) + (ShortcutTag.ConsoleWidth > 0 ? ShortcutTag.ConsoleWidth + 2 : 0) + 2; @@ -459,6 +465,7 @@ namespace Terminal.Gui { return GetNormalColor (); } + // Draws the Menu, within the Frame public override void Redraw (Rect bounds) { Driver.SetAttribute (GetNormalColor ()); @@ -484,6 +491,7 @@ namespace Terminal.Gui { Driver.AddRune (Driver.HLine); else if (i == 0 && p == 0 && host.UseSubMenusSingleFrame && item.Parent.Parent != null) Driver.AddRune (Driver.LeftArrow); + // TODO: Change this `- 3` to a const (is it spacesAfterTitle?) else if (p == Frame.Width - 3 && barItems.SubMenu (barItems.Children [i]) != null) Driver.AddRune (Driver.RightArrow); else @@ -516,6 +524,7 @@ namespace Terminal.Gui { textToDraw = item.Title; } + // Draw the item. The `2` is for the left border and the space before the text ViewToScreen (2, i + 1, out int vtsCol, out _, false); if (vtsCol < Driver.Cols) { Move (2, i + 1); @@ -527,6 +536,7 @@ namespace Terminal.Gui { HotKeySpecifier = MenuBar.HotKeySpecifier, Text = textToDraw }; + // TODO: Change this `- 3` to a const (is it spacesAfterTitle?) tf.Draw (ViewToScreen (new Rect (2, i + 1, Frame.Width - 3, 1)), i == current ? ColorScheme.Focus : GetNormalColor (), i == current ? ColorScheme.HotFocus : ColorScheme.HotNormal, @@ -1025,7 +1035,8 @@ namespace Terminal.Gui { } static int leftPadding = 1; - static int rightPadding = 1; + static int rightPadding = 1; + static int spaceAfterTitle = 3; /// public override void Redraw (Rect bounds) { @@ -1053,7 +1064,7 @@ namespace Terminal.Gui { normalColor = GetNormalColor (); } DrawHotString (menu.Help.IsEmpty ? $" {menu.Title} " : $" {menu.Title} ({menu.Help}) ", hotColor, normalColor); - pos += leftPadding + menu.TitleLength + (menu.Help.ConsoleWidth > 0 ? menu.Help.ConsoleWidth + 3 : 0) + rightPadding; + pos += leftPadding + menu.TitleLength + (menu.Help.ConsoleWidth > 0 ? menu.Help.ConsoleWidth + spaceAfterTitle : 0) + rightPadding; } PositionCursor (); } @@ -1076,7 +1087,7 @@ namespace Terminal.Gui { } return; } else { - pos += leftPadding + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 3 : 0) + rightPadding; + pos += leftPadding + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + spaceAfterTitle : 0)+ rightPadding; } } } @@ -1211,6 +1222,7 @@ namespace Terminal.Gui { int pos = 0; switch (subMenu) { case null: + // Open a submenu below a MenuBar lastFocused = lastFocused ?? (SuperView == null ? Application.Current.MostFocused : SuperView.MostFocused); if (openSubMenu != null && !CloseMenu (false, true)) return; @@ -1223,6 +1235,8 @@ namespace Terminal.Gui { openMenu.Dispose (); } + // This positions the submenu horizontally aligned with the first character of the + // menu it belongs to's text for (int i = 0; i < index; i++) pos += Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + 2; openMenu = new Menu (this, Frame.X + pos, Frame.Y + 1, Menus [index]); @@ -1237,6 +1251,7 @@ namespace Terminal.Gui { openMenu.SetFocus (); break; default: + // Opens a submenu next to another submenu (openSubMenu) if (openSubMenu == null) openSubMenu = new List (); if (sIndex > -1) { diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 895228942..8cd4f3dce 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -169,7 +169,7 @@ namespace UICatalog { _menu = new MenuBar (new MenuBarItem [] { new MenuBarItem ("_File", new MenuItem [] { - new MenuItem ("_Quit", "", () => Application.RequestStop(), null, null, Key.Q | Key.CtrlMask) + new MenuItem ("_Quit", "Quit UI Catalog", () => Application.RequestStop(), null, null, Key.Q | Key.CtrlMask) }), new MenuBarItem ("_Color Scheme", CreateColorSchemeMenuItems()), new MenuBarItem ("Diag_nostics", CreateDiagnosticMenuItems()), diff --git a/UnitTests/MenuTests.cs b/UnitTests/MenuTests.cs index 5f14632d1..549551fc6 100644 --- a/UnitTests/MenuTests.cs +++ b/UnitTests/MenuTests.cs @@ -1097,14 +1097,24 @@ Edit Assert.True (copyAction); } - // Defines the expected strings for a Menu + // Defines the expected strings for a Menu. Currently supports + // - MenuBar with any number of MenuItems + // - Each top-level MenuItem can have a SINGLE sub-menu + // + // TODO: Enable multiple sub-menus + // TODO: Enable checked sub-menus + // TODO: Enable sub-menus with sub-menus (perhaps better to put this in a separate class with focused unit tests?) + // + // E.g: // // File Edit // New Copy - public class ExpectedMenu : MenuBar { + public class ExpectedMenuBar : MenuBar { FakeDriver d = ((FakeDriver)Application.Driver); - public string expectedMenuBarText { + // Each MenuBar title has a 1 space pad on each side + // See `static int leftPadding` and `static int rightPadding` on line 1037 of Menu.cs + public string MenuBarText { get { string txt = string.Empty; foreach (var m in Menus) { @@ -1116,10 +1126,11 @@ Edit } // The expected strings when the menu is closed - public string expectedClosed => expectedMenuBarText + "\n"; + public string ClosedMenuText => MenuBarText + "\n"; - // left padding for the sub menu - public string padding (int i) + // Padding for the X of the sub menu Frane + // Menu.cs - Line 1239 in `internal void OpenMenu` is where the Menu is created + string padding (int i) { int n = 0; while (i > 0){ @@ -1133,13 +1144,16 @@ Edit // "┌──────┐" // "│ New │" // "└──────┘" - // BUGBUG: The extra 4 spaces on these should not be there + // + // The width of the Frame is determined in Menu.cs line 144, where `Width` is calculated + // 1 space before the Title and 2 spaces after the Title/Check/Help public string expectedTopRow (int i) => $"{d.ULCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.URCorner} \n"; - public string expectedMenuItemRow (int i) => $"{d.VLine} {Menus [i].Children [0].Title} {d.VLine}" + " \n"; + // The 3 spaces at end are a result of Menu.cs line 1062 where `pos` is calculated (` + spacesAfterTitle`) + public string expectedMenuItemRow (int i) => $"{d.VLine} {Menus [i].Children [0].Title} {d.VLine} \n"; public string expectedBottomRow (int i) => $"{d.LLCorner}{new String (d.HLine.ToString () [0], Menus [i].Children [0].TitleLength + 3)}{d.LRCorner} \n"; // The fulll expected string for an open sub menu - public string expectedSubMenuOpen (int i) => expectedClosed + + public string expectedSubMenuOpen (int i) => ClosedMenuText + (Menus [i].Children.Length > 0 ? padding (i) + expectedTopRow (i) + padding (i) + expectedMenuItemRow (i) + @@ -1147,7 +1161,7 @@ Edit : ""); - public ExpectedMenu (MenuBarItem [] menus) : base (menus) + public ExpectedMenuBar (MenuBarItem [] menus) : base (menus) { } } @@ -1156,7 +1170,7 @@ Edit public void MenuBar_Submenus_Alignment_Correct () { // Define the expected menu - var expectedMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenuBar (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("Really Long Sub Menu", "", null) }), @@ -1191,7 +1205,7 @@ Edit Application.Top.Add (menu); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output); for (var i = 0; i < expectedMenu.Menus.Length; i++) { menu.OpenMenu (i); @@ -1208,7 +1222,7 @@ Edit var copyAction = false; // Define the expected menu - var expectedMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenuBar (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("New", "", null) }), @@ -1255,7 +1269,7 @@ Edit public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKeys () { // Define the expected menu - var expectedMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenuBar (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("12", "", null) }), @@ -1292,7 +1306,7 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output); Application.Top.Remove (menu); @@ -1324,14 +1338,14 @@ Edit Assert.True (menu.ProcessHotKey (new (Key.F9, new KeyModifiers ()))); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output); } [Fact, AutoInitShutdown] public void MenuBar_ButtonPressed_Open_The_Menu_ButtonPressed_Again_Close_The_Menu () { // Define the expected menu - var expectedMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenuBar (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("Open", "", null) }), @@ -1361,7 +1375,7 @@ Edit Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output); } [Fact] @@ -1389,7 +1403,7 @@ Edit //└──────┘ └───────┘ // Define the expected menu - var expectedMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenuBar (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("New", "", null) }), @@ -1436,7 +1450,7 @@ Edit Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output); Assert.True (menu.MouseEvent (new MouseEvent () { X = 1, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (menu.IsMenuOpen); @@ -1449,13 +1463,13 @@ Edit Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output); } [Fact, AutoInitShutdown] public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Keyboard () { - var expectedMenu = new ExpectedMenu (new MenuBarItem [] { + var expectedMenu = new ExpectedMenuBar (new MenuBarItem [] { new MenuBarItem ("File", new MenuItem [] { new MenuItem ("New", "", null) }), @@ -1517,7 +1531,7 @@ Edit Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); Application.Top.Redraw (Application.Top.Bounds); - GraphViewTests.AssertDriverContentsAre (expectedMenu.expectedClosed, output); + GraphViewTests.AssertDriverContentsAre (expectedMenu.ClosedMenuText, output); } } } From f3e704207739ab2c2cff6c692986c42cb66dbf05 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Fri, 21 Oct 2022 08:47:09 -0600 Subject: [PATCH 06/10] added constants to MenuBar --- Terminal.Gui/Views/Menu.cs | 37 ++++++++++++++++++++++--------------- UICatalog/UICatalog.cs | 2 +- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 8685119bc..326cc1036 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -141,13 +141,14 @@ namespace Terminal.Gui { return CanExecute == null ? true : CanExecute (); } - // ┌──────────────────────────────┐ - // │ Quit Quit UI Catalog Ctrl+Q │ - // └──────────────────────────────┘ + // ┌─────────────────────────────┐ + // │ Quit Quit UI Catalog Ctrl+Q │ + // └─────────────────────────────┘ // ┌─────────────────┐ // │ ◌ TopLevel Alt+T │ // └─────────────────┘ - internal int Width => 1 + TitleLength + (Help.ConsoleWidth > 0 ? Help.ConsoleWidth + 2 : 0) + + // TODO: Repalace the `2` literals with named constants (e.g. spacesAfterHelp and spacesAfterCheck and spacesAfterShortCutTag) + internal int Width => + TitleLength + (Help.ConsoleWidth > 0 ? Help.ConsoleWidth + 2 : 0) + (Checked || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio) ? 2 : 0) + (ShortcutTag.ConsoleWidth > 0 ? ShortcutTag.ConsoleWidth + 2 : 0) + 2; @@ -226,7 +227,7 @@ namespace Terminal.Gui { /// Initializes a new as a . /// /// Title for the menu item. - /// Help text to display. + /// Help text to display. Will be displayed next to the Title surrounded by parentheses. /// Action to invoke when the menu item is activated. /// Function to determine if the action can currently be executed. /// The parent of this if exist, otherwise is null. @@ -397,8 +398,8 @@ namespace Terminal.Gui { } int minX = x; int minY = y; - int maxW = (items.Max (z => z?.Width) ?? 0) + 2; - int maxH = items.Length + 2; + int maxW = (items.Max (z => z?.Width) ?? 0) + 2; // This 2 is frame border? + int maxH = items.Length + 2; // This 2 is frame border? if (parent != null && x + maxW > Driver.Cols) { minX = Math.Max (parent.Frame.Right - parent.Frame.Width - maxW, 0); } @@ -484,7 +485,7 @@ namespace Terminal.Gui { Move (1, i + 1); Driver.SetAttribute (DetermineColorSchemeFor (item, i)); - for (int p = Bounds.X; p < Frame.Width - 2; p++) { + for (int p = Bounds.X; p < Frame.Width - 2; p++) { // This - 2 is for the border? if (p < 0) continue; if (item == null) @@ -1034,9 +1035,14 @@ namespace Terminal.Gui { isCleaning = false; } + // The column where the MenuBar starts + static int xOrigin = 0; + // Spaces before the Title static int leftPadding = 1; + // Spaces after the Title static int rightPadding = 1; - static int spaceAfterTitle = 3; + // Spaces after the submenu Title, before Help + static int parensAroundHelp = 3; /// public override void Redraw (Rect bounds) { @@ -1063,8 +1069,9 @@ namespace Terminal.Gui { hotColor = GetNormalColor (); normalColor = GetNormalColor (); } + // Note Help on MenuBar is drawn with parens around it DrawHotString (menu.Help.IsEmpty ? $" {menu.Title} " : $" {menu.Title} ({menu.Help}) ", hotColor, normalColor); - pos += leftPadding + menu.TitleLength + (menu.Help.ConsoleWidth > 0 ? menu.Help.ConsoleWidth + spaceAfterTitle : 0) + rightPadding; + pos += leftPadding + menu.TitleLength + (menu.Help.ConsoleWidth > 0 ? leftPadding + menu.Help.ConsoleWidth + parensAroundHelp : 0) + rightPadding; } PositionCursor (); } @@ -1087,7 +1094,7 @@ namespace Terminal.Gui { } return; } else { - pos += leftPadding + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + spaceAfterTitle : 0)+ rightPadding; + pos += leftPadding + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + parensAroundHelp : 0)+ rightPadding; } } } @@ -1238,7 +1245,7 @@ namespace Terminal.Gui { // This positions the submenu horizontally aligned with the first character of the // menu it belongs to's text for (int i = 0; i < index; i++) - pos += Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + 2; + pos += Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + leftPadding + rightPadding; openMenu = new Menu (this, Frame.X + pos, Frame.Y + 1, Menus [index]); openCurrentMenu = openMenu; openCurrentMenu.previousSubFocused = openMenu; @@ -1791,10 +1798,10 @@ namespace Terminal.Gui { if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked || me.Flags == MouseFlags.Button1TripleClicked || me.Flags == MouseFlags.Button1Clicked || (me.Flags == MouseFlags.ReportMousePosition && selected > -1) || (me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition) && selected > -1)) { - int pos = 1; + int pos = xOrigin; int cx = me.X; for (int i = 0; i < Menus.Length; i++) { - if (cx >= pos && cx < pos + 1 + Menus [i].TitleLength + Menus [i].Help.ConsoleWidth + 2) { + if (cx >= pos && cx < pos + leftPadding + Menus [i].TitleLength + Menus [i].Help.ConsoleWidth + rightPadding) { if (me.Flags == MouseFlags.Button1Clicked) { if (Menus [i].IsTopLevel) { var menu = new Menu (this, i, 0, Menus [i]); @@ -1823,7 +1830,7 @@ namespace Terminal.Gui { } return true; } - pos += 1 + Menus [i].TitleLength + 2; + pos += leftPadding + Menus [i].TitleLength + rightPadding; } } return false; diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 8cd4f3dce..5b94d3e55 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -178,7 +178,7 @@ namespace UICatalog { new MenuItem ("gui.cs _README", "", () => OpenUrl ("https://github.com/gui-cs/Terminal.Gui"), null, null, Key.F2), new MenuItem ("_About...", "About UI Catalog", () => MessageBox.Query ("About UI Catalog", aboutMessage.ToString(), "_Ok"), null, null, Key.CtrlMask | Key.A), - }) + }), }); _leftPane = new FrameView ("Categories") { From 4ef36560d71ea9a9ae1114d474c59a86a6ede73b Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Fri, 21 Oct 2022 10:52:41 -0600 Subject: [PATCH 07/10] made code clearer --- Terminal.Gui/Views/Menu.cs | 123 +++++++++++++++++-------------------- UICatalog/UICatalog.cs | 5 +- 2 files changed, 60 insertions(+), 68 deletions(-) diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 326cc1036..7a7d6e3d3 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -1,13 +1,3 @@ -// -// Menu.cs: application menus and submenus -// -// Authors: -// Miguel de Icaza (miguel@gnome.org) -// -// TODO: -// Add accelerator support, but should also support chords (Shortcut in MenuItem) -// Allow menus inside menus - using System; using NStack; using System.Linq; @@ -26,18 +16,19 @@ namespace Terminal.Gui { NoCheck = 0b_0000_0000, /// - /// The menu item will indicate checked/un-checked state (see . + /// The menu item will indicate checked/un-checked state (see ). /// Checked = 0b_0000_0001, /// - /// The menu item is part of a menu radio group (see and will indicate selected state. + /// The menu item is part of a menu radio group (see ) and will indicate selected state. /// Radio = 0b_0000_0010, }; /// - /// A has a title, an associated help text, and an action to execute on activation. + /// A has title, an associated help text, and an action to execute on activation. + /// MenuItems can also have a checked indicator (see ). /// public class MenuItem { ustring title; @@ -78,14 +69,28 @@ namespace Terminal.Gui { } /// - /// The HotKey is used when the menu is active, the shortcut can be triggered when the menu is not active. - /// For example HotKey would be "N" when the File Menu is open (assuming there is a "_New" entry - /// if the Shortcut is set to "Control-N", this would be a global hotkey that would trigger as well + /// The HotKey is used to activate a with they keyboard. HotKeys are defined by prefixing the + /// of a MenuItem with an underscore ('_'). + /// + /// Pressing Alt-Hotkey for a (menu items on the menu bar) works even if the menu is not active). + /// Once a menu has focus and is active, pressing just the HotKey will activate the MenuItem. + /// + /// + /// For example for a MenuBar with a "_File" MenuBarItem that contains a "_New" MenuItem, Alt-F will open the File menu. + /// Pressing the N key will then activate the New MenuItem. + /// + /// + /// See also which enable global key-bindings to menu items. + /// /// public Rune HotKey; /// - /// This is the global setting that can be used as a global to invoke the action on the menu. + /// Shortcut defines a key binding to the MenuItem that will invoke the MenuItem's action globally for the that is + /// the parent of the or this . + /// + /// The will be drawn on the MenuItem to the right of the and text. See . + /// /// public Key Shortcut { get => shortcutHelper.Shortcut; @@ -97,12 +102,12 @@ namespace Terminal.Gui { } /// - /// The keystroke combination used in the as string. + /// Gets the text describing the keystroke combination defined by . /// public ustring ShortcutTag => ShortcutHelper.GetShortcutTag (shortcutHelper.Shortcut); /// - /// Gets or sets the title. + /// Gets or sets the title of the menu item . /// /// The title. public ustring Title { @@ -116,41 +121,46 @@ namespace Terminal.Gui { } /// - /// Gets or sets the help text for the menu item. + /// Gets or sets the help text for the menu item. The help text is drawn to the right of the . /// /// The help text. public ustring Help { get; set; } /// - /// Gets or sets the action to be invoked when the menu is triggered + /// Gets or sets the action to be invoked when the menu item is triggered. /// /// Method to invoke. public Action Action { get; set; } /// - /// Gets or sets the action to be invoked if the menu can be triggered + /// Gets or sets the action to be invoked to determine if the menu can be triggered. If returns + /// the menu item will be enabled. Otherwise it will be disabled. /// - /// Function to determine if action is ready to be executed. + /// Function to determine if the action is can be executed or not. public Func CanExecute { get; set; } /// - /// Shortcut to check if the menu item is enabled + /// Returns if the menu item is enabled. This method is a wrapper around . /// public bool IsEnabled () { return CanExecute == null ? true : CanExecute (); } + // // ┌─────────────────────────────┐ // │ Quit Quit UI Catalog Ctrl+Q │ // └─────────────────────────────┘ // ┌─────────────────┐ // │ ◌ TopLevel Alt+T │ // └─────────────────┘ - // TODO: Repalace the `2` literals with named constants (e.g. spacesAfterHelp and spacesAfterCheck and spacesAfterShortCutTag) - internal int Width => + TitleLength + (Help.ConsoleWidth > 0 ? Help.ConsoleWidth + 2 : 0) + - (Checked || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio) ? 2 : 0) + - (ShortcutTag.ConsoleWidth > 0 ? ShortcutTag.ConsoleWidth + 2 : 0) + 2; + // TODO: Repalace the `2` literals with named constants + internal int Width => 1 + // space before Title + TitleLength + + 2 + // space after Title - BUGBUG: This should be 1 + (Checked || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio) ? 2 : 0) + // check glyph + space + (Help.ConsoleWidth > 0 ? 2 + Help.ConsoleWidth : 0) + // Two spaces before Help + (ShortcutTag.ConsoleWidth > 0 ? 2 + ShortcutTag.ConsoleWidth : 0); // Pad two spaces before shortcut tag (which are also aligned right) /// /// Sets or gets whether the shows a check indicator or not. See . @@ -158,12 +168,12 @@ namespace Terminal.Gui { public bool Checked { set; get; } /// - /// Sets or gets the type selection indicator the menu item will be displayed with. + /// Sets or gets the of a menu item where is set to . /// public MenuItemCheckStyle CheckType { get; set; } /// - /// Gets or sets the parent for this . + /// Gets the parent for this . /// /// The parent. public MenuItem Parent { get; internal set; } @@ -174,7 +184,7 @@ namespace Terminal.Gui { internal bool IsFromSubMenu { get { return Parent != null; } } /// - /// Merely a debugging aid to see the interaction with main + /// Merely a debugging aid to see the interaction with main. /// public MenuItem GetMenuItem () { @@ -182,7 +192,7 @@ namespace Terminal.Gui { } /// - /// Merely a debugging aid to see the interaction with main + /// Merely a debugging aid to see the interaction with main. /// public bool GetMenuBarItem () { @@ -220,7 +230,8 @@ namespace Terminal.Gui { } /// - /// A contains s or s. + /// is a menu item on an app's . MenuBarItems do not support + /// . /// public class MenuBarItem : MenuItem { /// @@ -296,19 +307,6 @@ namespace Terminal.Gui { } } - //static int GetMaxTitleLength (MenuItem [] children) - //{ - // int maxLength = 0; - // foreach (var item in children) { - // int len = GetMenuBarItemLength (item.Title); - // if (len > maxLength) - // maxLength = len; - // item.IsFromSubMenu = true; - // } - - // return maxLength; - //} - void SetChildrensParent (MenuItem [] childrens) { foreach (var child in childrens) { @@ -370,12 +368,6 @@ namespace Terminal.Gui { Title = title; } - ///// - ///// Gets or sets the title to display. - ///// - ///// The title. - //public ustring Title { get; set; } - /// /// Gets or sets an array of objects that are the children of this /// @@ -485,14 +477,14 @@ namespace Terminal.Gui { Move (1, i + 1); Driver.SetAttribute (DetermineColorSchemeFor (item, i)); - for (int p = Bounds.X; p < Frame.Width - 2; p++) { // This - 2 is for the border? + for (int p = Bounds.X; p < Frame.Width - 2; p++) { // This - 2 is for the border if (p < 0) continue; if (item == null) Driver.AddRune (Driver.HLine); else if (i == 0 && p == 0 && host.UseSubMenusSingleFrame && item.Parent.Parent != null) Driver.AddRune (Driver.LeftArrow); - // TODO: Change this `- 3` to a const (is it spacesAfterTitle?) + // This `- 3` is left border + right border + one row in from right else if (p == Frame.Width - 3 && barItems.SubMenu (barItems.Children [i]) != null) Driver.AddRune (Driver.RightArrow); else @@ -525,7 +517,6 @@ namespace Terminal.Gui { textToDraw = item.Title; } - // Draw the item. The `2` is for the left border and the space before the text ViewToScreen (2, i + 1, out int vtsCol, out _, false); if (vtsCol < Driver.Cols) { Move (2, i + 1); @@ -537,7 +528,7 @@ namespace Terminal.Gui { HotKeySpecifier = MenuBar.HotKeySpecifier, Text = textToDraw }; - // TODO: Change this `- 3` to a const (is it spacesAfterTitle?) + // The -3 is left/right border + one space (not sure what for) tf.Draw (ViewToScreen (new Rect (2, i + 1, Frame.Width - 3, 1)), i == current ? ColorScheme.Focus : GetNormalColor (), i == current ? ColorScheme.HotFocus : ColorScheme.HotNormal, @@ -846,14 +837,19 @@ namespace Terminal.Gui { /// + /// /// Provides a menu bar with drop-down and cascading menus. + /// + /// + /// + /// /// /// /// - /// The appears on the first row of the terminal. + /// The appears on the first row of the terminal and uses the full width. /// /// - /// The provides global hotkeys for the application. + /// The provides global hotkeys for the application. See . /// /// public class MenuBar : View { @@ -1035,7 +1031,7 @@ namespace Terminal.Gui { isCleaning = false; } - // The column where the MenuBar starts + // The column where the MenuBar starts static int xOrigin = 0; // Spaces before the Title static int leftPadding = 1; @@ -1086,15 +1082,10 @@ namespace Terminal.Gui { for (int i = 0; i < Menus.Length; i++) { if (i == selected) { pos++; - // BUGBUG: This if is not needed - if (IsMenuOpen) - Move (pos + 1, 0); - else { - Move (pos + 1, 0); - } + Move (pos + 1, 0); return; } else { - pos += leftPadding + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + parensAroundHelp : 0)+ rightPadding; + pos += leftPadding + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + parensAroundHelp : 0) + rightPadding; } } } diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 5b94d3e55..9949c337f 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -318,7 +318,7 @@ namespace UICatalog { { List menuItems = new List (); var item = new MenuItem (); - item.Title = "_Disable/Enable Mouse"; + item.Title = "_Disable Mouse"; item.Shortcut = Key.CtrlMask | Key.AltMask | (Key)item.Title.ToString ().Substring (1, 1) [0]; item.CheckType |= MenuItemCheckStyle.Checked; item.Checked = Application.IsMouseDisabled; @@ -334,7 +334,8 @@ namespace UICatalog { List menuItems = new List (); var item = new MenuItem (); - item.Title = "Keybindings"; + item.Title = "_Key Bindings"; + item.Help = "Change which keys do what"; item.Action += () => { var dlg = new KeyBindingsDialog (); Application.Run (dlg); From 138d0dacd126421626edb9e5ea21bc3414b88794 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Fri, 21 Oct 2022 11:03:28 -0600 Subject: [PATCH 08/10] made code clearer --- Terminal.Gui/Core/ContextMenu.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/Core/ContextMenu.cs b/Terminal.Gui/Core/ContextMenu.cs index c51b2eea2..79c1a9cb2 100644 --- a/Terminal.Gui/Core/ContextMenu.cs +++ b/Terminal.Gui/Core/ContextMenu.cs @@ -110,13 +110,13 @@ namespace Terminal.Gui { } else if (ForceMinimumPosToZero && position.Y < 0) { position.Y = 0; } - + menuBar = new MenuBar (new [] { MenuItems }) { X = position.X, Y = position.Y, Width = 0, Height = 0, - UseSubMenusSingleFrame = UseSubMenusSingleFrame // BUGBUG: This line of code does nothing + UseSubMenusSingleFrame = this.UseSubMenusSingleFrame }; menuBar.isContextMenuLoading = true; From 76dd8a70d461b99967ef8145eef4d128eb0ccbab Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Fri, 21 Oct 2022 16:03:30 -0600 Subject: [PATCH 09/10] more doc improvements --- Terminal.Gui/{Core => Views}/ContextMenu.cs | 57 ++++++--- Terminal.Gui/Views/Menu.cs | 131 +++++++------------- UICatalog/Scenarios/Editor.cs | 2 + 3 files changed, 82 insertions(+), 108 deletions(-) rename Terminal.Gui/{Core => Views}/ContextMenu.cs (62%) diff --git a/Terminal.Gui/Core/ContextMenu.cs b/Terminal.Gui/Views/ContextMenu.cs similarity index 62% rename from Terminal.Gui/Core/ContextMenu.cs rename to Terminal.Gui/Views/ContextMenu.cs index 79c1a9cb2..b5dcde5f6 100644 --- a/Terminal.Gui/Core/ContextMenu.cs +++ b/Terminal.Gui/Views/ContextMenu.cs @@ -2,8 +2,24 @@ namespace Terminal.Gui { /// - /// A context menu window derived from containing menu items - /// which can be opened in any position. + /// ContextMenu provides a pop-up menu that can be positioned anywhere within a . + /// ContextMenu is analogous to and, once activated, works like a sub-menu + /// of a (but can be positioned anywhere). + /// + /// By default, a ContextMenu with sub-menus is displayed in a cascading manner, where each sub-menu pops out of the ContextMenu frame + /// (either to the right or left, depending on where the ContextMenu is relative to the edge of the screen). By setting + /// to , this behavior can be changed such that all sub-menus are + /// drawn within the ContextMenu frame. + /// + /// + /// ContextMenus can be activated using the Shift-F10 key (by default; use the to change to another key). + /// + /// + /// Callers can cause the ContextMenu to be activated on a right-mouse click (or other interaction) by calling . + /// + /// + /// ContextMenus are located using screen using screen coordinates and appear above all other Views. + /// /// public sealed class ContextMenu : IDisposable { private static MenuBar menuBar; @@ -12,15 +28,15 @@ namespace Terminal.Gui { private Toplevel container; /// - /// Initialize a context menu with empty menu items. + /// Initializes a context menu with no menu items. /// public ContextMenu () : this (0, 0, new MenuBarItem ()) { } /// - /// Initialize a context menu with menu items from a host . + /// Initializes a context menu, with a specifiying the parent/hose of the menu. /// /// The host view. - /// The menu items. + /// The menu items for the context menu. public ContextMenu (View host, MenuBarItem menuItems) : this (host.Frame.X, host.Frame.Y, menuItems) { @@ -28,10 +44,10 @@ namespace Terminal.Gui { } /// - /// Initialize a context menu with menu items. + /// Initializes a context menu with menu items at a specific screen location. /// - /// The left position. - /// The top position. + /// The left position (screen relative). + /// The top position (screen relative). /// The menu items. public ContextMenu (int x, int y, MenuBarItem menuItems) { @@ -48,7 +64,7 @@ namespace Terminal.Gui { } /// - /// Disposes the all the context menu objects instances. + /// Disposes the context menu object. /// public void Dispose () { @@ -65,7 +81,7 @@ namespace Terminal.Gui { } /// - /// Open the menu items. + /// Shows (opens) the ContextMenu, displaying the s it contains. /// public void Show () { @@ -116,7 +132,7 @@ namespace Terminal.Gui { Y = position.Y, Width = 0, Height = 0, - UseSubMenusSingleFrame = this.UseSubMenusSingleFrame + UseSubMenusSingleFrame = this.UseSubMenusSingleFrame }; menuBar.isContextMenuLoading = true; @@ -138,7 +154,7 @@ namespace Terminal.Gui { } /// - /// Close the menu items. + /// Hides (closes) the ContextMenu. /// public void Hide () { @@ -157,7 +173,7 @@ namespace Terminal.Gui { public event Action MouseFlagsChanged; /// - /// Gets or set the menu position. + /// Gets or sets the menu position. /// public Point Position { get; set; } @@ -167,7 +183,7 @@ namespace Terminal.Gui { public MenuBarItem MenuItems { get; set; } /// - /// The used to activate the context menu by keyboard. + /// specifies they keyboard key that will activate the context menu with the keyboard. /// public Key Key { get => key; @@ -179,7 +195,7 @@ namespace Terminal.Gui { } /// - /// The used to activate the context menu by mouse. + /// specifies the mouse action used to activate the context menu by mouse. /// public MouseFlags MouseFlags { get => mouseFlags; @@ -191,7 +207,7 @@ namespace Terminal.Gui { } /// - /// Gets information whether menu is showing or not. + /// Gets whether the ContextMenu is showing or not. /// public static bool IsShow { get; private set; } @@ -202,8 +218,9 @@ namespace Terminal.Gui { public View Host { get; set; } /// - /// Gets or sets whether forces the minimum position to zero - /// if the left or right position are negative. + /// Sets or gets whether the context menu be forced to the right, ensuring it is not clipped, if the x position + /// is less than zero. The default is which means the context menu will be forced to the right. + /// If set to , the context menu will be clipped on the left if x is less than zero. /// public bool ForceMinimumPosToZero { get; set; } = true; @@ -213,7 +230,9 @@ namespace Terminal.Gui { public MenuBar MenuBar { get => menuBar; } /// - /// Gets or sets if the sub-menus must be displayed in a single or multiple frames. + /// Gets or sets if sub-menus will be displayed using a "single frame" menu style. If , the ContextMenu + /// and any sub-menus that would normally cascade will be displayed within a single frame. If (the default), + /// sub-menus will cascade using separate frames for each level of the menu hierarchy. /// public bool UseSubMenusSingleFrame { get; set; } } diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 7a7d6e3d3..ed037a10f 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -11,7 +11,7 @@ namespace Terminal.Gui { [Flags] public enum MenuItemCheckStyle { /// - /// The menu item will be shown normally, with no check indicator. + /// The menu item will be shown normally, with no check indicator. The default. /// NoCheck = 0b_0000_0000, @@ -69,7 +69,7 @@ namespace Terminal.Gui { } /// - /// The HotKey is used to activate a with they keyboard. HotKeys are defined by prefixing the + /// The HotKey is used to activate a with the keyboard. HotKeys are defined by prefixing the /// of a MenuItem with an underscore ('_'). /// /// Pressing Alt-Hotkey for a (menu items on the menu bar) works even if the menu is not active). @@ -134,7 +134,7 @@ namespace Terminal.Gui { /// /// Gets or sets the action to be invoked to determine if the menu can be triggered. If returns - /// the menu item will be enabled. Otherwise it will be disabled. + /// the menu item will be enabled. Otherwise, it will be disabled. /// /// Function to determine if the action is can be executed or not. public Func CanExecute { get; set; } @@ -154,7 +154,7 @@ namespace Terminal.Gui { // ┌─────────────────┐ // │ ◌ TopLevel Alt+T │ // └─────────────────┘ - // TODO: Repalace the `2` literals with named constants + // TODO: Replace the `2` literals with named constants internal int Width => 1 + // space before Title TitleLength + 2 + // space after Title - BUGBUG: This should be 1 @@ -230,8 +230,8 @@ namespace Terminal.Gui { } /// - /// is a menu item on an app's . MenuBarItems do not support - /// . + /// is a menu item on an app's . + /// MenuBarItems do not support . /// public class MenuBarItem : MenuItem { /// @@ -834,30 +834,35 @@ namespace Terminal.Gui { } } - - /// /// - /// Provides a menu bar with drop-down and cascading menus. - /// - /// - /// + /// Provides a menu bar that spans the top of a View with drop-down and cascading menus. /// + /// + /// By default, any sub-sub-menus (sub-menus of the s added to s) + /// are displayed in a cascading manner, where each sub-sub-menu pops out of the sub-menu frame + /// (either to the right or left, depending on where the sub-menu is relative to the edge of the screen). By setting + /// to , this behavior can be changed such that all sub-sub-menus are + /// drawn within a single frame below the MenuBar. + /// /// /// /// - /// The appears on the first row of the terminal and uses the full width. + /// The appears on the first row of the parent View and uses the full width. /// /// /// The provides global hotkeys for the application. See . /// + /// + /// See also: + /// /// public class MenuBar : View { internal int selected; internal int selectedSub; /// - /// Gets or sets the array of s for the menu. Only set this when the is visible. + /// Gets or sets the array of s for the menu. Only set this after the is visible. /// /// The menu array. public MenuBarItem [] Menus { get; set; } @@ -880,7 +885,7 @@ namespace Terminal.Gui { static ustring shortcutDelimiter = "+"; /// - /// Used for change the shortcut delimiter separator. + /// Sets or gets the shortcut delimiter separator. The default is "+". /// public static ustring ShortcutDelimiter { get => shortcutDelimiter; @@ -900,6 +905,13 @@ namespace Terminal.Gui { /// /// Gets or sets if the sub-menus must be displayed in a single or multiple frames. + /// + /// By default any sub-sub-menus (sub-menus of the main s) are displayed in a cascading manner, + /// where each sub-sub-menu pops out of the sub-menu frame + /// (either to the right or left, depending on where the sub-menu is relative to the edge of the screen). By setting + /// to , this behavior can be changed such that all sub-sub-menus are + /// drawn within a single frame below the MenuBar. + /// /// public bool UseSubMenusSingleFrame { get => useSubMenusSingleFrame; @@ -1123,7 +1135,7 @@ namespace Terminal.Gui { public event Action MenuClosing; /// - /// Raised when all the menu are closed. + /// Raised when all the menu is closed. /// public event Action MenuAllClosed; @@ -1146,7 +1158,7 @@ namespace Terminal.Gui { internal bool isMenuClosing; /// - /// True if the menu is open; otherwise false. + /// if the menu is open; otherwise . /// public bool IsMenuOpen { get; protected set; } @@ -1179,7 +1191,7 @@ namespace Terminal.Gui { } /// - /// Virtual method that will invoke the + /// Virtual method that will invoke the . /// /// The current menu to be closed. /// Whether the current menu will be reopen. @@ -1192,7 +1204,7 @@ namespace Terminal.Gui { } /// - /// Virtual method that will invoke the + /// Virtual method that will invoke the . /// public virtual void OnMenuAllClosed () { @@ -1202,7 +1214,7 @@ namespace Terminal.Gui { View lastFocused; /// - /// Get the lasted focused view before open the menu. + /// Gets the view that was last focused before opening the menu. /// public View LastFocused { get; private set; } @@ -1290,7 +1302,7 @@ namespace Terminal.Gui { } /// - /// Opens the current Menu programatically. + /// Opens the Menu programatically, as though the F9 key were pressed. /// public void OpenMenu () { @@ -1372,7 +1384,7 @@ namespace Terminal.Gui { } /// - /// Closes the current Menu programatically, if open and not canceled. + /// Closes the Menu programmatically if open and not canceled (as though F9 were pressed). /// public bool CloseMenu (bool ignoreUseSubMenusSingleFrame = false) { @@ -1474,26 +1486,6 @@ namespace Terminal.Gui { if (openSubMenu.Count > 0) openCurrentMenu = openSubMenu.Last (); - //if (openMenu.Subviews.Count == 0) - // return; - //if (index == 0) { - // //SuperView.SetFocus (previousSubFocused); - // FocusPrev (); - // return; - //} - - //for (int i = openMenu.Subviews.Count - 1; i > index; i--) { - // isMenuClosing = true; - // if (openMenu.Subviews.Count - 1 > 0) - // SuperView.SetFocus (openMenu.Subviews [i - 1]); - // else - // SuperView.SetFocus (openMenu); - // if (openMenu != null) { - // Remove (openMenu.Subviews [i]); - // openMenu.Remove (openMenu.Subviews [i]); - // } - // RemoveSubMenu (i); - //} isMenuClosing = false; } @@ -1894,47 +1886,6 @@ namespace Terminal.Gui { handled = false; return false; } - //if (me.View != this && me.Flags != MouseFlags.Button1Pressed) - // return true; - //else if (me.View != this && me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) { - // Application.UngrabMouse (); - // host.CloseAllMenus (); - // return true; - //} - - - //if (!(me.View is MenuBar) && !(me.View is Menu) && me.Flags != MouseFlags.Button1Pressed)) - // return false; - - //if (Application.MouseGrabView != null) { - // if (me.View is MenuBar || me.View is Menu) { - // me.X -= me.OfX; - // me.Y -= me.OfY; - // me.View.MouseEvent (me); - // return true; - // } else if (!(me.View is MenuBar || me.View is Menu) && me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) { - // Application.UngrabMouse (); - // CloseAllMenus (); - // } - //} else if (!isMenuClosed && selected == -1 && me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) { - // Application.GrabMouse (this); - // return true; - //} - - //if (Application.MouseGrabView != null) { - // if (Application.MouseGrabView == me.View && me.View == current) { - // me.X -= me.OfX; - // me.Y -= me.OfY; - // } else if (me.View != current && me.View is MenuBar && me.View is Menu) { - // Application.UngrabMouse (); - // Application.GrabMouse (me.View); - // } else if (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) { - // Application.UngrabMouse (); - // CloseMenu (); - // } - //} else if ((!isMenuClosed && selected > -1)) { - // Application.GrabMouse (current); - //} handled = true; @@ -1988,12 +1939,13 @@ namespace Terminal.Gui { /// public MenuBarItem NewMenuBarItem { get; set; } /// - /// Flag that allows you to cancel the opening of the menu. + /// Flag that allows the cancellation of the event. If set to in the + /// event handler, the event will be canceled. /// public bool Cancel { get; set; } /// - /// Initializes a new instance of + /// Initializes a new instance of . /// /// The current parent. public MenuOpeningEventArgs (MenuBarItem currentMenu) @@ -2012,7 +1964,7 @@ namespace Terminal.Gui { public MenuBarItem CurrentMenu { get; } /// - /// Indicates whether the current menu will be reopen. + /// Indicates whether the current menu will reopen. /// public bool Reopen { get; } @@ -2022,15 +1974,16 @@ namespace Terminal.Gui { public bool IsSubMenu { get; } /// - /// Flag that allows you to cancel the opening of the menu. + /// Flag that allows the cancellation of the event. If set to in the + /// event handler, the event will be canceled. /// public bool Cancel { get; set; } /// - /// Initializes a new instance of + /// Initializes a new instance of . /// /// The current parent. - /// Whether the current menu will be reopen. + /// Whether the current menu will reopen. /// Indicates whether it is a sub-menu. public MenuClosingEventArgs (MenuBarItem currentMenu, bool reopen, bool isSubMenu) { diff --git a/UICatalog/Scenarios/Editor.cs b/UICatalog/Scenarios/Editor.cs index 633158ee5..5f679c74b 100644 --- a/UICatalog/Scenarios/Editor.cs +++ b/UICatalog/Scenarios/Editor.cs @@ -116,6 +116,8 @@ namespace UICatalog.Scenarios { new MenuBarItem ("_Languages", GetSupportedCultures ()) }) }); + menu.UseSubMenusSingleFrame = true; + Top.Add (menu); var statusBar = new StatusBar (new StatusItem [] { From e6c322b1d5522563bff9038f29c345c7875fc0db Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Fri, 21 Oct 2022 16:12:02 -0600 Subject: [PATCH 10/10] backed out testing change --- UICatalog/Scenarios/Editor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/UICatalog/Scenarios/Editor.cs b/UICatalog/Scenarios/Editor.cs index 5f679c74b..96f11363e 100644 --- a/UICatalog/Scenarios/Editor.cs +++ b/UICatalog/Scenarios/Editor.cs @@ -116,7 +116,6 @@ namespace UICatalog.Scenarios { new MenuBarItem ("_Languages", GetSupportedCultures ()) }) }); - menu.UseSubMenusSingleFrame = true; Top.Add (menu);