Răsfoiți Sursa

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 ani în urmă
părinte
comite
c072e29a68
2 a modificat fișierele cu 29 adăugiri și 8 ștergeri
  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) {