Merge branch 'develop' into view-clear-background

This commit is contained in:
Tig
2022-10-20 07:30:09 -07:00
committed by GitHub
5 changed files with 692 additions and 275 deletions

View File

@@ -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 ();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -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;
// Don't create a Window, just return the top-level view
public override void Init (Toplevel top, ColorScheme colorScheme)
{
Application.Init ();
Top = top;
if (Top == null) {
Top = Application.Top;
}
Top.ColorScheme = Colors.Base;
}
public override void Setup ()
{
Win.Title = this.GetName ();
Win.Y = 1; // menu
Win.Height = Dim.Fill (1); // status bar
Top.LayoutSubviews ();
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>

View File

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