diff --git a/Terminal.Gui/Views/TileView.cs b/Terminal.Gui/Views/TileView.cs
index 67ee2f704..bd6c27a44 100644
--- a/Terminal.Gui/Views/TileView.cs
+++ b/Terminal.Gui/Views/TileView.cs
@@ -253,13 +253,6 @@ namespace Terminal.Gui {
contentArea.Y + 1,
Math.Max (0, contentArea.Width - 2),
Math.Max (0, contentArea.Height - 2));
- } else if (HasAnyTitles () && IsRootTileView ()) {
- // TODO: Bound with Max/Min
- contentArea = new Rect (
- contentArea.X,
- contentArea.Y + 1,
- contentArea.Width,
- Math.Max (0, contentArea.Height - 1));
}
Setup (contentArea);
@@ -297,15 +290,14 @@ namespace Terminal.Gui {
///
public override void Redraw (Rect bounds)
{
- var childTitles = new List ();
-
Driver.SetAttribute (ColorScheme.Normal);
Clear ();
base.Redraw (bounds);
var lc = new LineCanvas ();
- var allLines = GetAllChildTileViewLineViewRecursively (this);
+ var allLines = GetAllLineViewsRecursively (this);
+ var allTitlesToRender = GetAllTitlesToRenderRecursively(this);
if (IsRootTileView ()) {
if (HasBorder ()) {
@@ -333,10 +325,6 @@ namespace Terminal.Gui {
origin.Y -= 1;
}
length += 2;
-
- childTitles.Add (
- new ChildSplitterLine (line));
-
}
lc.AddLine (origin, length, line.Orientation, IntegratedBorder);
@@ -351,26 +339,26 @@ namespace Terminal.Gui {
line.DrawSplitterSymbol ();
}
- foreach (var child in childTitles) {
- child.DrawTitles ();
- }
-
// Draw Titles over Border
+ foreach(var titleToRender in allTitlesToRender)
+ {
+ var renderAt = titleToRender.GetLocalCoordinateForTitle(this);
- for (int i = 0; i < tiles.Count; i++) {
+ if(renderAt.Y < 0)
+ {
+ // If we have no border then root level tiles
+ // have nowhere to render their titles.
+ continue;
+ }
- var tile = tiles [i];
+ // TODO: Render with focus color if focused
- if (tile.View.Visible && tile.Title.Length > 0) {
+ var title = titleToRender.Tile.Title;
- var screen = i == 0 ?
- ViewToScreen (new Rect (0, 0, bounds.Width, 1)) :
- ViewToScreen (splitterLines [i - 1].Frame);
-
-
- Driver.SetAttribute (tile.View.HasFocus ? ColorScheme.HotNormal : ColorScheme.Normal);
- Driver.DrawWindowTitle (new Rect (screen.X, screen.Y, tile.View.Frame.Width, 0), tile.Title, 0, 0, 0, 0);
+ for(int i=0;i GetAllChildTileViewLineViewRecursively (View v)
+ private List GetAllLineViewsRecursively (View v)
{
var lines = new List ();
@@ -440,13 +428,44 @@ namespace Terminal.Gui {
lines.Add (s);
}
} else {
- lines.AddRange (GetAllChildTileViewLineViewRecursively (sub));
+ lines.AddRange (GetAllLineViewsRecursively (sub));
}
}
return lines;
}
+ private List GetAllTitlesToRenderRecursively (TileView v, int depth = 0)
+ {
+ var titles = new List ();
+
+ foreach (var sub in v.Tiles) {
+
+ // Don't render titles for invisible stuff!
+ if(!sub.View.Visible)
+ {
+ continue;
+ }
+
+ if(sub.View is TileView subTileView)
+ {
+ // Panels with sub split tiles in them can never
+ // have their Titles rendered. Instead we dive in
+ // and pull up their children as titles
+ titles.AddRange (GetAllTitlesToRenderRecursively (subTileView,depth+1));
+ }
+ else
+ {
+ if(sub.Title.Length > 0)
+ {
+ titles.Add(new TileTitleToRender(sub,depth));
+ }
+ }
+ }
+
+ return titles;
+ }
+
///
///
/// if is nested within a parent
@@ -618,6 +637,30 @@ namespace Terminal.Gui {
}
}
+ private class TileTitleToRender
+ {
+ public Tile Tile {get;}
+
+ public int Depth {get;}
+
+ public TileTitleToRender(Tile tile, int depth)
+ {
+ Tile = tile;
+ Depth = depth;
+ }
+
+ ///
+ /// Translates the title location from its local
+ /// coordinate space .
+ ///
+ public Point GetLocalCoordinateForTitle(TileView intoCoordinateSpace)
+ {
+ Tile.View.ViewToScreen(0,0, out var screenCol, out var screenRow);
+ screenRow--;
+ return intoCoordinateSpace.ScreenToView(screenCol,screenRow);
+ }
+ }
+
private class TileViewLineView : LineView {
public TileView Parent { get; private set; }
public int Idx { get; }
diff --git a/UnitTests/TileViewTests.cs b/UnitTests/TileViewTests.cs
index 4d2e1908c..092f97231 100644
--- a/UnitTests/TileViewTests.cs
+++ b/UnitTests/TileViewTests.cs
@@ -713,6 +713,28 @@ namespace UnitTests {
Assert.Equal(3,subSplit.Tiles.ElementAt(1).View.Frame.Height);
Assert.IsType(subSplit.Tiles.ElementAt(1).View.Subviews.Single());
}
+
+ [Fact,AutoInitShutdown]
+ public void TestNestedContainer3RightAnd1Down_WithTitledBorder_RendersNicely()
+ {
+ var tileView = GetNestedContainer3Right1Down (true,true);
+
+ tileView.Redraw (tileView.Bounds);
+
+ string looksLike =
+@"
+┌T1───┬T2────┬T3───┐
+│11111│222222│33333│
+│11111│222222│33333│
+│11111│222222│33333│
+│11111│222222│33333│
+│11111│222222├T4───┤
+│11111│222222│44444│
+│11111│222222│44444│
+│11111│222222│44444│
+└─────┴──────┴─────┘";
+ TestHelpers.AssertDriverContentsAre (looksLike, output);
+ }
[Fact, AutoInitShutdown]
public void TestNestedContainer3RightAnd1Down_WithBorder_RemovingTiles ()
@@ -827,7 +849,7 @@ namespace UnitTests {
///
///
///
- private TileView GetNestedContainer3Right1Down(bool withBorder)
+ private TileView GetNestedContainer3Right1Down(bool withBorder, bool withTitles = false)
{
var container =
new TileView (3)
@@ -846,6 +868,11 @@ namespace UnitTests {
{
i++;
+ if(withTitles)
+ {
+ tile.Title = "T"+i;
+ }
+
tile.View.Add(new TextView{
Width = Dim.Fill(),
Height = Dim.Fill(),