Selaa lähdekoodia

Merge branch 'v2_develop' into v2_draw-over-a-modal-view_2478

Tig 2 vuotta sitten
vanhempi
commit
4629e2b85e

+ 0 - 18
Terminal.Gui/Core/Application.cs

@@ -1515,7 +1515,6 @@ namespace Terminal.Gui {
 		static void TerminalResized ()
 		{
 			var full = new Rect (0, 0, Driver.Cols, Driver.Rows);
-			SetToplevelsSize (full);
 			Resized?.Invoke (new ResizedEventArgs () { Cols = full.Width, Rows = full.Height });
 			Driver.Clip = full;
 			foreach (var t in toplevels) {
@@ -1527,23 +1526,6 @@ namespace Terminal.Gui {
 			Refresh ();
 		}
 
-		static void SetToplevelsSize (Rect full)
-		{
-			if (MdiTop == null) {
-				foreach (var t in toplevels) {
-					if (t?.SuperView == null && !t.Modal) {
-						t.Frame = full;
-						t.Width = full.Width;
-						t.Height = full.Height;
-					}
-				}
-			} else {
-				Top.Frame = full;
-				Top.Width = full.Width;
-				Top.Height = full.Height;
-			}
-		}
-
 		static bool SetCurrentAsTop ()
 		{
 			if (MdiTop == null && Current != Top && Current?.SuperView == null && Current?.Modal == false) {

+ 19 - 8
Terminal.Gui/Core/View.cs

@@ -986,7 +986,7 @@ namespace Terminal.Gui {
 			}
 			SetNeedsLayout ();
 			SetNeedsDisplay ();
-      
+
 			OnAdded (new SuperViewChangedEventArgs (this, view));
 			if (IsInitialized && !view.IsInitialized) {
 				view.BeginInit ();
@@ -1040,9 +1040,6 @@ namespace Terminal.Gui {
 			view.tabIndex = -1;
 			SetNeedsLayout ();
 			SetNeedsDisplay ();
-			if (subviews.Count < 1) {
-				CanFocus = false;
-			}
 			foreach (var v in subviews) {
 				if (v.Frame.IntersectsWith (touched))
 					view.SetNeedsDisplay ();
@@ -1679,7 +1676,14 @@ namespace Terminal.Gui {
 				return;
 			if (focused?.hasFocus == true && focused == view)
 				return;
+			if ((focused?.hasFocus == true && focused?.SuperView == view)
+				|| view == this) {
 
+				if (!view.hasFocus) {
+					view.hasFocus = true;
+				}
+				return;
+			}
 			// Make sure that this view is a subview
 			View c;
 			for (c = view.container; c != null; c = c.container)
@@ -1697,7 +1701,11 @@ namespace Terminal.Gui {
 			focused.EnsureFocus ();
 
 			// Send focus upwards
-			SuperView?.SetFocus (this);
+			if (SuperView != null) {
+				SuperView.SetFocus (this);
+			} else {
+				SetFocus (this);
+			}
 		}
 
 		/// <summary>
@@ -1712,7 +1720,11 @@ namespace Terminal.Gui {
 				return;
 			}
 
-			SuperView?.SetFocus (this);
+			if (SuperView != null) {
+				SuperView.SetFocus (this);
+			} else {
+				SetFocus (this);
+			}
 		}
 
 		/// <summary>
@@ -2132,9 +2144,8 @@ namespace Terminal.Gui {
 				FocusFirst ();
 				return focused != null;
 			}
-			var n = tabIndexes.Count;
 			var focusedIdx = -1;
-			for (var i = 0; i < n; i++) {
+			for (var i = 0; i < tabIndexes.Count; i++) {
 				var w = tabIndexes [i];
 
 				if (w.HasFocus) {

+ 1 - 1
Terminal.Gui/Core/Window.cs

@@ -100,7 +100,7 @@ namespace Terminal.Gui {
 
 			public override void OnCanFocusChanged ()
 			{
-				if (MostFocused == null && CanFocus && Visible) {
+				if (IsInitialized && MostFocused == null && CanFocus && Visible) {
 					EnsureFocus ();
 				}
 

+ 127 - 31
UnitTests/Core/ViewTests.cs

@@ -238,7 +238,7 @@ namespace Terminal.Gui.CoreTests {
 			var v = new View (new Rect (0, 0, 10, 24));
 			var t = new View ();
 
-			v.Added += (s,e) => {
+			v.Added += (s, e) => {
 				Assert.Same (v.SuperView, e.Parent);
 				Assert.Same (t, e.Parent);
 				Assert.Same (v, e.Child);
@@ -658,7 +658,7 @@ namespace Terminal.Gui.CoreTests {
 
 			int tc = 0, wc = 0, v1c = 0, v2c = 0, sv1c = 0;
 
-			w.Added += (s,e) => {
+			w.Added += (s, e) => {
 				Assert.Equal (e.Parent.Frame.Width, w.Frame.Width);
 				Assert.Equal (e.Parent.Frame.Height, w.Frame.Height);
 			};
@@ -1232,10 +1232,10 @@ namespace Terminal.Gui.CoreTests {
 			Assert.Equal (80, view.Bounds.Width);
 			Assert.Equal (25, view.Bounds.Height);
 			bool layoutStarted = false;
-			view.LayoutStarted += (s,e) => layoutStarted = true;
+			view.LayoutStarted += (s, e) => layoutStarted = true;
 			view.OnLayoutStarted (null);
 			Assert.True (layoutStarted);
-			view.LayoutComplete += (s,e) => layoutStarted = false;
+			view.LayoutComplete += (s, e) => layoutStarted = false;
 			view.OnLayoutComplete (null);
 			Assert.False (layoutStarted);
 			view.X = Pos.Center () - 41;
@@ -1252,7 +1252,7 @@ namespace Terminal.Gui.CoreTests {
 		{
 			var wasClicked = false;
 			var view = new Button ("Click Me");
-			view.Clicked += (s,e) => wasClicked = !wasClicked;
+			view.Clicked += (s, e) => wasClicked = !wasClicked;
 			Application.Top.Add (view);
 
 			view.ProcessKey (new KeyEvent (Key.Enter, null));
@@ -1281,7 +1281,7 @@ namespace Terminal.Gui.CoreTests {
 		{
 			var wasClicked = false;
 			var button = new Button ("Click Me");
-			button.Clicked += (s,e) => wasClicked = !wasClicked;
+			button.Clicked += (s, e) => wasClicked = !wasClicked;
 			var win = new Window () { Width = Dim.Fill (), Height = Dim.Fill () };
 			win.Add (button);
 			Application.Top.Add (win);
@@ -1452,11 +1452,11 @@ namespace Terminal.Gui.CoreTests {
 		[AutoInitShutdown]
 		public void CanFocus_Sets_To_False_On_Single_View_Focus_View_On_Another_Toplevel ()
 		{
-			var view1 = new View () { Width = 10, Height = 1, CanFocus = true };
-			var win1 = new Window () { Width = Dim.Percent (50), Height = Dim.Fill () };
+			var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true };
+			var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () };
 			win1.Add (view1);
-			var view2 = new View () { Width = 20, Height = 2, CanFocus = true };
-			var win2 = new Window () { X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () };
+			var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true };
+			var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () };
 			win2.Add (view2);
 			Application.Top.Add (win1, win2);
 			Application.Begin (Application.Top);
@@ -1464,7 +1464,7 @@ namespace Terminal.Gui.CoreTests {
 			Assert.True (view1.CanFocus);
 			Assert.True (view1.HasFocus);
 			Assert.True (view2.CanFocus);
-			Assert.True (view2.HasFocus);
+			Assert.False (view2.HasFocus);
 
 			view1.CanFocus = false;
 			Assert.False (view1.CanFocus);
@@ -1477,12 +1477,12 @@ namespace Terminal.Gui.CoreTests {
 		[AutoInitShutdown]
 		public void CanFocus_Sets_To_False_With_Two_Views_Focus_Another_View_On_The_Same_Toplevel ()
 		{
-			var view1 = new View () { Width = 10, Height = 1, CanFocus = true };
-			var view12 = new View () { Y = 5, Width = 10, Height = 1, CanFocus = true };
-			var win1 = new Window () { Width = Dim.Percent (50), Height = Dim.Fill () };
+			var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true };
+			var view12 = new View () { Id = "view12", Y = 5, Width = 10, Height = 1, CanFocus = true };
+			var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () };
 			win1.Add (view1, view12);
-			var view2 = new View () { Width = 20, Height = 2, CanFocus = true };
-			var win2 = new Window () { X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () };
+			var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true };
+			var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () };
 			win2.Add (view2);
 			Application.Top.Add (win1, win2);
 			Application.Begin (Application.Top);
@@ -1490,7 +1490,7 @@ namespace Terminal.Gui.CoreTests {
 			Assert.True (view1.CanFocus);
 			Assert.True (view1.HasFocus);
 			Assert.True (view2.CanFocus);
-			Assert.True (view2.HasFocus);
+			Assert.False (view2.HasFocus);
 
 			view1.CanFocus = false;
 			Assert.False (view1.CanFocus);
@@ -1503,11 +1503,11 @@ namespace Terminal.Gui.CoreTests {
 		[AutoInitShutdown]
 		public void CanFocus_Sets_To_False_On_Toplevel_Focus_View_On_Another_Toplevel ()
 		{
-			var view1 = new View () { Width = 10, Height = 1, CanFocus = true };
-			var win1 = new Window () { Width = Dim.Percent (50), Height = Dim.Fill () };
+			var view1 = new View () { Id = "view1", Width = 10, Height = 1, CanFocus = true };
+			var win1 = new Window () { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () };
 			win1.Add (view1);
-			var view2 = new View () { Width = 20, Height = 2, CanFocus = true };
-			var win2 = new Window () { X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () };
+			var view2 = new View () { Id = "view2", Width = 20, Height = 2, CanFocus = true };
+			var win2 = new Window () { Id = "win2", X = Pos.Right (win1), Width = Dim.Fill (), Height = Dim.Fill () };
 			win2.Add (view2);
 			Application.Top.Add (win1, win2);
 			Application.Begin (Application.Top);
@@ -1515,7 +1515,7 @@ namespace Terminal.Gui.CoreTests {
 			Assert.True (view1.CanFocus);
 			Assert.True (view1.HasFocus);
 			Assert.True (view2.CanFocus);
-			Assert.True (view2.HasFocus);
+			Assert.False (view2.HasFocus);
 
 			win1.CanFocus = false;
 			Assert.False (view1.CanFocus);
@@ -2025,7 +2025,7 @@ namespace Terminal.Gui.CoreTests {
 				Width = Dim.Fill (),
 				Height = Dim.Fill ()
 			};
-			view.DrawContent += (s,e) => {
+			view.DrawContent += (s, e) => {
 				view.DrawFrame (view.Bounds);
 				var savedClip = Application.Driver.Clip;
 				Application.Driver.Clip = new Rect (1, 1, view.Bounds.Width - 2, view.Bounds.Height - 2);
@@ -2073,7 +2073,7 @@ namespace Terminal.Gui.CoreTests {
 				Width = Dim.Fill (),
 				Height = Dim.Fill ()
 			};
-			view.DrawContent += (s,e) => {
+			view.DrawContent += (s, e) => {
 				view.DrawFrame (view.Bounds);
 				var savedClip = Application.Driver.Clip;
 				Application.Driver.Clip = new Rect (1, 1, view.Bounds.Width - 2, view.Bounds.Height - 2);
@@ -2268,7 +2268,7 @@ This is a tes
 			var tvCalled = false;
 
 			var view = new View ("View") { Width = 10, Height = 10 };
-			view.DrawContentComplete += (s,e) => viewCalled = true;
+			view.DrawContentComplete += (s, e) => viewCalled = true;
 			var tv = new TextView () { Y = 11, Width = 10, Height = 10 };
 			tv.DrawContentComplete += (s, e) => tvCalled = true;
 
@@ -2294,7 +2294,7 @@ This is a tes
 				e.Handled = true;
 				keyDown = true;
 			};
-			view.KeyPress += (s,e) => {
+			view.KeyPress += (s, e) => {
 				Assert.Equal (Key.a, e.KeyEvent.Key);
 				Assert.False (keyPress);
 				Assert.False (view.IsKeyPress);
@@ -2390,7 +2390,7 @@ This is a tes
 			var keyUp = false;
 
 			var view = new DerivedView ();
-			view.KeyDown += (s,e) => {
+			view.KeyDown += (s, e) => {
 				Assert.Equal (-1, e.KeyEvent.KeyValue);
 				Assert.Equal (shift, e.KeyEvent.IsShift);
 				Assert.Equal (alt, e.KeyEvent.IsAlt);
@@ -2441,15 +2441,15 @@ This is a tes
 			var view1 = new View { CanFocus = true };
 			var subView1 = new View { CanFocus = true };
 			var subView1subView1 = new View { CanFocus = true };
-			view1.Leave += (s,e) => {
+			view1.Leave += (s, e) => {
 				view1Leave = true;
 			};
-			subView1.Leave += (s,e) => {
+			subView1.Leave += (s, e) => {
 				subView1.Remove (subView1subView1);
 				subView1Leave = true;
 			};
 			view1.Add (subView1);
-			subView1subView1.Leave += (s,e) => {
+			subView1subView1.Leave += (s, e) => {
 				// This is never invoked
 				subView1subView1Leave = true;
 			};
@@ -2908,7 +2908,7 @@ At 0,0
 			Assert.Equal (new Rect (0, 0, 30, 1), label.NeedDisplay);
 			Assert.Equal (new Rect (0, 0, 13, 1), button.NeedDisplay);
 
-			top.LayoutComplete += (s,e) => {
+			top.LayoutComplete += (s, e) => {
 				Assert.Equal (new Rect (0, 0, 80, 25), top.NeedDisplay);
 			};
 
@@ -2957,5 +2957,101 @@ At 0,0
 
 			TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
 		}
+
+		[Fact, AutoInitShutdown]
+		public void Remove_Does_Not_Change_Focus ()
+		{
+			Assert.True (Application.Top.CanFocus);
+			Assert.False (Application.Top.HasFocus);
+
+			var container = new View () { Width = 10, Height = 10 };
+			var leave = false;
+			container.Leave += (s, e) => leave = true;
+			Assert.False (container.CanFocus);
+			var child = new View () { Width = Dim.Fill (), Height = Dim.Fill (), CanFocus = true };
+			container.Add (child);
+
+			Assert.True (container.CanFocus);
+			Assert.False (container.HasFocus);
+			Assert.True (child.CanFocus);
+			Assert.False (child.HasFocus);
+
+			Application.Top.Add (container);
+			Application.Begin (Application.Top);
+
+			Assert.True (Application.Top.CanFocus);
+			Assert.True (Application.Top.HasFocus);
+			Assert.True (container.CanFocus);
+			Assert.True (container.HasFocus);
+			Assert.True (child.CanFocus);
+			Assert.True (child.HasFocus);
+
+			container.Remove (child);
+			child.Dispose ();
+			child = null;
+			Assert.True (Application.Top.HasFocus);
+			Assert.True (container.CanFocus);
+			Assert.True (container.HasFocus);
+			Assert.Null (child);
+			Assert.False (leave);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void SetFocus_View_With_Null_Superview_Does_Not_Throw_Exception ()
+		{
+			Assert.True (Application.Top.CanFocus);
+			Assert.False (Application.Top.HasFocus);
+
+			var exception = Record.Exception (Application.Top.SetFocus);
+			Assert.Null (exception);
+			Assert.True (Application.Top.CanFocus);
+			Assert.True (Application.Top.HasFocus);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void FocusNext_Does_Not_Throws_If_A_View_Was_Removed_From_The_Collection ()
+		{
+			var top1 = Application.Top;
+			var view1 = new View () { Id = "view1", Width = 10, Height = 5, CanFocus = true };
+			var top2 = new Toplevel () { Id = "top2", Y = 1, Width = 10, Height = 5 };
+			var view2 = new View () { Id = "view2", Y = 1, Width = 10, Height = 5, CanFocus = true };
+			View view3 = null;
+			var removed = false;
+			view2.Enter += (s, e) => {
+				if (!removed) {
+					removed = true;
+					view3 = new View () { Id = "view3", Y = 1, Width = 10, Height = 5 };
+					Application.Current.Add (view3);
+					Application.Current.BringSubviewToFront (view3);
+					Assert.False (view3.HasFocus);
+				}
+			};
+			view2.Leave += (s, e) => {
+				Application.Current.Remove (view3);
+				view3.Dispose ();
+				view3 = null;
+			};
+			top2.Add (view2);
+			top1.Add (view1, top2);
+			Application.Begin (top1);
+
+			Assert.True (top1.HasFocus);
+			Assert.True (view1.HasFocus);
+			Assert.False (view2.HasFocus);
+			Assert.False (removed);
+			Assert.Null (view3);
+
+			Assert.True (top1.ProcessKey (new KeyEvent (Key.Tab | Key.CtrlMask, new KeyModifiers { Ctrl = true })));
+			Assert.True (top1.HasFocus);
+			Assert.False (view1.HasFocus);
+			Assert.True (view2.HasFocus);
+			Assert.True (removed);
+			Assert.NotNull (view3);
+
+			var exception = Record.Exception (() => top1.ProcessKey (new KeyEvent (Key.Tab | Key.CtrlMask, new KeyModifiers { Ctrl = true })));
+			Assert.Null (exception);
+			Assert.True (removed);
+			Assert.Null (view3);
+		}
 	}
 }

+ 14 - 14
UnitTests/TopLevels/ToplevelTests.cs

@@ -340,22 +340,22 @@ namespace Terminal.Gui.TopLevelTests {
 		{
 			var isRunning = false;
 
-			var win1 = new Window ("Win1") { Width = Dim.Percent (50f), Height = Dim.Fill () };
-			var lblTf1W1 = new Label ("Enter text in TextField on Win1:");
-			var tf1W1 = new TextField ("Text1 on Win1") { X = Pos.Right (lblTf1W1) + 1, Width = Dim.Fill () };
-			var lblTvW1 = new Label ("Enter text in TextView on Win1:") { Y = Pos.Bottom (lblTf1W1) + 1 };
-			var tvW1 = new TextView () { X = Pos.Left (tf1W1), Width = Dim.Fill (), Height = 2, Text = "First line Win1\nSecond line Win1" };
-			var lblTf2W1 = new Label ("Enter text in TextField on Win1:") { Y = Pos.Bottom (lblTvW1) + 1 };
-			var tf2W1 = new TextField ("Text2 on Win1") { X = Pos.Left (tf1W1), Width = Dim.Fill () };
+			var win1 = new Window ("Win1") { Id = "win1", Width = Dim.Percent (50f), Height = Dim.Fill () };
+			var lblTf1W1 = new Label ("Enter text in TextField on Win1:") { Id = "lblTf1W1" };
+			var tf1W1 = new TextField ("Text1 on Win1") { Id = "tf1W1", X = Pos.Right (lblTf1W1) + 1, Width = Dim.Fill () };
+			var lblTvW1 = new Label ("Enter text in TextView on Win1:") { Id = "lblTvW1", Y = Pos.Bottom (lblTf1W1) + 1 };
+			var tvW1 = new TextView () { Id = "tvW1", X = Pos.Left (tf1W1), Width = Dim.Fill (), Height = 2, Text = "First line Win1\nSecond line Win1" };
+			var lblTf2W1 = new Label ("Enter text in TextField on Win1:") { Id = "lblTf2W1", Y = Pos.Bottom (lblTvW1) + 1 };
+			var tf2W1 = new TextField ("Text2 on Win1") { Id = "tf2W1", X = Pos.Left (tf1W1), Width = Dim.Fill () };
 			win1.Add (lblTf1W1, tf1W1, lblTvW1, tvW1, lblTf2W1, tf2W1);
 
-			var win2 = new Window ("Win2") { X = Pos.Right (win1) + 1, Width = Dim.Percent (50f), Height = Dim.Fill () };
-			var lblTf1W2 = new Label ("Enter text in TextField on Win2:");
-			var tf1W2 = new TextField ("Text1 on Win2") { X = Pos.Right (lblTf1W2) + 1, Width = Dim.Fill () };
-			var lblTvW2 = new Label ("Enter text in TextView on Win2:") { Y = Pos.Bottom (lblTf1W2) + 1 };
-			var tvW2 = new TextView () { X = Pos.Left (tf1W2), Width = Dim.Fill (), Height = 2, Text = "First line Win1\nSecond line Win2" };
-			var lblTf2W2 = new Label ("Enter text in TextField on Win2:") { Y = Pos.Bottom (lblTvW2) + 1 };
-			var tf2W2 = new TextField ("Text2 on Win2") { X = Pos.Left (tf1W2), Width = Dim.Fill () };
+			var win2 = new Window ("Win2") { Id = "win2", X = Pos.Right (win1) + 1, Width = Dim.Percent (50f), Height = Dim.Fill () };
+			var lblTf1W2 = new Label ("Enter text in TextField on Win2:") { Id = "lblTf1W2" };
+			var tf1W2 = new TextField ("Text1 on Win2") { Id = "tf1W2", X = Pos.Right (lblTf1W2) + 1, Width = Dim.Fill () };
+			var lblTvW2 = new Label ("Enter text in TextView on Win2:") { Id = "lblTvW2", Y = Pos.Bottom (lblTf1W2) + 1 };
+			var tvW2 = new TextView () { Id = "tvW2", X = Pos.Left (tf1W2), Width = Dim.Fill (), Height = 2, Text = "First line Win1\nSecond line Win2" };
+			var lblTf2W2 = new Label ("Enter text in TextField on Win2:") { Id = "lblTf2W2", Y = Pos.Bottom (lblTvW2) + 1 };
+			var tf2W2 = new TextField ("Text2 on Win2") { Id = "tf2W2", X = Pos.Left (tf1W2), Width = Dim.Fill () };
 			win2.Add (lblTf1W2, tf1W2, lblTvW2, tvW2, lblTf2W2, tf2W2);
 
 			var top = Application.Top;

+ 18 - 1
UnitTests/TopLevels/WindowTests.cs

@@ -138,7 +138,7 @@ namespace Terminal.Gui.TopLevelTests {
 
 			string expectedOld = null;
 			string expected = null;
-			r.TitleChanged += (s,args) => {
+			r.TitleChanged += (s, args) => {
 				Assert.Equal (expectedOld, args.OldTitle);
 				Assert.Equal (r.Title, args.NewTitle);
 			};
@@ -235,7 +235,24 @@ namespace Terminal.Gui.TopLevelTests {
 │└────────────────┘│
 │ ^Q Quit │ ^O Open│
 └──────────────────┘", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void OnCanFocusChanged_Only_Must_ContentView_Forces_SetFocus_After_IsInitialized_Is_True ()
+		{
+			var win1 = new Window () { Id = "win1", Width = 10, Height = 1 };
+			var view1 = new View () { Id = "view1", Width = Dim.Fill (), Height = Dim.Fill (), CanFocus = true };
+			var win2 = new Window () { Id = "win2", Y = 6, Width = 10, Height = 1 };
+			var view2 = new View () { Id = "view2", Width = Dim.Fill (), Height = Dim.Fill (), CanFocus = true };
+			win2.Add (view2);
+			win1.Add (view1, win2);
+
+			Application.Begin (win1);
 
+			Assert.True (win1.HasFocus);
+			Assert.True (view1.HasFocus);
+			Assert.False (win2.HasFocus);
+			Assert.False (view2.HasFocus);
 		}
 	}
 }