Browse Source

Button pressed now close the menu and the menu length is the same with or without hot-keys

BDisp 3 years ago
parent
commit
ed2c516702
3 changed files with 189 additions and 67 deletions
  1. 23 27
      Terminal.Gui/Views/Menu.cs
  2. 27 27
      UnitTests/ContextMenuTests.cs
  3. 139 13
      UnitTests/MenuTests.cs

+ 23 - 27
Terminal.Gui/Views/Menu.cs

@@ -41,9 +41,9 @@ namespace Terminal.Gui {
 	/// </summary>
 	public class MenuItem {
 		ustring title;
-
 		ShortcutHelper shortcutHelper;
-		
+		internal int TitleLength => GetMenuBarItemLength (Title);
+
 		/// <summary>
 		/// Gets or sets arbitrary data for the menu item.
 		/// </summary>
@@ -141,9 +141,9 @@ namespace Terminal.Gui {
 			return CanExecute == null ? true : CanExecute ();
 		}
 
-		internal int Width => Title.Sum (x => Rune.ColumnWidth (x)) + Help.Sum (x => Rune.ColumnWidth (x)) + 1 + 2 +
+		internal int Width => 1 + TitleLength + (Help.ConsoleWidth > 0 ? Help.ConsoleWidth + 2 : 0) +
 			(Checked || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio) ? 2 : 0) +
-			(ShortcutTag.RuneCount > 0 ? ShortcutTag.RuneCount + 2 : 0);
+			(ShortcutTag.ConsoleWidth > 0 ? ShortcutTag.ConsoleWidth + 2 : 0) + 2;
 
 		/// <summary>
 		/// Sets or gets whether the <see cref="MenuItem"/> shows a check indicator or not. See <see cref="MenuItemCheckStyle"/>.
@@ -198,6 +198,18 @@ namespace Terminal.Gui {
 				}
 			}
 		}
+
+		int GetMenuBarItemLength (ustring title)
+		{
+			int len = 0;
+			foreach (var ch in title) {
+				if (ch == MenuBar.HotKeySpecifier)
+					continue;
+				len += Math.Max (Rune.ColumnWidth (ch), 1);
+			}
+
+			return len;
+		}
 	}
 
 	/// <summary>
@@ -351,18 +363,6 @@ namespace Terminal.Gui {
 			Title = title;
 		}
 
-		int GetMenuBarItemLength (ustring title)
-		{
-			int len = 0;
-			foreach (var ch in title) {
-				if (ch == MenuBar.HotKeySpecifier)
-					continue;
-				len++;
-			}
-
-			return len;
-		}
-
 		///// <summary>
 		///// Gets or sets the title to display.
 		///// </summary>
@@ -375,10 +375,7 @@ namespace Terminal.Gui {
 		/// <value>The children.</value>
 		public MenuItem [] Children { get; set; }
 
-		internal int TitleLength => GetMenuBarItemLength (Title);
-
 		internal bool IsTopLevel { get => Parent == null && (Children == null || Children.Length == 0) && Action != null; }
-
 	}
 
 	class Menu : View {
@@ -529,7 +526,7 @@ namespace Terminal.Gui {
 					}
 
 					// The help string
-					var l = item.ShortcutTag.RuneCount == 0 ? item.Help.RuneCount : item.Help.RuneCount + item.ShortcutTag.RuneCount + 2;
+					var l = item.ShortcutTag.ConsoleWidth == 0 ? item.Help.ConsoleWidth : item.Help.ConsoleWidth + item.ShortcutTag.ConsoleWidth + 2;
 					var col = Frame.Width - l - 2;
 					ViewToScreen (col, i + 1, out vtsCol, out _, false);
 					if (vtsCol < Driver.Cols) {
@@ -538,7 +535,7 @@ namespace Terminal.Gui {
 
 						// The shortcut tag string
 						if (!item.ShortcutTag.IsEmpty) {
-							l = item.ShortcutTag.RuneCount;
+							l = item.ShortcutTag.ConsoleWidth;
 							Move (Frame.Width - l - 2, 1 + i);
 							Driver.AddStr (item.ShortcutTag);
 						}
@@ -1020,7 +1017,7 @@ namespace Terminal.Gui {
 					normalColor = GetNormalColor ();
 				}
 				DrawHotString (menu.Help.IsEmpty ? $" {menu.Title}  " : $" {menu.Title}  {menu.Help}  ", hotColor, normalColor);
-				pos += 1 + menu.TitleLength + (menu.Help.Length > 0 ? menu.Help.Length + 2 : 0) + 2;
+				pos += 1 + menu.TitleLength + (menu.Help.ConsoleWidth > 0 ? menu.Help.ConsoleWidth + 2 : 0) + 2;
 			}
 			PositionCursor ();
 		}
@@ -1041,10 +1038,8 @@ namespace Terminal.Gui {
 						Move (pos + 1, 0);
 					}
 					return;
-				} else if (IsMenuOpen) {
-					pos += 1 + Menus [i].TitleLength + (Menus [i].Help.Length > 0 ? Menus [i].Help.Length + 2 : 0) + 2;
 				} else {
-					pos += 2 + Menus [i].TitleLength + (Menus [i].Help.Length > 0 ? Menus [i].Help.Length + 2 : 0) + 1;
+					pos += 1 + Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + 2;
 				}
 			}
 		}
@@ -1188,7 +1183,7 @@ namespace Terminal.Gui {
 				}
 
 				for (int i = 0; i < index; i++)
-					pos += Menus [i].Title.RuneCount + (Menus [i].Help.RuneCount > 0 ? Menus [i].Help.RuneCount + 2 : 0) + 2;
+					pos += 1 + 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;
@@ -1474,6 +1469,7 @@ namespace Terminal.Gui {
 					return;
 				if (LastFocused != null && LastFocused != this)
 					selected = -1;
+				Application.UngrabMouse ();
 			}
 			IsMenuOpen = false;
 			openedByHotKey = false;
@@ -1739,7 +1735,7 @@ namespace Terminal.Gui {
 				int pos = 1;
 				int cx = me.X;
 				for (int i = 0; i < Menus.Length; i++) {
-					if (cx >= pos && cx < pos + 1 + Menus [i].TitleLength + Menus [i].Help.RuneCount + 2) {
+					if (cx >= pos && cx < pos + 1 + Menus [i].TitleLength + Menus [i].Help.ConsoleWidth + 2) {
 						if (me.Flags == MouseFlags.Button1Clicked) {
 							if (Menus [i].IsTopLevel) {
 								var menu = new Menu (this, i, 0, Menus [i]);

+ 27 - 27
UnitTests/ContextMenuTests.cs

@@ -596,15 +596,15 @@ namespace Terminal.Gui.Core {
 
 
   Label: TextField
-         ┌───────────────────────────
-         │ Select All          Ctrl+T │
-         │ Delete All    Ctrl+Shift+D │
-         │ Copy                Ctrl+C │
-         │ Cut                 Ctrl+X │
-         │ Paste               Ctrl+V │
-         │ Undo                Ctrl+Z │
-         │ Redo                Ctrl+Y │
-         └───────────────────────────
+         ┌───────────────────────────┐
+         │ Select All         Ctrl+T │
+         │ Delete All   Ctrl+Shift+D │
+         │ Copy               Ctrl+C │
+         │ Cut                Ctrl+X │
+         │ Paste              Ctrl+V │
+         │ Undo               Ctrl+Z │
+         │ Redo               Ctrl+Y │
+         └───────────────────────────┘
 
 
 
@@ -612,7 +612,7 @@ namespace Terminal.Gui.Core {
 ";
 
 			var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
-			Assert.Equal (new Rect (2, 0, 39, 17), pos);
+			Assert.Equal (new Rect (2, 0, 38, 17), pos);
 		}
 
 		[Fact, AutoInitShutdown]
@@ -646,7 +646,7 @@ namespace Terminal.Gui.Core {
 
 			Application.Top.Add (menu, win, statusBar);
 			Application.Begin (Application.Top);
-			((FakeDriver)Application.Driver).SetBufferSize (45, 17);
+			((FakeDriver)Application.Driver).SetBufferSize (44, 17);
 
 
 			Assert.Equal (new Rect (9, 3, 20, 1), tf.Frame);
@@ -658,26 +658,26 @@ namespace Terminal.Gui.Core {
 			Application.Top.Redraw (Application.Top.Bounds);
 			var expected = @"
   File   Edit
-┌ Window ──────────────────────────────────
-│                                           
-│                                           
-│                                           
-│  Label: TextField                         
-│         ┌───────────────────────────┐    │
-│         │ Select All          Ctrl+T │    │
-│         │ Delete All    Ctrl+Shift+D │    │
-│         │ Copy                Ctrl+C │    │
-│         │ Cut                 Ctrl+X │    │
-│         │ Paste               Ctrl+V │    │
-│         │ Undo                Ctrl+Z │    │
-│         │ Redo                Ctrl+Y │    │
-│         └───────────────────────────┘    │
-└──────────────────────────────────────────
+┌ Window ──────────────────────────────────┐
+│                                          │
+│                                          │
+│                                          │
+│  Label: TextField                        │
+│         ┌───────────────────────────┐    │
+│         │ Select All         Ctrl+T │    │
+│         │ Delete All   Ctrl+Shift+D │    │
+│         │ Copy               Ctrl+C │    │
+│         │ Cut                Ctrl+X │    │
+│         │ Paste              Ctrl+V │    │
+│         │ Undo               Ctrl+Z │    │
+│         │ Redo               Ctrl+Y │    │
+│         └───────────────────────────┘    │
+└──────────────────────────────────────────┘
  F1 Help │ ^Q Quit
 ";
 
 			var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
-			Assert.Equal (new Rect (2, 0, 45, 17), pos);
+			Assert.Equal (new Rect (2, 0, 44, 17), pos);
 		}
 	}
 }

+ 139 - 13
UnitTests/MenuTests.cs

@@ -144,9 +144,9 @@ namespace Terminal.Gui.Views {
 			Application.Top.Redraw (Application.Top.Bounds);
 			var expected = @"
 Edit
-┌─────────────────────────────┐
-│ Copy  Copies the selection. │
-└─────────────────────────────┘
+┌─────────────────────────────
+│ Copy   Copies the selection. │
+└─────────────────────────────
 ";
 			GraphViewTests.AssertDriverContentsAre (expected, output);
 
@@ -157,9 +157,9 @@ Edit
 			Application.Top.Redraw (Application.Top.Bounds);
 			expected = @"
 Edit
-┌─────────────────────────────┐
-│ Copy  Copies the selection. │
-└─────────────────────────────┘
+┌─────────────────────────────
+│ Copy   Copies the selection. │
+└─────────────────────────────
 ";
 			GraphViewTests.AssertDriverContentsAre (expected, output);
 
@@ -1031,9 +1031,9 @@ Edit
 			Application.Top.Redraw (Application.Top.Bounds);
 			var expected = @"
   File   Edit
-┌──────
-│ New   
-└──────
+┌──────┐
+│ New  │
+└──────┘
 ";
 
 			var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
@@ -1048,17 +1048,143 @@ Edit
 			Application.Top.Redraw (Application.Top.Bounds);
 			expected = @"
   File   Edit
-       ┌───────
-       │ Copy   
-       └───────
+       ┌───────┐
+       │ Copy  │
+       └───────┘
 ";
 
 			pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
-			Assert.Equal (new Rect (2, 0, 17, 4), pos);
+			Assert.Equal (new Rect (2, 0, 16, 4), pos);
 
 			Assert.True (Application.Top.Subviews [1].ProcessKey (new (Key.C, null)));
 			Application.MainLoop.MainIteration ();
 			Assert.True (copyAction);
 		}
+
+		[Fact, AutoInitShutdown]
+		public void MenuBar_Position_And_Size_With_HotKeys_Is_The_Same_As_Without_HotKeys ()
+		{
+			// With HotKeys
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("_File", new MenuItem [] {
+					new MenuItem ("_New", "", null)
+				}),
+				new MenuBarItem ("_Edit", new MenuItem [] {
+					new MenuItem ("_Copy", "", null)
+				})
+			});
+
+			Application.Top.Add (menu);
+
+			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);
+
+			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);
+
+			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 (expected, output);
+			Assert.Equal (new Rect (2, 0, 13, 1), pos);
+
+			// Without HotKeys
+			menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("File", new MenuItem [] {
+					new MenuItem ("New", "", null)
+				}),
+				new MenuBarItem ("Edit", new MenuItem [] {
+					new MenuItem ("Copy", "", null)
+				})
+			});
+
+			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);
+
+			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);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void MenuBar_ButtonPressed_Open_The_Menu_ButtonPressed_Again_Close_The_Menu ()
+		{
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("File", new MenuItem [] {
+					new MenuItem ("New", "", null)
+				}),
+				new MenuBarItem ("Edit", new MenuItem [] {
+					new MenuItem ("Copy", "", 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 (2, 0, 13, 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
+";
+
+			pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output);
+			Assert.Equal (new Rect (2, 0, 13, 1), pos);
+		}
 	}
 }