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

Merge branch 'develop' into view-clear-background

Tig 2 жил өмнө
parent
commit
ac6f7756b7

+ 5 - 2
Terminal.Gui/Core/MainLoop.cs

@@ -306,9 +306,12 @@ namespace Terminal.Gui {
 
 			Driver.MainIteration ();
 
+			bool runIdle = false;
 			lock (idleHandlersLock) {
-				if (idleHandlers.Count > 0)
-					RunIdle ();
+				runIdle = idleHandlers.Count > 0;
+			}
+			if (runIdle) {
+				RunIdle ();
 			}
 		}
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 190 - 187
Terminal.Gui/Core/View.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);
 

+ 23 - 38
UICatalog/Scenarios/Notepad.cs

@@ -1,36 +1,35 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.IO;
 using Terminal.Gui;
-using static UICatalog.Scenario;
 
 namespace UICatalog.Scenarios {
 
-	[ScenarioMetadata (Name: "Notepad", Description: "Multi tab text editor uising the TabView control.")]
+	[ScenarioMetadata (Name: "Notepad", Description: "Multi-tab text editor uising the TabView control.")]
 	[ScenarioCategory ("Controls"), ScenarioCategory ("TabView")]
 	public class Notepad : Scenario {
-
 		TabView tabView;
-		Label lblStatus;
 
 		private int numbeOfNewTabs = 1;
 
-		public override void Setup ()
+		// Don't create a Window, just return the top-level view
+		public override void Init (Toplevel top, ColorScheme colorScheme)
 		{
-			Win.Title = this.GetName ();
-			Win.Y = 1; // menu
-			Win.Height = Dim.Fill (1); // status bar
-			Top.LayoutSubviews ();
+			Application.Init ();
+
+			Top = top;
+			if (Top == null) {
+				Top = Application.Top;
+			}
+			Top.ColorScheme = Colors.Base;
+		}
 
+		public override void Setup ()
+		{
 			var menu = new MenuBar (new MenuBarItem [] {
 				new MenuBarItem ("_File", new MenuItem [] {
 					new MenuItem ("_New", "", () => New()),
 					new MenuItem ("_Open", "", () => Open()),
 					new MenuItem ("_Save", "", () => Save()),
-					new MenuItem ("_Save As", "", () => SaveAs()),
+					new MenuItem ("Save _As", "", () => SaveAs()),
 					new MenuItem ("_Close", "", () => Close()),
 					new MenuItem ("_Quit", "", () => Quit()),
 				})
@@ -39,16 +38,17 @@ namespace UICatalog.Scenarios {
 
 			tabView = new TabView () {
 				X = 0,
-				Y = 0,
+				Y = 1,
 				Width = Dim.Fill (),
 				Height = Dim.Fill (1),
 			};
 
-			tabView.Style.ShowBorder = false;
+			tabView.Style.ShowBorder = true;
 			tabView.ApplyStyleChanges ();
 
-			Win.Add (tabView);
+			Top.Add (tabView);
 
+			var lenStatusItem = new StatusItem (Key.CharMask, "Len: ", null);
 			var statusBar = new StatusBar (new StatusItem [] {
 				new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
 
@@ -58,26 +58,16 @@ namespace UICatalog.Scenarios {
 
 				new StatusItem(Key.CtrlMask | Key.S, "~^S~ Save", () => Save()),
 				new StatusItem(Key.CtrlMask | Key.W, "~^W~ Close", () => Close()),
+				lenStatusItem,
 			});
 
-			Win.Add (lblStatus = new Label ("Len:") {
-				Y = Pos.Bottom (tabView),
-				Width = Dim.Fill (),
-				TextAlignment = TextAlignment.Right
-			});
-
-			tabView.SelectedTabChanged += (s, e) => UpdateStatus (e.NewTab);
+			tabView.SelectedTabChanged += (s, e) => lenStatusItem.Title = $"Len:{(e.NewTab?.View?.Text?.Length ?? 0)}";
 
 			Top.Add (statusBar);
 
 			New ();
 		}
 
-		private void UpdateStatus (TabView.Tab newTab)
-		{
-			lblStatus.Text = $"Len:{(newTab?.View?.Text?.Length ?? 0)}";
-		}
-
 		private void New ()
 		{
 			Open ("", null, $"new {numbeOfNewTabs++}");
@@ -109,12 +99,10 @@ namespace UICatalog.Scenarios {
 			// close and dispose the tab
 			tabView.RemoveTab (tab);
 			tab.View.Dispose ();
-
 		}
 
 		private void Open ()
 		{
-
 			var open = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = true };
 
 			Application.Run (open);
@@ -130,7 +118,6 @@ namespace UICatalog.Scenarios {
 					Open (File.ReadAllText (path), new FileInfo (path), Path.GetFileName (path));
 				}
 			}
-
 		}
 
 		/// <summary>
@@ -140,7 +127,6 @@ namespace UICatalog.Scenarios {
 		/// <param name="fileInfo">File that was read or null if a new blank document</param>
 		private void Open (string initialText, FileInfo fileInfo, string tabName)
 		{
-
 			var textView = new TextView () {
 				X = 0,
 				Y = 0,
@@ -188,7 +174,7 @@ namespace UICatalog.Scenarios {
 			}
 
 			tab.Save ();
-
+			tabView.SetNeedsDisplay ();
 		}
 
 		public bool SaveAs ()
@@ -207,14 +193,13 @@ namespace UICatalog.Scenarios {
 			}
 
 			tab.File = new FileInfo (fd.FilePath.ToString ());
+			tab.Text = fd.FileName.ToString ();
 			tab.Save ();
 
 			return true;
 		}
 
 		private class OpenedFile : TabView.Tab {
-
-
 			public FileInfo File { get; set; }
 
 			/// <summary>

+ 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 ();

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно