2
0
Эх сурвалжийг харах

Fixes #829. Hangs with disabled menu item selected solved.

BDisp 5 жил өмнө
parent
commit
ffef3276e4

+ 3 - 0
Terminal.Gui/Core/View.cs

@@ -1911,6 +1911,9 @@ namespace Terminal.Gui {
 				Remove (subview);
 				Remove (subview);
 				subview.Dispose ();
 				subview.Dispose ();
 			}
 			}
+			if (Application.Top.focused == this) {
+				Application.Top.focused = null;
+			}
 			base.Dispose (disposing);
 			base.Dispose (disposing);
 		}
 		}
 
 

+ 163 - 55
Terminal.Gui/Views/Menu.cs

@@ -429,66 +429,19 @@ namespace Terminal.Gui {
 
 
 		public override bool ProcessKey (KeyEvent kb)
 		public override bool ProcessKey (KeyEvent kb)
 		{
 		{
-			bool disabled;
 			switch (kb.Key) {
 			switch (kb.Key) {
 			case Key.Tab:
 			case Key.Tab:
 				host.CleanUp ();
 				host.CleanUp ();
 				return true;
 				return true;
 			case Key.CursorUp:
 			case Key.CursorUp:
-				if (barItems.IsTopLevel || current == -1)
-					return true;
-				do {
-					disabled = false;
-					current--;
-					if (host.UseKeysUpDownAsKeysLeftRight) {
-						if (current == -1 && barItems.Children [current + 1].IsFromSubMenu && host.selectedSub > -1) {
-							current++;
-							host.PreviousMenu (true);
-							if (host.openMenu.current > 0) {
-								host.openMenu.current--;
-							}
-							break;
-						}
-					}
-					if (current < 0)
-						current = barItems.Children.Length - 1;
-					var item = barItems.Children [current];
-					if (item == null || !item.IsEnabled ()) disabled = true;
-					if (host.UseKeysUpDownAsKeysLeftRight && barItems.Children [current]?.SubMenu != null &&
-						!disabled && host.IsMenuOpen) {
-						CheckSubMenu ();
-						break;
-					}
-				} while (barItems.Children [current] == null || disabled);
-				SetNeedsDisplay ();
-				return true;
+				return MoveUp ();
 			case Key.CursorDown:
 			case Key.CursorDown:
-				if (barItems.IsTopLevel) {
-					return true;
-				}
-
-				do {
-					current++;
-					disabled = false;
-					if (current == barItems.Children.Length)
-						current = 0;
-					var item = barItems.Children [current];
-					if (item == null || !item.IsEnabled ()) disabled = true;
-					if (host.UseKeysUpDownAsKeysLeftRight && barItems.Children [current]?.SubMenu != null &&
-						!disabled && host.IsMenuOpen) {
-						CheckSubMenu ();
-						break;
-					}
-					if (!host.IsMenuOpen)
-						host.OpenMenu (host.selected);
-				} while (barItems.Children [current] == null || disabled);
-				SetNeedsDisplay ();
-				return true;
+				return MoveDown ();
 			case Key.CursorLeft:
 			case Key.CursorLeft:
 				host.PreviousMenu (true);
 				host.PreviousMenu (true);
 				return true;
 				return true;
 			case Key.CursorRight:
 			case Key.CursorRight:
-				host.NextMenu (barItems.IsTopLevel || barItems.Children [current].IsFromSubMenu ? true : false);
+				host.NextMenu (barItems.IsTopLevel || (barItems.Children != null && current > -1 && current < barItems.Children.Length && barItems.Children [current].IsFromSubMenu) ? true : false);
 				return true;
 				return true;
 			case Key.Esc:
 			case Key.Esc:
 				Application.UngrabMouse ();
 				Application.UngrabMouse ();
@@ -497,8 +450,7 @@ namespace Terminal.Gui {
 			case Key.Enter:
 			case Key.Enter:
 				if (barItems.IsTopLevel) {
 				if (barItems.IsTopLevel) {
 					Run (barItems.Action);
 					Run (barItems.Action);
-				} else {
-					CheckSubMenu ();
+				} else if (current > -1) {
 					Run (barItems.Children [current].Action);
 					Run (barItems.Children [current].Action);
 				}
 				}
 				return true;
 				return true;
@@ -520,6 +472,95 @@ namespace Terminal.Gui {
 			return false;
 			return false;
 		}
 		}
 
 
+		bool MoveDown ()
+		{
+			if (barItems.IsTopLevel) {
+				return true;
+			}
+			bool disabled;
+			do {
+				current++;
+				if (current >= barItems.Children.Length) {
+					current = 0;
+				}
+				if (!host.SelectEnabledItem (barItems.Children, current, out current)) {
+					if (current == -1 && barItems.Children [current + 1].IsFromSubMenu && host.selectedSub > -1) {
+						current++;
+						host.PreviousMenu (true);
+						if (host.openMenu.current > 0) {
+							host.openMenu.current++;
+							if (host.openMenu.current >= barItems.Children.Length) {
+								host.openMenu.current = 0;
+								host.SelectEnabledItem (host.openMenu.barItems.Children, host.openMenu.current, out host.openMenu.current);
+							}
+							host.openCurrentMenu = host.openMenu;
+						}
+					}
+					break;
+				}
+				var item = barItems.Children [current];
+				if (item?.IsEnabled () != true) {
+					disabled = true;
+				} else {
+					disabled = false;
+				}
+				if (host.UseKeysUpDownAsKeysLeftRight && barItems.Children [current]?.SubMenu != null &&
+					!disabled && host.IsMenuOpen) {
+					CheckSubMenu ();
+					break;
+				}
+				if (!host.IsMenuOpen) {
+					host.OpenMenu (host.selected);
+				}
+			} while (barItems.Children [current] == null || disabled);
+			SetNeedsDisplay ();
+			return true;
+		}
+
+		bool MoveUp ()
+		{
+			if (barItems.IsTopLevel || current == -1) {
+				return true;
+			}
+			bool disabled;
+			do {
+				current--;
+				if (host.UseKeysUpDownAsKeysLeftRight) {
+					if (current == -1 && barItems.Children [current + 1].IsFromSubMenu && host.selectedSub > -1) {
+						current++;
+						host.PreviousMenu (true);
+						if (host.openMenu.current > 0) {
+							host.openMenu.current--;
+							host.openCurrentMenu = host.openMenu;
+						}
+						break;
+					}
+				}
+				if (current < 0)
+					current = barItems.Children.Length - 1;
+				if (!host.SelectEnabledItem (barItems.Children, current, out current, false)) {
+					current = 0;
+					if (!host.SelectEnabledItem (barItems.Children, current, out current)) {
+						host.CloseMenu ();
+					}
+					break;
+				}
+				var item = barItems.Children [current];
+				if (item?.IsEnabled () != true) {
+					disabled = true;
+				} else {
+					disabled = false;
+				}
+				if (host.UseKeysUpDownAsKeysLeftRight && barItems.Children [current]?.SubMenu != null &&
+					!disabled && host.IsMenuOpen) {
+					CheckSubMenu ();
+					break;
+				}
+			} while (barItems.Children [current] == null || disabled);
+			SetNeedsDisplay ();
+			return true;
+		}
+
 		public override bool MouseEvent (MouseEvent me)
 		public override bool MouseEvent (MouseEvent me)
 		{
 		{
 			if (!host.handled && !host.HandleGrabView (me, this)) {
 			if (!host.handled && !host.HandleGrabView (me, this)) {
@@ -558,7 +599,7 @@ namespace Terminal.Gui {
 
 
 		internal void CheckSubMenu ()
 		internal void CheckSubMenu ()
 		{
 		{
-			if (barItems.Children [current] == null)
+			if (current == -1 || barItems.Children [current] == null)
 				return;
 				return;
 			var subMenu = barItems.Children [current].SubMenu;
 			var subMenu = barItems.Children [current].SubMenu;
 			if (subMenu != null) {
 			if (subMenu != null) {
@@ -788,7 +829,7 @@ namespace Terminal.Gui {
 		public Action MenuClosing;
 		public Action MenuClosing;
 
 
 		internal Menu openMenu;
 		internal Menu openMenu;
-		Menu openCurrentMenu;
+		internal Menu openCurrentMenu;
 		internal List<Menu> openSubMenu;
 		internal List<Menu> openSubMenu;
 		View previousFocused;
 		View previousFocused;
 		internal bool isMenuOpening;
 		internal bool isMenuOpening;
@@ -878,6 +919,10 @@ namespace Terminal.Gui {
 
 
 			previousFocused = SuperView.Focused;
 			previousFocused = SuperView.Focused;
 			OpenMenu (selected);
 			OpenMenu (selected);
+			if (!SelectEnabledItem (openCurrentMenu.barItems.Children, openCurrentMenu.current, out openCurrentMenu.current)) {
+				CloseMenu ();
+			}
+			openCurrentMenu.CheckSubMenu ();
 			Application.GrabMouse (this);
 			Application.GrabMouse (this);
 		}
 		}
 
 
@@ -891,9 +936,58 @@ namespace Terminal.Gui {
 				previousFocused = SuperView.Focused;
 				previousFocused = SuperView.Focused;
 
 
 			OpenMenu (idx, sIdx, subMenu);
 			OpenMenu (idx, sIdx, subMenu);
+			if (!SelectEnabledItem (openCurrentMenu.barItems.Children, openCurrentMenu.current, out openCurrentMenu.current)) {
+				if (subMenu == null) {
+					CloseMenu ();
+				}
+			}
 			SetNeedsDisplay ();
 			SetNeedsDisplay ();
 		}
 		}
 
 
+		internal bool SelectEnabledItem (IEnumerable<MenuItem> chldren, int current, out int newCurrent, bool forward = true)
+		{
+			if (chldren == null) {
+				newCurrent = -1;
+				return true;
+			}
+
+			IEnumerable<MenuItem> childrens;
+			if (forward) {
+				childrens = chldren;
+			} else {
+				childrens = chldren.Reverse ();
+			}
+			int count;
+			if (forward) {
+				count = -1;
+			} else {
+				count = childrens.Count ();
+			}
+			foreach (var child in childrens) {
+				if (forward) {
+					if (++count < current) {
+						continue;
+					}
+				} else {
+					if (--count > current) {
+						continue;
+					}
+				}
+				if (child == null || !child.IsEnabled ()) {
+					if (forward) {
+						current++;
+					} else {
+						current--;
+					}
+				} else {
+					newCurrent = current;
+					return true;
+				}
+			}
+			newCurrent = -1;
+			return false;
+		}
+
 		/// <summary>
 		/// <summary>
 		/// Closes the current Menu programatically, if open.
 		/// Closes the current Menu programatically, if open.
 		/// </summary>
 		/// </summary>
@@ -1041,6 +1135,13 @@ namespace Terminal.Gui {
 				if (selected > -1)
 				if (selected > -1)
 					CloseMenu (true, false);
 					CloseMenu (true, false);
 				OpenMenu (selected);
 				OpenMenu (selected);
+				if (!SelectEnabledItem (openCurrentMenu.barItems.Children, openCurrentMenu.current, out openCurrentMenu.current, false)) {
+					openCurrentMenu.current = 0;
+					if (!SelectEnabledItem (openCurrentMenu.barItems.Children, openCurrentMenu.current, out openCurrentMenu.current)) {
+						CloseMenu ();
+					}
+					break;
+				}
 				break;
 				break;
 			case true:
 			case true:
 				if (selectedSub > -1) {
 				if (selectedSub > -1) {
@@ -1068,6 +1169,7 @@ namespace Terminal.Gui {
 				if (selected > -1)
 				if (selected > -1)
 					CloseMenu (true);
 					CloseMenu (true);
 				OpenMenu (selected);
 				OpenMenu (selected);
+				SelectEnabledItem (openCurrentMenu.barItems.Children, openCurrentMenu.current, out openCurrentMenu.current);
 				break;
 				break;
 			case true:
 			case true:
 				if (UseKeysUpDownAsKeysLeftRight) {
 				if (UseKeysUpDownAsKeysLeftRight) {
@@ -1120,6 +1222,10 @@ namespace Terminal.Gui {
 				Application.GrabMouse (this);
 				Application.GrabMouse (this);
 				selected = i;
 				selected = i;
 				OpenMenu (i);
 				OpenMenu (i);
+				if (!SelectEnabledItem (openCurrentMenu.barItems.Children, openCurrentMenu.current, out openCurrentMenu.current)) {
+					CloseMenu ();
+				}
+				openCurrentMenu.CheckSubMenu ();
 			}
 			}
 		}
 		}
 
 
@@ -1173,7 +1279,9 @@ namespace Terminal.Gui {
 
 
 			case Key.CursorDown:
 			case Key.CursorDown:
 			case Key.Enter:
 			case Key.Enter:
-				ProcessMenu (selected, Menus [selected]);
+				if (selected > -1) {
+					ProcessMenu (selected, Menus [selected]); 
+				}
 				break;
 				break;
 
 
 			default:
 			default: