Преглед изворни кода

Allow key events to traverse the TopLevel hierarchy unless IsModal=true (#262)

It's quite common for key events to flow up the containment hierarchy in
UI frameworks. This could simplify management of global hotkeys that can
be placed in a top-level "App" and have all views shown subsequently just
"inherit" that behavior as long as they let the key event flow.

Propagating keys upwards is typically undesirable in modal dialogs, so we
set it to true in the `Dialog` base class.

Make sure we make a copy of the items since a key handler could modify the
top-level collection (i.e. by closing a dialog in between this processing).
Daniel Cazzulino пре 5 година
родитељ
комит
c072e29a68
2 измењених фајлова са 29 додато и 8 уклоњено
  1. 28 8
      Terminal.Gui/Core.cs
  2. 1 0
      Terminal.Gui/Dialogs/Dialog.cs

+ 28 - 8
Terminal.Gui/Core.cs

@@ -1323,6 +1323,13 @@ namespace Terminal.Gui {
 			get => true;
 		}
 
+		/// <summary>
+		/// Determines whether the <see cref="Toplevel"/> is modal or not. 
+		/// Causes <see cref="ProcessKey(KeyEvent)"/> to propagate keys upwards 
+		/// by default unless set to <see langword="true"/>.
+		/// </summary>
+		public bool Modal { get; set; }
+
 		public override bool ProcessKey (KeyEvent keyEvent)
 		{
 			if (base.ProcessKey (keyEvent))
@@ -1790,15 +1797,28 @@ namespace Terminal.Gui {
 
 		static void ProcessKeyEvent (KeyEvent ke)
 		{
-			if (Current.ProcessHotKey (ke))
-				return;
+			var chain = toplevels.ToList();
+			foreach (var topLevel in chain) {
+				if (topLevel.Modal)
+					break;
+				if (topLevel.ProcessHotKey (ke))
+					return;
+			}
 
-			if (Current.ProcessKey (ke))
-				return;
-			
-			// Process the key normally
-			if (Current.ProcessColdKey (ke))
-				return;
+			foreach (var topLevel in chain) {
+				if (topLevel.Modal)
+					break;
+				if (topLevel.ProcessKey (ke))
+					return;
+			}
+
+			foreach (var topLevel in chain) {
+				if (topLevel.Modal)
+					break;
+				// Process the key normally
+				if (topLevel.ProcessColdKey (ke))
+					return;
+			}
 		}
 
 		static View FindDeepestView (View start, int x, int y, out int resx, out int resy)

+ 1 - 0
Terminal.Gui/Dialogs/Dialog.cs

@@ -38,6 +38,7 @@ namespace Terminal.Gui {
 			Width = width;
 			Height = height;
 			ColorScheme = Colors.Dialog;
+			Modal = true;
 
 			if (buttons != null) {
 				foreach (var b in buttons) {