瀏覽代碼

Improves the TabView minimum size and added more unit tests.

BDisp 2 年之前
父節點
當前提交
769f5c8091
共有 2 個文件被更改,包括 450 次插入26 次删除
  1. 8 6
      Terminal.Gui/Views/TabView.cs
  2. 442 20
      UnitTests/TabViewTests.cs

+ 8 - 6
Terminal.Gui/Views/TabView.cs

@@ -98,7 +98,7 @@ namespace Terminal.Gui {
 
 
 		/// <summary>
-		/// Initialzies a <see cref="TabView"/> class using <see cref="LayoutStyle.Computed"/> layout.
+		/// Initializes a <see cref="TabView"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		public TabView () : base ()
 		{
@@ -182,7 +182,7 @@ namespace Terminal.Gui {
 
 			if (Style.ShowBorder) {
 
-				// How muc space do we need to leave at the bottom to show the tabs
+				// How much space do we need to leave at the bottom to show the tabs
 				int spaceAtBottom = Math.Max (0, GetTabHeight (false) - 1);
 				int startAtY = Math.Max (0, GetTabHeight (true) - 1);
 
@@ -347,8 +347,10 @@ namespace Terminal.Gui {
 				var maxWidth = Math.Max (0, Math.Min (bounds.Width - 3, MaxTabTextWidth));
 
 				// if tab view is width <= 3 don't render any tabs
-				if (maxWidth == 0)
-					yield break;
+				if (maxWidth == 0) {
+					yield return new TabToRender (i, tab, string.Empty, Equals (SelectedTab, tab), 0);
+					break;
+				}
 
 				if (tabTextWidth > maxWidth) {
 					text = tab.Text.ToString ().Substring (0, (int)maxWidth);
@@ -412,7 +414,7 @@ namespace Terminal.Gui {
 
 			// if the currently selected tab is no longer a member of Tabs
 			if (SelectedTab == null || !Tabs.Contains (SelectedTab)) {
-				// select the tab closest to the one that disapeared
+				// select the tab closest to the one that disappeared
 				var toSelect = Math.Max (idx - 1, 0);
 
 				if (toSelect < Tabs.Count) {
@@ -657,7 +659,7 @@ namespace Terminal.Gui {
 					Driver.AddRune (Driver.LeftArrow);
 				}
 
-				// if there are mmore tabs to the right not visible
+				// if there are more tabs to the right not visible
 				if (ShouldDrawRightScrollIndicator (tabLocations)) {
 					Move (width - 1, y);
 

+ 442 - 20
UnitTests/TabViewTests.cs

@@ -242,7 +242,7 @@ namespace Terminal.Gui.Views {
 		}
 
 		[Fact, AutoInitShutdown]
-		public void TestThinTabView_WithLongNames ()
+		public void ShowTopLine_True_TabsOnBottom_False_TestThinTabView_WithLongNames ()
 		{
 			var tv = GetTabView (out var tab1, out var tab2, false);
 			tv.Width = 10;
@@ -257,23 +257,34 @@ namespace Terminal.Gui.Views {
 
 			tv.Redraw (tv.Bounds);
 
-			GraphViewTests.AssertDriverContentsAre (@"
-┌──┐
-│12│13
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌──┐      
+│12│13    
 │  └─────┐
 │hi      │
 └────────┘", output);
 
+			tv.SelectedTab = tab2;
 
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+   ┌──┐   
+ 12│13│   
+┌──┘  └──┐
+│hi2     │
+└────────┘", output);
+
+			tv.SelectedTab = tab1;
 			// Test first tab name too long
 			tab1.Text = "12345678910";
 			tab2.Text = "13";
 
 			tv.Redraw (tv.Bounds);
 
-			GraphViewTests.AssertDriverContentsAre (@"
-┌───────┐
-│1234567│
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌───────┐ 
+│1234567│ 
 │       └►
 │hi      │
 └────────┘", output);
@@ -282,9 +293,9 @@ namespace Terminal.Gui.Views {
 			tv.SelectedTab = tab2;
 			tv.Redraw (tv.Bounds);
 
-			GraphViewTests.AssertDriverContentsAre (@"   
-┌──┐
-│13│
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌──┐      
+│13│      
 ◄  └─────┐
 │hi2     │
 └────────┘", output);
@@ -296,16 +307,94 @@ namespace Terminal.Gui.Views {
 
 			tv.Redraw (tv.Bounds);
 
-			GraphViewTests.AssertDriverContentsAre (@"     
-┌───────┐
-│abcdefg│
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌───────┐ 
+│abcdefg│ 
 ◄       └┐
 │hi2     │
 └────────┘", output);
 		}
 
 		[Fact, AutoInitShutdown]
-		public void TestTabView_Width4 ()
+		public void ShowTopLine_False_TabsOnBottom_False_TestThinTabView_WithLongNames ()
+		{
+			var tv = GetTabView (out var tab1, out var tab2, false);
+			tv.Width = 10;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { ShowTopLine = false };
+			tv.ApplyStyleChanges ();
+
+			// Ensures that the tab bar subview gets the bounds of the parent TabView
+			tv.LayoutSubviews ();
+
+			// Test two tab names that fit 
+			tab1.Text = "12";
+			tab2.Text = "13";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+│12│13    
+│  └─────┐
+│hi      │
+│        │
+└────────┘", output);
+
+
+			tv.SelectedTab = tab2;
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+ 12│13│   
+┌──┘  └──┐
+│hi2     │
+│        │
+└────────┘", output);
+
+			tv.SelectedTab = tab1;
+
+			// Test first tab name too long
+			tab1.Text = "12345678910";
+			tab2.Text = "13";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+│1234567│ 
+│       └►
+│hi      │
+│        │
+└────────┘", output);
+
+			//switch to tab2
+			tv.SelectedTab = tab2;
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+│13│      
+◄  └─────┐
+│hi2     │
+│        │
+└────────┘", output);
+
+
+			// now make both tabs too long
+			tab1.Text = "12345678910";
+			tab2.Text = "abcdefghijklmnopq";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+│abcdefg│ 
+◄       └┐
+│hi2     │
+│        │
+└────────┘", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_True_TabsOnBottom_False_TestTabView_Width4 ()
 		{
 			var tv = GetTabView (out _, out _, false);
 			tv.Width = 4;
@@ -314,16 +403,36 @@ namespace Terminal.Gui.Views {
 
 			tv.Redraw (tv.Bounds);
 
-			GraphViewTests.AssertDriverContentsAre (@"
-┌─┐
-│T│
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌─┐ 
+│T│ 
 │ └►
 │hi│
 └──┘", output);
 		}
 
 		[Fact, AutoInitShutdown]
-		public void TestTabView_Width3 ()
+		public void ShowTopLine_False_TabsOnBottom_False_TestTabView_Width4 ()
+		{
+			var tv = GetTabView (out _, out _, false);
+			tv.Width = 4;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { ShowTopLine = false };
+			tv.ApplyStyleChanges ();
+			tv.LayoutSubviews ();
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+│T│ 
+│ └►
+│hi│
+│  │
+└──┘", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_True_TabsOnBottom_False_TestTabView_Width3 ()
 		{
 			var tv = GetTabView (out _, out _, false);
 			tv.Width = 3;
@@ -332,12 +441,325 @@ namespace Terminal.Gui.Views {
 
 			tv.Redraw (tv.Bounds);
 
-			GraphViewTests.AssertDriverContentsAre (@"
-┌─┐
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌┐ 
+││ 
+│└►
 │h│
 └─┘", output);
 		}
 
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_False_TabsOnBottom_False_TestTabView_Width3 ()
+		{
+			var tv = GetTabView (out _, out _, false);
+			tv.Width = 3;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { ShowTopLine = false };
+			tv.ApplyStyleChanges ();
+			tv.LayoutSubviews ();
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+││ 
+│└►
+│h│
+│ │
+└─┘", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_True_TabsOnBottom_True_TestThinTabView_WithLongNames ()
+		{
+			var tv = GetTabView (out var tab1, out var tab2, false);
+			tv.Width = 10;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { TabsOnBottom = true };
+			tv.ApplyStyleChanges ();
+
+			// Ensures that the tab bar subview gets the bounds of the parent TabView
+			tv.LayoutSubviews ();
+
+			// Test two tab names that fit 
+			tab1.Text = "12";
+			tab2.Text = "13";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi      │
+│  ┌─────┘
+│12│13    
+└──┘      ", output);
+
+
+			// Test first tab name too long
+			tab1.Text = "12345678910";
+			tab2.Text = "13";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi      │
+│       ┌►
+│1234567│ 
+└───────┘ ", output);
+
+			//switch to tab2
+			tv.SelectedTab = tab2;
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi2     │
+◄  ┌─────┘
+│13│      
+└──┘      ", output);
+
+
+			// now make both tabs too long
+			tab1.Text = "12345678910";
+			tab2.Text = "abcdefghijklmnopq";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi2     │
+◄       ┌┘
+│abcdefg│ 
+└───────┘ ", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_False_TabsOnBottom_True_TestThinTabView_WithLongNames ()
+		{
+			var tv = GetTabView (out var tab1, out var tab2, false);
+			tv.Width = 10;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { ShowTopLine = false, TabsOnBottom = true };
+			tv.ApplyStyleChanges ();
+
+			// Ensures that the tab bar subview gets the bounds of the parent TabView
+			tv.LayoutSubviews ();
+
+			// Test two tab names that fit 
+			tab1.Text = "12";
+			tab2.Text = "13";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi      │
+│        │
+│  ┌─────┘
+│12│13    ", output);
+
+
+			tv.SelectedTab = tab2;
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi2     │
+│        │
+└──┐  ┌──┘
+ 12│13│   ", output);
+
+			tv.SelectedTab = tab1;
+
+			// Test first tab name too long
+			tab1.Text = "12345678910";
+			tab2.Text = "13";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi      │
+│        │
+│       ┌►
+│1234567│ ", output);
+
+			//switch to tab2
+			tv.SelectedTab = tab2;
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi2     │
+│        │
+◄  ┌─────┘
+│13│      ", output);
+
+
+			// now make both tabs too long
+			tab1.Text = "12345678910";
+			tab2.Text = "abcdefghijklmnopq";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────────┐
+│hi2     │
+│        │
+◄       ┌┘
+│abcdefg│ ", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_True_TabsOnBottom_True_TestTabView_Width4 ()
+		{
+			var tv = GetTabView (out _, out _, false);
+			tv.Width = 4;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { TabsOnBottom = true };
+			tv.ApplyStyleChanges ();
+			tv.LayoutSubviews ();
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌──┐
+│hi│
+│ ┌►
+│T│ 
+└─┘ ", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_False_TabsOnBottom_True_TestTabView_Width4 ()
+		{
+			var tv = GetTabView (out _, out _, false);
+			tv.Width = 4;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { ShowTopLine = false, TabsOnBottom = true };
+			tv.ApplyStyleChanges ();
+			tv.LayoutSubviews ();
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌──┐
+│hi│
+│  │
+│ ┌►
+│T│ ", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_True_TabsOnBottom_True_TestTabView_Width3 ()
+		{
+			var tv = GetTabView (out _, out _, false);
+			tv.Width = 3;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { TabsOnBottom = true };
+			tv.ApplyStyleChanges ();
+			tv.LayoutSubviews ();
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌─┐
+│h│
+│┌►
+││ 
+└┘ ", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_False_TabsOnBottom_True_TestTabView_Width3 ()
+		{
+			var tv = GetTabView (out _, out _, false);
+			tv.Width = 3;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { ShowTopLine = false, TabsOnBottom = true };
+			tv.ApplyStyleChanges ();
+			tv.LayoutSubviews ();
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌─┐
+│h│
+│ │
+│┌►
+││ ", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_True_TabsOnBottom_False_With_Unicode ()
+		{
+			var tv = GetTabView (out var tab1, out var tab2, false);
+			tv.Width = 20;
+			tv.Height = 5;
+
+			tv.LayoutSubviews ();
+
+			tab1.Text = "Tab0";
+			tab2.Text = "Les Mise" + Char.ConvertFromUtf32 (Int32.Parse ("0301", NumberStyles.HexNumber)) + "rables";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌────┐              
+│Tab0│              
+│    └─────────────►
+│hi                │
+└──────────────────┘", output);
+
+			tv.SelectedTab = tab2;
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌──────────────┐    
+│Les Misérables│    
+◄              └───┐
+│hi2               │
+└──────────────────┘", output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void ShowTopLine_True_TabsOnBottom_True_With_Unicode ()
+		{
+			var tv = GetTabView (out var tab1, out var tab2, false);
+			tv.Width = 20;
+			tv.Height = 5;
+			tv.Style = new TabView.TabStyle { TabsOnBottom = true };
+			tv.ApplyStyleChanges ();
+
+			tv.LayoutSubviews ();
+
+			tab1.Text = "Tab0";
+			tab2.Text = "Les Mise" + Char.ConvertFromUtf32 (Int32.Parse ("0301", NumberStyles.HexNumber)) + "rables";
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌──────────────────┐
+│hi                │
+│    ┌─────────────►
+│Tab0│              
+└────┘              ", output);
+
+			tv.SelectedTab = tab2;
+
+			tv.Redraw (tv.Bounds);
+
+			GraphViewTests.AssertDriverContentsWithFrameAre (@"
+┌──────────────────┐
+│hi2               │
+◄              ┌───┘
+│Les Misérables│    
+└──────────────┘    ", output);
+		}
+
 		private void InitFakeDriver ()
 		{
 			var driver = new FakeDriver ();