Finish overload by vertical.

This commit is contained in:
Kolosov Alexandr 2024-03-14 00:09:18 +05:00
parent e15e42dbe8
commit 3c2f945480
9 changed files with 124 additions and 34 deletions

View File

@ -8,7 +8,7 @@ public static class Helper
{
private static readonly Queue<ConsoleColor> Colors = new();
static Helper()
private static void Init()
{
Colors.Enqueue(ConsoleColor.DarkYellow);
Colors.Enqueue(ConsoleColor.DarkMagenta);
@ -22,9 +22,14 @@ public static class Helper
public static void ShowBackground(Position position, Size size)
{
return;
// return;
if (!Colors.Any())
{
Init();
}
var color = Colors.Dequeue();
var top = position.Top;
var height = 0;

View File

@ -10,8 +10,10 @@ public sealed class Sketch : IEnumerable<string>
public IEnumerator<string> GetEnumerator() => ContentRows.GetEnumerator();
public IEnumerable<string> Crop(Size maxSize) =>
ContentRows.Where(row => maxSize.Width >= row.GetWidth()).Take(maxSize.Height).ToArray();
public IEnumerable<string> Crop(Size maxSize) => ContentRows
.Select(row => maxSize.Width < row.GetWidth() ? row[..maxSize.Width] : row)
.Take(maxSize.Height)
.ToArray();
public Size GetSize()
{

View File

@ -3,28 +3,84 @@ using TUI.Engine.Nodes.Attributes.Alignments;
using TUI.Engine.Nodes.Attributes.Orientations;
using TUI.Engine.Nodes.Attributes.Resizing;
using TUI.Engine.Nodes.Components;
using TUI.Engine.Rendering;
namespace TUI.Engine.Nodes.Containers;
public static class ContainerExtension
{
public static Size GetSize(this IContainer container, Size allowableSize)
public static Size GetSize(this INode node, IContainer parentContainer, int nodeNumber, Size allowableSize)
{
var nodeCount = container.GetNodes().Count;
var width = container.ResizingHorizontal switch
{
Resizing.Adaptive => container.Orientation == Orientation.Horizontal
? allowableSize.Width / nodeCount
: allowableSize.Width,
Resizing.Fixed => container.GetFixedSize().Width,
_ => throw new ArgumentOutOfRangeException()
};
var height = container.Orientation == Orientation.Vertical
? allowableSize.Height / nodeCount
: allowableSize.Height;
var width = GetWidth(node, parentContainer, allowableSize.Width);
var height = GetHeight(node, parentContainer, allowableSize.Height, nodeNumber);
return new Size(width, height);
}
private static IEnumerable<INode> GetFixedNodes(this IContainer container, int? takeNodeNumber = null)
{
if (takeNodeNumber is not null)
{
return container
.GetNodes()
.Take(takeNodeNumber.Value + 1)
.Where(n => n.ResizingVertical == Resizing.Fixed);
}
return container
.GetNodes()
.Where(n => n.ResizingVertical == Resizing.Fixed);
}
private static int GetHeight(IResizable node, IContainer container, int maxHeight, int nodeIndex)
{
if (node.ResizingVertical == Resizing.Fixed)
{
return node.GetFixedSize().Height;
}
if (container.Orientation == Orientation.Horizontal)
{
return maxHeight;
}
var fixedNodes = container.GetFixedNodes().ToArray();
var fixedHeight = fixedNodes.Sum(s => s.GetFixedSize().Height);
var allowableHeight = maxHeight - fixedHeight;
var allowableCount = container.GetNodes().Count - fixedNodes.Length;
var nodeHeight = (allowableHeight / allowableCount).Min(1);
var nodeNumber = nodeIndex + 1 - container.GetFixedNodes(nodeIndex).Sum(c => c.GetFixedSize().Height);
if (allowableHeight - nodeNumber * nodeHeight < nodeHeight)
{
return allowableHeight + nodeHeight - nodeNumber * nodeHeight;
}
return nodeHeight;
}
private static int GetWidth(IResizable node, IContainer container, int maxWidth)
{
if (node.ResizingHorizontal == Resizing.Fixed)
{
return node.GetFixedSize().Width;
}
if (container.Orientation == Orientation.Vertical)
{
return maxWidth;
}
var fixedNodes = container
.GetNodes()
.Where(n => n.ResizingHorizontal == Resizing.Fixed).ToArray();
var allowableWidth = maxWidth - fixedNodes.Sum(s => s.GetFixedSize().Width);
var allowableCount = container.GetNodes().Count - fixedNodes.Length;
return allowableWidth / allowableCount;
}
}
public static class ComponentExtensions

View File

@ -21,7 +21,7 @@ public sealed class ComponentCraftsman : CraftsmanBase, IDrawable<IComponent>
var correctedPencil = component.CorrectPosition(pencil, maxSize, sketchSize);
Debug(correctedPencil, pencil, maxSize);
Debug(pencil, maxSize);
foreach (var line in sketch.Crop(maxSize))
{

View File

@ -18,20 +18,22 @@ public sealed class ContainerCraftsman : CraftsmanBase, IDrawable<IContainer>
public Size Draw(IContainer container, Position pencil, Size maxSize)
{
var controlNumber = 0;
var nodeNumber = 0;
var nextNodePosition = pencil;
var nodes = container.GetNodes();
var sketchSize = container.GetSize(maxSize);
Debug(nextNodePosition, nextNodePosition, maxSize);
while (controlNumber < nodes.Count)
Debug(nextNodePosition, maxSize);
while (nodeNumber < nodes.Count)
{
var node = nodes[controlNumber];
nextNodePosition = DrawNode(node, container, nextNodePosition, sketchSize);
controlNumber++;
var node = nodes[nodeNumber];
var nodeSize = node.GetSize(container, nodeNumber, maxSize);
nextNodePosition = DrawNode(node, container, nextNodePosition, nodeSize);
nodeNumber++;
}
return sketchSize;
return maxSize;
}
private Position DrawNode(INode node, IContainer container, Position nodePosition, Size maxSize)

View File

@ -6,9 +6,9 @@ namespace TUI.Engine.Rendering;
public abstract class CraftsmanBase
{
protected void Debug(Position pencilPosition, Position sketchPosition, Size allowableSize)
protected void Debug(Position pencilPosition, Size allowableSize)
{
Debugger.Log(0, "Draw", $"{pencilPosition}{GetType().Name}.\n");
Helper.ShowBackground(sketchPosition, allowableSize);
Helper.ShowBackground(pencilPosition, allowableSize);
}
}

View File

@ -3,4 +3,5 @@ namespace TUI.Engine.Rendering;
public static class IntegerExtension
{
public static int Max(this int value, int maxValue) => value <= maxValue ? value : maxValue;
public static int Min(this int value, int minValue) => value > minValue ? value : minValue;
}

View File

@ -3,6 +3,7 @@ using TUI.Components.Controls;
using TUI.Components.Layouts;
using TUI.Engine.Nodes;
using TUI.Engine.Nodes.Attributes.Alignments;
using TUI.Engine.Nodes.Attributes.Orientations;
using TUI.Engine.Rendering;
using TUI.Engine.Theme;
@ -21,6 +22,8 @@ public class DependenciesPage
var nodeCraftsman = new NodeCraftsman(componentCraftsman, containerCraftsman);
var header = new HeaderContainer();
header.SetFixed(Orientation.Vertical, 6);
var copyright = new Copyright();
copyright.SetPaddingRight(Level.Normal);
copyright.SetAlignment(Horizontal.Right);

View File

@ -112,8 +112,7 @@ public class NodeCraftsmanTests
[Theory]
[InlineData(Orientation.Horizontal, 9, 1)]
[InlineData(Orientation.Vertical, 5, 1)]
public void DrawWithOverload(Orientation orientation, int rootWidth, int rootHeight)
public void DrawWithOverloadHorizontal(Orientation orientation, int rootWidth, int rootHeight)
{
var canvas = Mock.Of<ICanvas>(w => w.Width == rootWidth && w.Height == rootHeight);
var nodes = new Nodes { _component, _component };
@ -124,7 +123,30 @@ public class NodeCraftsmanTests
containerCraftsman.Draw(root, Position.Default, canvas.GetSize());
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Once());
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Once());
Mock.Get(canvas).Verify(w => w.SetPencil(4, 0), Times.Once());
Mock.Get(canvas).Verify(w => w.Paint("Lore"), Times.Exactly(2));
}
[Theory]
[InlineData(4, 4, new[] { 0, 1, 2, 3 })]
public void DrawWithOverloadVertical(int rootWidth, int rootHeight, int[] expectedTopPositions)
{
var canvas = Mock.Of<ICanvas>(w => w.Width == rootWidth && w.Height == rootHeight);
_component.SetContent("Lorem\nLorem\nLorem");
var nodes = new Nodes { _component, _component };
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes && r.Orientation == Orientation.Vertical);
var componentCraftsman = new ComponentCraftsman(canvas);
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
containerCraftsman.Draw(root, Position.Default, canvas.GetSize());
foreach (var expectedTopPosition in expectedTopPositions)
{
Mock.Get(canvas).Verify(w => w.SetPencil(0, expectedTopPosition), Times.Once());
}
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(rootHeight));
}
[Fact]
@ -196,7 +218,6 @@ public class NodeCraftsmanTests
[Theory]
[InlineData(Resizing.Fixed, 6)]
[InlineData(Resizing.Fixed, 3)]
[InlineData(Resizing.Adaptive, 10)]
public void DrawResizingContainer(Resizing resizing, int expectedCursorPosition)
{