mirror of
https://github.com/dnwSilver/tld.git
synced 2024-11-25 16:42:07 +00:00
🧪 Refactoring tests.
This commit is contained in:
parent
3c2f945480
commit
634beddf77
8
TLD.sln
8
TLD.sln
@ -2,7 +2,9 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI", "src\TUI\TUI.csproj", "{F92C03F7-2A65-4D0A-9736-13E749AF6903}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Tests", "tests\WIdgets\TUI.Tests\TUI.Tests.csproj", "{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Engine.Tests", "tests\TUI.Engine.Tests\TUI.Engine.Tests.csproj", "{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Engine", "src\TUI.Engine\TUI.Engine.csproj", "{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -22,5 +24,9 @@ Global
|
||||
{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -1,10 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
@ -1,9 +0,0 @@
|
||||
namespace Dashboard;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello, World!");
|
||||
}
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public record Alignment(Horizontal Horizontal, Vertical Vertical);
|
@ -1,4 +1,4 @@
|
||||
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public enum Horizontal
|
||||
{
|
10
src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs
Normal file
10
src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public interface IWithAlignment
|
||||
{
|
||||
internal Alignment Alignment { get; }
|
||||
|
||||
void SetAlignment(Vertical vertical);
|
||||
|
||||
void SetAlignment(Horizontal horizontal);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
||||
namespace TUI.Engine.Attributes.Alignments;
|
||||
|
||||
public enum Vertical
|
||||
{
|
@ -0,0 +1,9 @@
|
||||
namespace TUI.Engine.Attributes.Orientations;
|
||||
|
||||
public interface IWithOrientation
|
||||
{
|
||||
internal Orientation Orientation { get; }
|
||||
|
||||
public void SetOrientationHorizontal();
|
||||
public void SetOrientationVertical();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace TUI.Engine.Nodes.Attributes.Orientations;
|
||||
namespace TUI.Engine.Attributes.Orientations;
|
||||
|
||||
public enum Orientation
|
||||
{
|
@ -1,8 +1,8 @@
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Nodes.Attributes.Paddings;
|
||||
namespace TUI.Engine.Attributes.Paddings;
|
||||
|
||||
public interface IPaddingable
|
||||
public interface IWithPadding
|
||||
{
|
||||
Padding Padding { get; }
|
||||
|
@ -1,6 +1,6 @@
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Nodes.Attributes.Paddings;
|
||||
namespace TUI.Engine.Attributes.Paddings;
|
||||
|
||||
public record Padding(
|
||||
Level Left = Level.None,
|
16
src/TUI.Engine/Attributes/Resizings/IResizable.cs
Normal file
16
src/TUI.Engine/Attributes/Resizings/IResizable.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
|
||||
namespace TUI.Engine.Attributes.Resizings;
|
||||
|
||||
public interface IResizable
|
||||
{
|
||||
internal Resizing ResizingHorizontal { get; }
|
||||
|
||||
internal Resizing ResizingVertical { get; }
|
||||
|
||||
internal Size GetFixedSize();
|
||||
|
||||
void SetAdaptive(Orientation orientation);
|
||||
|
||||
void SetFixed(Orientation orientation, int value);
|
||||
}
|
7
src/TUI.Engine/Attributes/Resizings/Resizing.cs
Normal file
7
src/TUI.Engine/Attributes/Resizings/Resizing.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace TUI.Engine.Attributes.Resizings;
|
||||
|
||||
public enum Resizing
|
||||
{
|
||||
Adaptive,
|
||||
Fixed
|
||||
}
|
58
src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs
Normal file
58
src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Containers;
|
||||
|
||||
namespace TUI.Engine.Attributes.Resizings;
|
||||
|
||||
internal static class ResizingExtensions
|
||||
{
|
||||
internal static int GetHeight(this 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;
|
||||
}
|
||||
|
||||
internal static int GetWidth(this 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;
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
namespace TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Attributes;
|
||||
|
||||
public readonly record struct Size(int Width, int Height)
|
||||
{
|
50
src/TUI.Engine/Components/ComponentAttribute.cs
Normal file
50
src/TUI.Engine/Components/ComponentAttribute.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Paddings;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public abstract class ComponentAttribute : NodeBase, IComponent
|
||||
{
|
||||
protected abstract Sketch DrawComponent();
|
||||
|
||||
Sketch IComponent.MakeSketch() => DrawComponent();
|
||||
|
||||
#region Alignments
|
||||
|
||||
internal Alignment Alignment { get; private set; } = new(Defaults.HorizontalAlignment, Defaults.VerticalAlignment);
|
||||
|
||||
Alignment IWithAlignment.Alignment => Alignment;
|
||||
|
||||
public void SetAlignment(Vertical vertical)
|
||||
{
|
||||
Alignment = Alignment with { Vertical = vertical };
|
||||
}
|
||||
|
||||
public void SetAlignment(Horizontal horizontal)
|
||||
{
|
||||
Alignment = Alignment with { Horizontal = horizontal };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Paddings
|
||||
|
||||
internal Padding Padding { get; private set; } = new(Defaults.Padding);
|
||||
|
||||
|
||||
Padding IWithPadding.Padding => Padding;
|
||||
|
||||
public void SetPadding(Level level) => Padding = new Padding(level);
|
||||
|
||||
public void SetPaddingTop(Level level) => Padding = Padding with { Top = level };
|
||||
|
||||
public void SetPaddingRight(Level level) => Padding = Padding with { Right = level };
|
||||
|
||||
public void SetPaddingBottom(Level level) => Padding = Padding with { Bottom = level };
|
||||
|
||||
public void SetPaddingLeft(Level level) => Padding = Padding with { Left = level };
|
||||
|
||||
#endregion
|
||||
}
|
40
src/TUI.Engine/Components/ComponentExtensions.cs
Normal file
40
src/TUI.Engine/Components/ComponentExtensions.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
internal static class ComponentExtensions
|
||||
{
|
||||
internal static Position CorrectContentPosition(this IComponent component,
|
||||
Position pencil,
|
||||
Size maxSize,
|
||||
Size sketchSize)
|
||||
{
|
||||
var padding = component.Padding;
|
||||
var alignment = component.Alignment;
|
||||
var alignmentCompensationLeft = GetAlignmentCompensationLeft(alignment.Horizontal, maxSize, sketchSize);
|
||||
var alignmentCompensationTop = GetAlignmentCompensationTop(alignment.Vertical, maxSize, sketchSize);
|
||||
var left = pencil.Left + (int)padding.Left + alignmentCompensationLeft;
|
||||
var top = pencil.Top + (int)padding.Top + alignmentCompensationTop;
|
||||
return new Position(left, top);
|
||||
}
|
||||
|
||||
private static int GetAlignmentCompensationLeft(Horizontal alignment, Size maxSize, Size sketchSize) =>
|
||||
alignment switch
|
||||
{
|
||||
Horizontal.Left => 0,
|
||||
Horizontal.Center => (maxSize.Width - sketchSize.Width) / 2,
|
||||
Horizontal.Right => maxSize.Width - sketchSize.Width,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
private static int GetAlignmentCompensationTop(Vertical alignment, Size maxSize, Size sketchSize) =>
|
||||
alignment switch
|
||||
{
|
||||
Vertical.Top => 0,
|
||||
Vertical.Center => (maxSize.Height - sketchSize.Height) / 2,
|
||||
Vertical.Bottom => maxSize.Height - sketchSize.Height,
|
||||
_ => 0
|
||||
};
|
||||
}
|
10
src/TUI.Engine/Components/IComponent.cs
Normal file
10
src/TUI.Engine/Components/IComponent.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Paddings;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public interface IComponent : INode, IWithAlignment, IWithPadding
|
||||
{
|
||||
internal Sketch MakeSketch();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Attributes;
|
||||
|
||||
namespace TUI.Engine.Nodes.Components;
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public sealed class Sketch : IEnumerable<string>
|
||||
{
|
@ -1,14 +1,14 @@
|
||||
using System.Text;
|
||||
|
||||
namespace TUI.Engine.Nodes.Components;
|
||||
namespace TUI.Engine.Components;
|
||||
|
||||
public abstract class ComponentStaticBase : ComponentBase
|
||||
public abstract class StaticComponentAttribute : ComponentAttribute
|
||||
{
|
||||
private Sketch? _cache;
|
||||
|
||||
protected abstract void RenderWithCache(StringBuilder builder);
|
||||
|
||||
public override Sketch DrawComponent()
|
||||
protected override Sketch DrawComponent()
|
||||
{
|
||||
if (_cache is not null)
|
||||
{
|
||||
@ -16,7 +16,9 @@ public abstract class ComponentStaticBase : ComponentBase
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
RenderWithCache(builder);
|
||||
|
||||
_cache = new Sketch(builder.ToString());
|
||||
|
||||
return _cache;
|
24
src/TUI.Engine/Containers/ContainerBase.cs
Normal file
24
src/TUI.Engine/Containers/ContainerBase.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Containers;
|
||||
|
||||
public abstract class ContainerBase : NodeBase, IContainer
|
||||
{
|
||||
private Orientation _orientation = Defaults.Orientation;
|
||||
|
||||
Orientation IWithOrientation.Orientation => _orientation;
|
||||
|
||||
public void SetOrientationHorizontal()
|
||||
{
|
||||
_orientation = Orientation.Horizontal;
|
||||
}
|
||||
|
||||
public void SetOrientationVertical()
|
||||
{
|
||||
_orientation = Orientation.Vertical;
|
||||
}
|
||||
|
||||
public abstract Nodes.Nodes GetNodes();
|
||||
}
|
22
src/TUI.Engine/Containers/ContainerExtensions.cs
Normal file
22
src/TUI.Engine/Containers/ContainerExtensions.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Containers;
|
||||
|
||||
internal static class ContainerExtensions
|
||||
{
|
||||
internal 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);
|
||||
}
|
||||
}
|
9
src/TUI.Engine/Containers/IContainer.cs
Normal file
9
src/TUI.Engine/Containers/IContainer.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Containers;
|
||||
|
||||
public interface IContainer : INode, IWithOrientation
|
||||
{
|
||||
public Nodes.Nodes GetNodes();
|
||||
}
|
@ -1,11 +1,20 @@
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace TUI;
|
||||
namespace TUI.Engine;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static int Max(this int value, int maxValue)
|
||||
{
|
||||
return value <= maxValue ? value : maxValue;
|
||||
}
|
||||
|
||||
public static int Min(this int value, int minValue)
|
||||
{
|
||||
return value > minValue ? value : minValue;
|
||||
}
|
||||
|
||||
public static bool Have(this IEnumerable<string> array, string findValue)
|
||||
{
|
||||
return array.Any(item => item == findValue);
|
@ -1,6 +1,9 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using Pastel;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
|
||||
[assembly:InternalsVisibleTo("TUI.Engine.Tests", AllInternalsVisible = true)]
|
||||
|
||||
namespace TUI.Engine;
|
||||
|
@ -1,4 +1,4 @@
|
||||
using TUI.Engine.Nodes.Attributes.Resizing;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
@ -1,6 +1,7 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes.Attributes.Resizing;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
||||
@ -9,12 +10,17 @@ public abstract class NodeBase : INode
|
||||
private int _fixedWidth;
|
||||
private int _fixedHeight;
|
||||
|
||||
public Size GetFixedSize() => new(_fixedWidth, _fixedHeight);
|
||||
Size IResizable.GetFixedSize() => new(_fixedWidth, _fixedHeight);
|
||||
|
||||
#region Resizing
|
||||
|
||||
public Resizing ResizingHorizontal { get; private set; } = Resizing.Adaptive;
|
||||
public Resizing ResizingVertical { get; private set; } = Resizing.Adaptive;
|
||||
private Resizing ResizingHorizontal { get; set; } = Defaults.HorizontalResizing;
|
||||
|
||||
Resizing IResizable.ResizingHorizontal => ResizingHorizontal;
|
||||
|
||||
private Resizing ResizingVertical { get; set; } = Defaults.VerticalResizing;
|
||||
|
||||
Resizing IResizable.ResizingVertical => ResizingVertical;
|
||||
|
||||
public void SetAdaptive(Orientation orientation)
|
||||
{
|
15
src/TUI.Engine/Nodes/NodeExtensions.cs
Normal file
15
src/TUI.Engine/Nodes/NodeExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Containers;
|
||||
|
||||
namespace TUI.Engine.Nodes;
|
||||
|
||||
internal static class NodeExtensions
|
||||
{
|
||||
internal static Size GetSize(this INode node, IContainer parentContainer, int nodeNumber, Size allowableSize)
|
||||
{
|
||||
var width = node.GetWidth(parentContainer, allowableSize.Width);
|
||||
var height = node.GetHeight(parentContainer, allowableSize.Height, nodeNumber);
|
||||
return new Size(width, height);
|
||||
}
|
||||
}
|
@ -3,5 +3,6 @@ namespace TUI.Engine.Nodes;
|
||||
public record Position(int Left, int Top)
|
||||
{
|
||||
public static readonly Position Default = new(0, 0);
|
||||
|
||||
public override string ToString() => $"L[{Left}] T[{Top}]";
|
||||
}
|
35
src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs
Normal file
35
src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering.Canvas;
|
||||
|
||||
public class ConsoleCanvas : ICanvas
|
||||
{
|
||||
private readonly DrawCraftsman _drawCraftsman;
|
||||
|
||||
public Size Size { get; } = new(Console.WindowWidth, Console.WindowHeight);
|
||||
|
||||
public ConsoleCanvas()
|
||||
{
|
||||
var componentCraftsman = new ComponentCraftsman(this);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
_drawCraftsman = new DrawCraftsman(componentCraftsman, containerCraftsman);
|
||||
}
|
||||
|
||||
public void SetPencil(Position pencilPosition)
|
||||
{
|
||||
Console.SetCursorPosition(pencilPosition.Left, pencilPosition.Top);
|
||||
}
|
||||
|
||||
public void Paint(string value) => Console.Write(value);
|
||||
|
||||
public void Draw(INode node)
|
||||
{
|
||||
_drawCraftsman.Draw(node, Position.Default, Size);
|
||||
}
|
||||
|
||||
public void Draw(INode node, Position pencil, Size maxSize)
|
||||
{
|
||||
_drawCraftsman.Draw(node, pencil, maxSize);
|
||||
}
|
||||
}
|
17
src/TUI.Engine/Rendering/Canvas/ICanvas.cs
Normal file
17
src/TUI.Engine/Rendering/Canvas/ICanvas.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Rendering.Canvas;
|
||||
|
||||
public interface ICanvas
|
||||
{
|
||||
Size Size { get; }
|
||||
|
||||
void SetPencil(Position pencilPosition);
|
||||
|
||||
void Paint(string value);
|
||||
|
||||
void Draw(INode node);
|
||||
|
||||
void Draw(INode node, Position pencil, Size maxSize);
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Nodes.Containers;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
public sealed class ComponentCraftsman : CraftsmanBase, IDrawable<IComponent>
|
||||
internal sealed class ComponentCraftsman : CraftsmanBase, IDrawable<IComponent>
|
||||
{
|
||||
private readonly ICanvas _canvas;
|
||||
|
||||
@ -19,13 +19,13 @@ public sealed class ComponentCraftsman : CraftsmanBase, IDrawable<IComponent>
|
||||
var sketch = component.MakeSketch();
|
||||
var sketchSize = sketch.GetSize();
|
||||
|
||||
var correctedPencil = component.CorrectPosition(pencil, maxSize, sketchSize);
|
||||
var correctedPencil = component.CorrectContentPosition(pencil, maxSize, sketchSize);
|
||||
|
||||
Debug(pencil, maxSize);
|
||||
|
||||
foreach (var line in sketch.Crop(maxSize))
|
||||
{
|
||||
_canvas.SetPencil(correctedPencil.Left, correctedPencil.Top);
|
||||
_canvas.SetPencil(correctedPencil);
|
||||
_canvas.Paint(line);
|
||||
|
||||
correctedPencil = correctedPencil with { Top = correctedPencil.Top + 1 };
|
@ -1,13 +1,13 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes.Attributes.Resizing;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Nodes.Containers;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
public sealed class ContainerCraftsman : CraftsmanBase, IDrawable<IContainer>
|
||||
internal sealed class ContainerCraftsman : CraftsmanBase, IDrawable<IContainer>
|
||||
{
|
||||
private readonly IDrawable<IComponent> _componentCraftsman;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
@ -1,19 +1,16 @@
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Nodes.Containers;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// 🍀
|
||||
/// </summary>
|
||||
public sealed class NodeCraftsman : IDrawable<INode>
|
||||
internal sealed class DrawCraftsman : IDrawable<INode>
|
||||
{
|
||||
private readonly IDrawable<IComponent> _componentCraftsman;
|
||||
private readonly IDrawable<IContainer> _containerCraftsman;
|
||||
|
||||
public NodeCraftsman(
|
||||
public DrawCraftsman(
|
||||
IDrawable<IComponent> componentCraftsman,
|
||||
IDrawable<IContainer> containerCraftsman)
|
||||
{
|
20
src/TUI.Engine/TUI.Engine.csproj
Normal file
20
src/TUI.Engine/TUI.Engine.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Pastel" Version="4.1.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Other.Assembly.Name</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
20
src/TUI.Engine/Theme/Defaults.cs
Normal file
20
src/TUI.Engine/Theme/Defaults.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Attributes.Resizings;
|
||||
|
||||
namespace TUI.Engine.Theme;
|
||||
|
||||
public static class Defaults
|
||||
{
|
||||
public const Horizontal HorizontalAlignment = Horizontal.Center;
|
||||
|
||||
public const Vertical VerticalAlignment = Vertical.Top;
|
||||
|
||||
public const Level Padding = Level.None;
|
||||
|
||||
public const Resizing HorizontalResizing = Resizing.Adaptive;
|
||||
|
||||
public const Resizing VerticalResizing = Resizing.Adaptive;
|
||||
|
||||
public const Orientation Orientation = TUI.Engine.Attributes.Orientations.Orientation.Horizontal;
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Components;
|
||||
|
||||
namespace TUI.Components.Controls;
|
||||
|
||||
public class CellsComponentBase : ComponentBase, IComponent
|
||||
public class CellsComponentAttribute : ComponentAttribute, IComponent
|
||||
{
|
||||
private const int MaxCellWidth = 10;
|
||||
|
||||
private readonly IEnumerable<string> _cells;
|
||||
|
||||
public CellsComponentBase(IEnumerable<string> cells)
|
||||
public CellsComponentAttribute(IEnumerable<string> cells)
|
||||
{
|
||||
_cells = cells;
|
||||
}
|
||||
@ -29,7 +29,7 @@ public class CellsComponentBase : ComponentBase, IComponent
|
||||
// base.Render(content, position, size);
|
||||
}
|
||||
|
||||
public override Sketch DrawComponent()
|
||||
protected override Sketch DrawComponent()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Components.Controls;
|
||||
|
||||
public class Copyright : ComponentStaticBase
|
||||
public class Copyright : StaticComponentAttribute
|
||||
{
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
|
@ -1,13 +1,13 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Components.Controls;
|
||||
|
||||
public class Dashboard : ComponentBase, IComponent
|
||||
public class Dashboard : ComponentAttribute, IComponent
|
||||
{
|
||||
private readonly string _title;
|
||||
|
||||
@ -61,7 +61,7 @@ public class Dashboard : ComponentBase, IComponent
|
||||
dashboardBuilder.Append(Symbols.Angles.RightBottom);
|
||||
}
|
||||
|
||||
public override Sketch DrawComponent()
|
||||
protected override Sketch DrawComponent()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
using TUI.Components.Controls.Statics;
|
||||
using TUI.Components.Controls.Statics.Hints;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Containers;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Components.Controls;
|
||||
|
@ -1,12 +1,12 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
using TUI.UserInterface;
|
||||
|
||||
namespace TUI.Components.Controls.Statics.Hints;
|
||||
|
||||
public class AppTypeHints : ComponentStaticBase
|
||||
public class AppTypeHints : StaticComponentAttribute
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Components.Controls.Statics.Hints;
|
||||
|
||||
public class HotkeysHint : ComponentStaticBase
|
||||
public class HotkeysHint : StaticComponentAttribute
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
|
@ -1,12 +1,12 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
using TUI.UserInterface;
|
||||
|
||||
namespace TUI.Components.Controls.Statics.Hints;
|
||||
|
||||
public class TagHints : ComponentStaticBase
|
||||
public class TagHints : StaticComponentAttribute
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Components.Controls.Statics.Hints;
|
||||
|
||||
public class VersionHints : ComponentStaticBase
|
||||
public class VersionHints : StaticComponentAttribute
|
||||
{
|
||||
private readonly Dictionary<string, string> _hints = new()
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Components.Controls.Statics;
|
||||
|
||||
public class Logo : ComponentStaticBase
|
||||
public class Logo : StaticComponentAttribute
|
||||
{
|
||||
protected override void RenderWithCache(StringBuilder builder)
|
||||
{
|
||||
|
@ -1,23 +1,18 @@
|
||||
using System.Text;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Rendering;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Theme;
|
||||
using TUI.UserInterface;
|
||||
|
||||
namespace TUI.Components.Controls;
|
||||
|
||||
public class Tag : ComponentBase
|
||||
public class Tag : ComponentAttribute
|
||||
{
|
||||
private IEnumerable<string> _tags;
|
||||
private string _gitType;
|
||||
|
||||
public Tag(NodeCraftsman drawEngine)
|
||||
{
|
||||
}
|
||||
|
||||
public void Bind(IEnumerable<string> tags, string gitType)
|
||||
{
|
||||
_tags = tags;
|
||||
@ -59,7 +54,7 @@ public class Tag : ComponentBase
|
||||
_ => Symbols.Git
|
||||
};
|
||||
|
||||
public override Sketch DrawComponent()
|
||||
protected override Sketch DrawComponent()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -1,14 +1,18 @@
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Components;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes.Attributes.Resizing;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Nodes.Containers;
|
||||
|
||||
namespace TUI.Components.Layouts;
|
||||
|
||||
public class DashboardLayout : ContainerBase, IContainer
|
||||
{
|
||||
public new Orientation Orientation => Orientation.Vertical;
|
||||
public DashboardLayout()
|
||||
{
|
||||
SetOrientationVertical();
|
||||
SetAdaptive(Orientation.Horizontal);
|
||||
SetAdaptive(Orientation.Vertical);
|
||||
}
|
||||
|
||||
private INode _header;
|
||||
private INode _footer;
|
||||
@ -35,8 +39,4 @@ public class DashboardLayout : ContainerBase, IContainer
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Resizing ResizingHorizontal => Resizing.Adaptive;
|
||||
|
||||
public Resizing ResizingVertical => Resizing.Adaptive;
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
using TUI.Components.Controls;
|
||||
using TUI.Domain;
|
||||
using TUI.Engine;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Components;
|
||||
|
||||
namespace TUI.Components.Views;
|
||||
|
||||
public class DependenciesView : ComponentBase, IComponent
|
||||
public class DependenciesView : ComponentAttribute, IComponent
|
||||
{
|
||||
private const string ViewName = "Dependencies";
|
||||
|
||||
@ -153,7 +153,7 @@ public class DependenciesView : ComponentBase, IComponent
|
||||
// {
|
||||
// _table.Previous();
|
||||
// }
|
||||
public override Sketch DrawComponent()
|
||||
protected override Sketch DrawComponent()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using TUI.Engine;
|
||||
|
||||
|
||||
namespace TUI.Domain;
|
||||
|
@ -1,10 +0,0 @@
|
||||
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
||||
|
||||
public interface IAlignable
|
||||
{
|
||||
Alignment Alignment { get; }
|
||||
|
||||
void SetAlignment(Vertical vertical);
|
||||
|
||||
void SetAlignment(Horizontal horizontal);
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
namespace TUI.Engine.Nodes.Attributes.Orientations;
|
||||
|
||||
public interface IWithOrientation
|
||||
{
|
||||
public Orientation Orientation { get; }
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||
|
||||
namespace TUI.Engine.Nodes.Attributes.Resizing;
|
||||
|
||||
public interface IResizable
|
||||
{
|
||||
Resizing ResizingHorizontal { get; }
|
||||
|
||||
Resizing ResizingVertical { get; }
|
||||
|
||||
void SetAdaptive(Orientation orientation);
|
||||
void SetFixed(Orientation orientation, int value);
|
||||
Size GetFixedSize();
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace TUI.Engine.Nodes.Attributes.Resizing;
|
||||
|
||||
public enum Resizing
|
||||
{
|
||||
Adaptive,
|
||||
Fixed
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Attributes.Paddings;
|
||||
using TUI.Engine.Nodes.Attributes.Resizing;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
|
||||
namespace TUI.Engine.Nodes.Components;
|
||||
|
||||
|
||||
public abstract class ComponentBase : NodeBase, IComponent
|
||||
{
|
||||
private Size _sketchSize;
|
||||
|
||||
public abstract Sketch DrawComponent();
|
||||
|
||||
public Sketch MakeSketch()
|
||||
{
|
||||
var sketch = DrawComponent();
|
||||
_sketchSize = sketch.GetSize();
|
||||
return sketch;
|
||||
}
|
||||
|
||||
public Resizing ResizingHorizontal { get; }
|
||||
|
||||
// protected override Size GetAllowableSize() =>
|
||||
// new(
|
||||
// AllowableSize.Width <= _sketchSize.Width ? _sketchSize.Width : AllowableSize.Width,
|
||||
// AllowableSize.Height <= _sketchSize.Height ? _sketchSize.Height : AllowableSize.Height
|
||||
// );
|
||||
|
||||
#region Alignments
|
||||
|
||||
public Alignment Alignment { get; private set; } = new(Horizontal.Center, Vertical.Top);
|
||||
|
||||
public void SetAlignment(Vertical vertical)
|
||||
{
|
||||
Alignment = Alignment with { Vertical = vertical };
|
||||
}
|
||||
|
||||
public void SetAlignment(Horizontal horizontal)
|
||||
{
|
||||
Alignment = Alignment with { Horizontal = horizontal };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Paddings
|
||||
|
||||
public Padding Padding { get; private set; } = new(Level.None);
|
||||
|
||||
public void SetPadding(Level level) => Padding = new Padding(level);
|
||||
|
||||
public void SetPaddingTop(Level level) => Padding = Padding with { Top = level };
|
||||
|
||||
public void SetPaddingRight(Level level) => Padding = Padding with { Right = level };
|
||||
|
||||
public void SetPaddingBottom(Level level) => Padding = Padding with { Bottom = level };
|
||||
|
||||
public void SetPaddingLeft(Level level) => Padding = Padding with { Left = level };
|
||||
|
||||
#endregion
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Attributes.Paddings;
|
||||
|
||||
namespace TUI.Engine.Nodes.Components;
|
||||
|
||||
public interface IComponent : INode, IAlignable, IPaddingable
|
||||
{
|
||||
Sketch MakeSketch();
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||
|
||||
namespace TUI.Engine.Nodes.Containers;
|
||||
|
||||
public abstract class ContainerBase : NodeBase, IContainer
|
||||
{
|
||||
public Orientation Orientation => Orientation.Horizontal;
|
||||
|
||||
public Size GetSketchSize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public abstract Nodes GetNodes();
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
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 INode node, IContainer parentContainer, int nodeNumber, Size allowableSize)
|
||||
{
|
||||
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
|
||||
{
|
||||
public static Position CorrectPosition(this IComponent component, Position pencil, Size maxSize, Size sketchSize)
|
||||
{
|
||||
var padding = component.Padding;
|
||||
var alignment = component.Alignment;
|
||||
var alignmentCompensationLeft = GetAlignmentCompensationLeft(alignment.Horizontal, maxSize, sketchSize);
|
||||
var alignmentCompensationTop = GetAlignmentCompensationTop(alignment.Vertical, maxSize, sketchSize);
|
||||
var left = pencil.Left + (int)padding.Left + alignmentCompensationLeft;
|
||||
var top = pencil.Top + (int)padding.Top + alignmentCompensationTop;
|
||||
return new Position(left, top);
|
||||
}
|
||||
|
||||
private static int GetAlignmentCompensationLeft(Horizontal alignment, Size maxSize, Size sketchSize) =>
|
||||
alignment switch
|
||||
{
|
||||
Horizontal.Left => 0,
|
||||
Horizontal.Center => (maxSize.Width - sketchSize.Width) / 2,
|
||||
Horizontal.Right => maxSize.Width - sketchSize.Width,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
private static int GetAlignmentCompensationTop(Vertical alignment, Size maxSize, Size sketchSize) =>
|
||||
alignment switch
|
||||
{
|
||||
Vertical.Top => 0,
|
||||
Vertical.Center => (maxSize.Height - sketchSize.Height) / 2,
|
||||
Vertical.Bottom => maxSize.Height - sketchSize.Height,
|
||||
_ => 0
|
||||
};
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||
|
||||
namespace TUI.Engine.Nodes.Containers;
|
||||
|
||||
public interface IContainer : INode, IWithOrientation
|
||||
{
|
||||
Size GetSketchSize();
|
||||
Nodes GetNodes();
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
public static class CanvasExtensions
|
||||
{
|
||||
public static Size GetSize(this ICanvas canvas) => new(canvas.Width, canvas.Height);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
public class ConsoleCanvas : ICanvas
|
||||
{
|
||||
public int Width => Console.WindowWidth;
|
||||
public int Height => Console.WindowHeight;
|
||||
|
||||
public void SetPencil(int left, int top) => Console.SetCursorPosition(left, top);
|
||||
public void Paint(string value) => Console.Write(value);
|
||||
public Size GetSize() => new(Width, Height);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace TUI.Engine.Rendering;
|
||||
|
||||
public interface ICanvas
|
||||
{
|
||||
int Width { get; }
|
||||
int Height { get; }
|
||||
void SetPencil(int left, int top);
|
||||
void Paint(string value);
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
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;
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
using System.Diagnostics;
|
||||
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.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace TUI.Pages;
|
||||
@ -15,11 +14,7 @@ public class DependenciesPage
|
||||
{
|
||||
Debugger.Log(0, "Event", "Open page dependencies\n");
|
||||
|
||||
var canvas = new ConsoleCanvas();
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
var nodeCraftsman = new NodeCraftsman(componentCraftsman, containerCraftsman);
|
||||
ICanvas canvas = new ConsoleCanvas();
|
||||
|
||||
var header = new HeaderContainer();
|
||||
header.SetFixed(Orientation.Vertical, 6);
|
||||
@ -33,7 +28,7 @@ public class DependenciesPage
|
||||
// CommandLine = new CommandLine();
|
||||
// DependenciesView = new DependenciesView();
|
||||
|
||||
nodeCraftsman.Draw(layout, Position.Default, canvas.GetSize());
|
||||
canvas.Draw(layout);
|
||||
}
|
||||
|
||||
// private bool _commandLineInDisplay;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Text.Json;
|
||||
using TUI.Domain;
|
||||
using TUI.Engine;
|
||||
using TUI.Settings;
|
||||
|
||||
namespace TUI.Store;
|
||||
|
@ -19,4 +19,8 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TUI.Engine\TUI.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,16 +1,16 @@
|
||||
using FluentAssertions;
|
||||
using TUI.Components.Controls.Statics;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Tests.Stubs;
|
||||
using TUI.Engine.Theme;
|
||||
|
||||
namespace Widgets.Tests;
|
||||
namespace TUI.Engine.Tests.DrawTests;
|
||||
|
||||
public class ComponentBaseTests
|
||||
public class ComponentAttributeTests
|
||||
{
|
||||
[Fact]
|
||||
public void WhenUseChainingSaveAllChange()
|
||||
{
|
||||
var logo = new Logo();
|
||||
var logo = new TestComponent();
|
||||
logo.SetPadding(Level.Normal);
|
||||
logo.SetAlignment(Vertical.Center);
|
||||
logo.SetAlignment(Horizontal.Center);
|
||||
@ -26,7 +26,7 @@ public class ComponentBaseTests
|
||||
[Fact]
|
||||
public void WhenSetPaddingsSaveAllChange()
|
||||
{
|
||||
var component = new Logo();
|
||||
var component = new TestComponent();
|
||||
|
||||
component.SetPadding(Level.Normal);
|
||||
|
||||
@ -42,7 +42,7 @@ public class ComponentBaseTests
|
||||
[InlineData(Vertical.Top)]
|
||||
public void WhenSetVerticalAlignSaveAllChange(Vertical alignment)
|
||||
{
|
||||
var component = new Logo();
|
||||
var component = new TestComponent();
|
||||
|
||||
component.SetAlignment(alignment);
|
||||
|
||||
@ -55,7 +55,7 @@ public class ComponentBaseTests
|
||||
[InlineData(Horizontal.Right)]
|
||||
public void WhenSetHorizontalAlignSaveAllChange(Horizontal alignment)
|
||||
{
|
||||
var component = new Logo();
|
||||
var component = new TestComponent();
|
||||
|
||||
component.SetAlignment(alignment);
|
||||
|
55
tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs
Normal file
55
tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using Moq;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Rendering;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
using TUI.Engine.Tests.Stubs;
|
||||
|
||||
namespace TUI.Engine.Tests.DrawTests;
|
||||
|
||||
public class DrawResizingTests
|
||||
{
|
||||
private readonly ICanvas _canvas;
|
||||
private readonly TestContainer _container;
|
||||
private readonly ContainerCraftsman _craftsman;
|
||||
private readonly TestContainer _root;
|
||||
|
||||
public DrawResizingTests()
|
||||
{
|
||||
var component = Prepare.Component();
|
||||
_canvas = Mock.Of<ICanvas>(w => w.Size == new Size(20, 2));
|
||||
_container = Prepare.Container(component);
|
||||
|
||||
_root = Prepare.Container(_container, component);
|
||||
_root.SetOrientationHorizontal();
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(_canvas);
|
||||
_craftsman = new ContainerCraftsman(componentCraftsman);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawResizingFixedContainer()
|
||||
{
|
||||
_container.SetFixed(Orientation.Horizontal, 6);
|
||||
_container.SetFixed(Orientation.Vertical, 2);
|
||||
|
||||
_craftsman.Draw(_root, Position.Default, _canvas.Size);
|
||||
|
||||
Mock.Get(_canvas).VerifyPositionOnce(Position.Default);
|
||||
Mock.Get(_canvas).VerifyPositionOnce(6, 0);
|
||||
Mock.Get(_canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawResizingAdaptiveContainer()
|
||||
{
|
||||
_container.SetAdaptive(Orientation.Horizontal);
|
||||
|
||||
_craftsman.Draw(_root, Position.Default, _canvas.Size);
|
||||
|
||||
Mock.Get(_canvas).VerifyPositionOnce(Position.Default);
|
||||
Mock.Get(_canvas).VerifyPositionOnce(10, 0);
|
||||
Mock.Get(_canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
}
|
218
tests/TUI.Engine.Tests/DrawTests/DrawTests.cs
Normal file
218
tests/TUI.Engine.Tests/DrawTests/DrawTests.cs
Normal file
@ -0,0 +1,218 @@
|
||||
using Moq;
|
||||
using TUI.Engine.Attributes;
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Attributes.Orientations;
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Rendering;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
using TUI.Engine.Tests.Stubs;
|
||||
|
||||
namespace TUI.Engine.Tests.DrawTests;
|
||||
|
||||
public class DrawCraftsmanTests
|
||||
{
|
||||
public TestComponent _component;
|
||||
|
||||
public DrawCraftsmanTests()
|
||||
{
|
||||
_component = Prepare.Component();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawSimple()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(9, 1));
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(_component, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(Position.Default), Times.Once());
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Once());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Horizontal.Left, "Lorem", 10, 0)]
|
||||
[InlineData(Horizontal.Center, "Lorem", 10, 2)]
|
||||
[InlineData(Horizontal.Center, "Lo", 10, 4)]
|
||||
[InlineData(Horizontal.Center, "Lorem", 9, 2)]
|
||||
[InlineData(Horizontal.Center, "Lorem", 11, 3)]
|
||||
[InlineData(Horizontal.Right, "Lorem", 10, 5)]
|
||||
[InlineData(Horizontal.Right, "Lo", 10, 8)]
|
||||
public void DrawWithHorizontalAlignment(Horizontal alignment, string content, int canvasSize,
|
||||
int expectedPosition)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(canvasSize, canvasSize));
|
||||
var component = Prepare.Component();
|
||||
component.SetContent(content);
|
||||
component.SetAlignment(Vertical.Top);
|
||||
component.SetAlignment(alignment);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(component, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.Paint(content), Times.Once());
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(new Position(expectedPosition, 0)), Times.Once());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Vertical.Top, "v", 5, new[] { 0 })]
|
||||
[InlineData(Vertical.Top, "v\nv", 5, new[] { 0, 1 })]
|
||||
[InlineData(Vertical.Top, "v\nv\nv", 5, new[] { 0, 1, 2 })]
|
||||
[InlineData(Vertical.Center, "v", 1, new[] { 0 })]
|
||||
[InlineData(Vertical.Center, "v", 4, new[] { 1 })]
|
||||
[InlineData(Vertical.Center, "v", 5, new[] { 2 })]
|
||||
[InlineData(Vertical.Center, "v", 6, new[] { 2 })]
|
||||
[InlineData(Vertical.Center, "v\nv", 4, new[] { 1, 2 })]
|
||||
[InlineData(Vertical.Center, "v\nv", 5, new[] { 1, 2 })]
|
||||
[InlineData(Vertical.Center, "v\nv", 6, new[] { 2, 3 })]
|
||||
[InlineData(Vertical.Bottom, "v", 5, new[] { 4 })]
|
||||
[InlineData(Vertical.Bottom, "v\nv", 2, new[] { 0, 1 })]
|
||||
[InlineData(Vertical.Bottom, "v\nv", 3, new[] { 1, 2 })]
|
||||
[InlineData(Vertical.Bottom, "v\nv\nv\nv", 5, new[] { 1, 2, 3, 4 })]
|
||||
public void DrawWithVerticalAlignment(Vertical alignment, string content, int canvasSize, int[] expectedPositions)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(canvasSize, canvasSize));
|
||||
_component.SetContent(content);
|
||||
_component.SetAlignment(Horizontal.Left);
|
||||
_component.SetAlignment(alignment);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(_component, Position.Default, canvas.Size);
|
||||
|
||||
foreach (var expectedPencilPosition in expectedPositions)
|
||||
{
|
||||
Mock.Get(canvas).VerifyPositionOnce(0, expectedPencilPosition);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Horizontal.Left, Vertical.Top, 0, 0)]
|
||||
[InlineData(Horizontal.Left, Vertical.Center, 0, 2)]
|
||||
[InlineData(Horizontal.Left, Vertical.Bottom, 0, 4)]
|
||||
[InlineData(Horizontal.Center, Vertical.Top, 2, 0)]
|
||||
[InlineData(Horizontal.Center, Vertical.Center, 2, 2)]
|
||||
[InlineData(Horizontal.Center, Vertical.Bottom, 2, 4)]
|
||||
[InlineData(Horizontal.Right, Vertical.Top, 4, 0)]
|
||||
[InlineData(Horizontal.Right, Vertical.Center, 4, 2)]
|
||||
[InlineData(Horizontal.Right, Vertical.Bottom, 4, 4)]
|
||||
public void DrawWithAlignment(Horizontal horizontal, Vertical vertical, int expectedLeft,
|
||||
int expectedTop)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(6, 5));
|
||||
_component.SetContent("VV");
|
||||
_component.SetAlignment(horizontal);
|
||||
_component.SetAlignment(vertical);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(_component, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).VerifyPositionOnce(expectedLeft, expectedTop);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Orientation.Horizontal, 9, 1)]
|
||||
public void DrawWithOverloadHorizontal(Orientation orientation, int rootWidth, int rootHeight)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(rootWidth, rootHeight));
|
||||
var root = Prepare.Container(_component, _component);
|
||||
root.SetOrientationHorizontal();
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
containerCraftsman.Draw(root, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).VerifyPositionOnce(Position.Default);
|
||||
Mock.Get(canvas).VerifyPositionOnce(4, 0);
|
||||
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.Size == new Size(rootWidth, rootHeight));
|
||||
_component.SetContent("Lorem\nLorem\nLorem");
|
||||
var root = Prepare.Container(_component, _component);
|
||||
root.SetOrientationVertical();
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
containerCraftsman.Draw(root, Position.Default, canvas.Size);
|
||||
|
||||
foreach (var expectedTopPosition in expectedTopPositions)
|
||||
{
|
||||
Mock.Get(canvas).VerifyPositionOnce(0, expectedTopPosition);
|
||||
}
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lore"), Times.Exactly(rootHeight));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawVerticalWithDoubleComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(10, 2));
|
||||
var root = Prepare.Container(_component, _component);
|
||||
root.SetOrientationVertical();
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
new DrawCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).VerifyPositionOnce(Position.Default);
|
||||
Mock.Get(canvas).VerifyPositionOnce(0, 1);
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawHorizontalWithDoubleComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(10, 1));
|
||||
var nodes = new Nodes.Nodes { _component, _component };
|
||||
var container = Mock.Of<ContainerBase>(g => g.GetNodes() == nodes);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
new DrawCraftsman(componentCraftsman, containerCraftsman).Draw(container, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).VerifyPositionOnce(Position.Default);
|
||||
Mock.Get(canvas).VerifyPositionOnce(5, 0);
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawWithMultipleComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(24, 1));
|
||||
var root = Prepare.Container(_component, _component, _component, _component);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
containerCraftsman.Draw(root, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).VerifyPositionOnce(Position.Default);
|
||||
Mock.Get(canvas).VerifyPositionOnce(6, 0);
|
||||
Mock.Get(canvas).VerifyPositionOnce(12, 0);
|
||||
Mock.Get(canvas).VerifyPositionOnce(18, 0);
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawWithContainerAndComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Size == new Size(10, 2));
|
||||
var container = Prepare.Container(_component);
|
||||
var root = Prepare.Container(container, _component);
|
||||
root.SetAdaptive(Orientation.Vertical);
|
||||
root.SetOrientationVertical();
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
containerCraftsman.Draw(root, Position.Default, canvas.Size);
|
||||
|
||||
Mock.Get(canvas).VerifyPositionOnce(Position.Default);
|
||||
Mock.Get(canvas).VerifyPositionOnce(0, 1);
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
}
|
26
tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs
Normal file
26
tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using FluentAssertions;
|
||||
|
||||
namespace TUI.Engine.Tests.DrawTests;
|
||||
|
||||
public class IntegerTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(5, 10, 5)]
|
||||
[InlineData(5, 5, 5)]
|
||||
[InlineData(5, 3, 3)]
|
||||
public void Max(int value, int max, int expected)
|
||||
{
|
||||
var result = value.Max(max);
|
||||
result.Should().Be(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(5, 10, 10)]
|
||||
[InlineData(5, 5, 5)]
|
||||
[InlineData(5, 3, 5)]
|
||||
public void Min(int value, int min, int expected)
|
||||
{
|
||||
var result = value.Min(min);
|
||||
result.Should().Be(expected);
|
||||
}
|
||||
}
|
18
tests/TUI.Engine.Tests/MockExtensions.cs
Normal file
18
tests/TUI.Engine.Tests/MockExtensions.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Moq;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Rendering.Canvas;
|
||||
|
||||
namespace TUI.Engine.Tests;
|
||||
|
||||
public static class MockExtensions
|
||||
{
|
||||
public static void VerifyPositionOnce<T>(this Mock<T> mock, int left, int top) where T : class, ICanvas
|
||||
{
|
||||
mock.Verify(w => w.SetPencil(new Position(left, top)), Times.Exactly(1));
|
||||
}
|
||||
|
||||
public static void VerifyPositionOnce<T>(this Mock<T> mock, Position position) where T : class, ICanvas
|
||||
{
|
||||
mock.Verify(w => w.SetPencil(position), Times.Exactly(1));
|
||||
}
|
||||
}
|
22
tests/TUI.Engine.Tests/Stubs/Prepare.cs
Normal file
22
tests/TUI.Engine.Tests/Stubs/Prepare.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using TUI.Engine.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Tests.Stubs;
|
||||
|
||||
public static class Prepare
|
||||
{
|
||||
public static TestComponent Component()
|
||||
{
|
||||
var testComponent = new TestComponent();
|
||||
testComponent.SetAlignment(Horizontal.Left);
|
||||
testComponent.SetAlignment(Vertical.Top);
|
||||
return testComponent;
|
||||
}
|
||||
|
||||
public static TestContainer Container(params INode[] nodes)
|
||||
{
|
||||
var testContainer = new TestContainer();
|
||||
testContainer.SetNodes(nodes);
|
||||
return testContainer;
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
using TUI.Engine.Nodes.Components;
|
||||
using TUI.Engine.Components;
|
||||
|
||||
namespace Widgets.Tests;
|
||||
namespace TUI.Engine.Tests.Stubs;
|
||||
|
||||
internal class TestComponent : ComponentBase
|
||||
public class TestComponent : ComponentAttribute
|
||||
{
|
||||
private string _content = "Lorem";
|
||||
|
||||
@ -11,7 +11,7 @@ internal class TestComponent : ComponentBase
|
||||
_content = content;
|
||||
}
|
||||
|
||||
public override Sketch DrawComponent()
|
||||
protected override Sketch DrawComponent()
|
||||
{
|
||||
return new Sketch(_content);
|
||||
}
|
20
tests/TUI.Engine.Tests/Stubs/TestContainer.cs
Normal file
20
tests/TUI.Engine.Tests/Stubs/TestContainer.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using TUI.Engine.Containers;
|
||||
using TUI.Engine.Nodes;
|
||||
|
||||
namespace TUI.Engine.Tests.Stubs;
|
||||
|
||||
public class TestContainer : ContainerBase
|
||||
{
|
||||
private Nodes.Nodes _nodes = new();
|
||||
|
||||
public override Nodes.Nodes GetNodes()
|
||||
{
|
||||
return _nodes;
|
||||
}
|
||||
|
||||
public TestContainer SetNodes(params INode[] nodes)
|
||||
{
|
||||
_nodes.AddRange(nodes);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -7,7 +7,8 @@
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<RootNamespace>Widgets.Tests</RootNamespace>
|
||||
<RootNamespace>TUI.Engine.Tests</RootNamespace>
|
||||
<AssemblyName>TUI.Engine.Tests</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -26,7 +27,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\TUI\TUI.csproj" />
|
||||
<ProjectReference Include="..\..\src\TUI.Engine\TUI.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,240 +0,0 @@
|
||||
using Moq;
|
||||
using TUI.Engine.Nodes;
|
||||
using TUI.Engine.Nodes.Attributes;
|
||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||
using TUI.Engine.Nodes.Attributes.Resizing;
|
||||
using TUI.Engine.Nodes.Containers;
|
||||
using TUI.Engine.Rendering;
|
||||
|
||||
namespace Widgets.Tests;
|
||||
|
||||
public class NodeCraftsmanTests
|
||||
{
|
||||
private readonly TestComponent _component;
|
||||
|
||||
public NodeCraftsmanTests()
|
||||
{
|
||||
_component = new TestComponent();
|
||||
_component.SetAlignment(Horizontal.Left);
|
||||
_component.SetAlignment(Vertical.Top);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawSimple()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == 9 && w.Height == 1);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(_component, 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());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Horizontal.Left, "Lorem", 10, 0)]
|
||||
[InlineData(Horizontal.Center, "Lorem", 10, 2)]
|
||||
[InlineData(Horizontal.Center, "Lo", 10, 4)]
|
||||
[InlineData(Horizontal.Center, "Lorem", 9, 2)]
|
||||
[InlineData(Horizontal.Center, "Lorem", 11, 3)]
|
||||
[InlineData(Horizontal.Right, "Lorem", 10, 5)]
|
||||
[InlineData(Horizontal.Right, "Lo", 10, 8)]
|
||||
public void DrawWithHorizontalAlignment(Horizontal alignment, string content, int canvasSize,
|
||||
int expectedPosition)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == canvasSize && w.Height == canvasSize);
|
||||
_component.SetContent(content);
|
||||
_component.SetAlignment(Vertical.Top);
|
||||
_component.SetAlignment(alignment);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(_component, Position.Default, canvas.GetSize());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.Paint(content), Times.Once());
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(expectedPosition, 0), Times.Once());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Vertical.Top, "v", 5, new[] { 0 })]
|
||||
[InlineData(Vertical.Top, "v\nv", 5, new[] { 0, 1 })]
|
||||
[InlineData(Vertical.Top, "v\nv\nv", 5, new[] { 0, 1, 2 })]
|
||||
[InlineData(Vertical.Center, "v", 1, new[] { 0 })]
|
||||
[InlineData(Vertical.Center, "v", 4, new[] { 1 })]
|
||||
[InlineData(Vertical.Center, "v", 5, new[] { 2 })]
|
||||
[InlineData(Vertical.Center, "v", 6, new[] { 2 })]
|
||||
[InlineData(Vertical.Center, "v\nv", 4, new[] { 1, 2 })]
|
||||
[InlineData(Vertical.Center, "v\nv", 5, new[] { 1, 2 })]
|
||||
[InlineData(Vertical.Center, "v\nv", 6, new[] { 2, 3 })]
|
||||
[InlineData(Vertical.Bottom, "v", 5, new[] { 4 })]
|
||||
[InlineData(Vertical.Bottom, "v\nv", 2, new[] { 0, 1 })]
|
||||
[InlineData(Vertical.Bottom, "v\nv", 3, new[] { 1, 2 })]
|
||||
[InlineData(Vertical.Bottom, "v\nv\nv\nv", 5, new[] { 1, 2, 3, 4 })]
|
||||
public void DrawWithVerticalAlignment(Vertical alignment, string content, int canvasSize, int[] expectedPositions)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == canvasSize && w.Height == canvasSize);
|
||||
_component.SetContent(content);
|
||||
_component.SetAlignment(Horizontal.Left);
|
||||
_component.SetAlignment(alignment);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(_component, Position.Default, canvas.GetSize());
|
||||
|
||||
foreach (var expectedCursorPosition in expectedPositions)
|
||||
{
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, expectedCursorPosition), Times.Once());
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Horizontal.Left, Vertical.Top, 0, 0)]
|
||||
[InlineData(Horizontal.Left, Vertical.Center, 0, 2)]
|
||||
[InlineData(Horizontal.Left, Vertical.Bottom, 0, 4)]
|
||||
[InlineData(Horizontal.Center, Vertical.Top, 2, 0)]
|
||||
[InlineData(Horizontal.Center, Vertical.Center, 2, 2)]
|
||||
[InlineData(Horizontal.Center, Vertical.Bottom, 2, 4)]
|
||||
[InlineData(Horizontal.Right, Vertical.Top, 4, 0)]
|
||||
[InlineData(Horizontal.Right, Vertical.Center, 4, 2)]
|
||||
[InlineData(Horizontal.Right, Vertical.Bottom, 4, 4)]
|
||||
public void DrawWithAlignment(Horizontal horizontal, Vertical vertical, int expectedLeft,
|
||||
int expectedTop)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == 6 && w.Height == 5);
|
||||
_component.SetContent("VV");
|
||||
_component.SetAlignment(horizontal);
|
||||
_component.SetAlignment(vertical);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
componentCraftsman.Draw(_component, Position.Default, canvas.GetSize());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(expectedLeft, expectedTop), Times.Once());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Orientation.Horizontal, 9, 1)]
|
||||
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 };
|
||||
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes && r.Orientation == orientation);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
containerCraftsman.Draw(root, Position.Default, canvas.GetSize());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), 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]
|
||||
public void DrawVerticalWithDoubleComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Height == 2 && w.Width == 10);
|
||||
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);
|
||||
new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Once());
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 1), Times.Once());
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawHorizontalWithDoubleComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == 10 && w.Height == 1);
|
||||
var nodes = new Nodes { _component, _component };
|
||||
var container = Mock.Of<ContainerBase>(g => g.GetNodes() == nodes);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(container, Position.Default, canvas.GetSize());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(5, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawWithMultipleComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == 24 && w.Height == 1);
|
||||
var nodes = new Nodes { _component, _component, _component, _component };
|
||||
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
containerCraftsman.Draw(root, Position.Default, canvas.GetSize());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(6, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(12, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(18, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawWithContainerAndComponent()
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == 10 && w.Height == 2);
|
||||
var container = Mock.Of<IContainer>(c => c.GetNodes() == new Nodes { _component });
|
||||
var nodes = new Nodes { container, _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());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 1), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Resizing.Fixed, 6)]
|
||||
[InlineData(Resizing.Adaptive, 10)]
|
||||
public void DrawResizingContainer(Resizing resizing, int expectedCursorPosition)
|
||||
{
|
||||
var canvas = Mock.Of<ICanvas>(w => w.Width == 20 && w.Height == 2);
|
||||
var container =
|
||||
Mock.Of<IContainer>(c =>
|
||||
c.GetNodes() == new Nodes { _component } && c.ResizingHorizontal == resizing &&
|
||||
c.GetFixedSize() == new Size(6, 2));
|
||||
var nodes = new Nodes { container, _component };
|
||||
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes && r.Orientation == Orientation.Horizontal);
|
||||
|
||||
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||
var containerCraftsman = new ContainerCraftsman(componentCraftsman);
|
||||
containerCraftsman.Draw(root, Position.Default, canvas.GetSize());
|
||||
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.SetPencil(expectedCursorPosition, 0), Times.Exactly(1));
|
||||
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(2));
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
using TUI.Components.Controls.Statics;
|
||||
|
||||
namespace Widgets.Tests.Controls;
|
||||
|
||||
public class LogoTests
|
||||
{
|
||||
[Fact]
|
||||
public void Simple()
|
||||
{
|
||||
var logo = new Logo();
|
||||
|
||||
var render = logo.MakeSketch().ToString();
|
||||
|
||||
Assert.Equal(
|
||||
" \u001b[38;2;132;186;100m\u256d\u2501\u2501\u2501\u2501\u2533\u256e\u001b[0m\u001b[38;2;113;121;126m\u2571\u2571\u001b[0m\u001b[38;2;132;186;100m\u256d\u2501\u2501\u2501\u256e\u001b[0m\n \u001b[38;2;132;186;100m\u2503\u256d\u256e\u256d\u256e\u2503\u2503\u001b[0m\u001b[38;2;113;121;126m\u2571\u2571\u001b[0m\u001b[38;2;132;186;100m\u2570\u256e\u256d\u256e\u2503\u001b[0m\n \u001b[38;2;132;186;100m\u2570\u256f\u2503\u2503\u2570\u252b\u2503\u001b[0m\u001b[38;2;113;121;126m\u2571\u2571\u2571\u001b[0m\u001b[38;2;132;186;100m\u2503\u2503\u2503\u2503\u001b[0m\n \u001b[38;2;113;121;126m\u2571\u2571\u001b[0m\u001b[38;2;132;186;100m\u2503\u2503\u001b[0m\u001b[38;2;113;121;126m\u2571\u001b[0m\u001b[38;2;132;186;100m\u2503\u2503\u001b[0m\u001b[38;2;113;121;126m\u2571\u001b[0m\u001b[38;2;132;186;100m\u256d\u256e\u2503\u2503\u2503\u2503\u001b[0m\n \u001b[38;2;113;121;126m\u2571\u2571\u2571\u001b[0m\u001b[38;2;132;186;100m\u2503\u2503\u001b[0m\u001b[38;2;113;121;126m\u2571\u001b[0m\u001b[38;2;132;186;100m\u2503\u2570\u2501\u256f\u2523\u256f\u2570\u256f\u2503\u001b[0m\n\u001b[38;2;113;121;126m\u2571\u2571\u2571\u2571\u001b[0m\u001b[38;2;132;186;100m\u2570\u256f\u001b[0m\u001b[38;2;113;121;126m\u2571\u001b[0m\u001b[38;2;132;186;100m\u2570\u2501\u2501\u2501\u253b\u2501\u2501\u2501\u256f\u001b[0m\n",
|
||||
render);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
using FluentAssertions;
|
||||
using TUI.Engine.Rendering;
|
||||
|
||||
namespace Widgets.Tests;
|
||||
|
||||
public class IntegerTests
|
||||
{
|
||||
[Fact]
|
||||
public void IntegerGreaterMax()
|
||||
{
|
||||
var result = 5.Max(10);
|
||||
|
||||
result.Should().Be(5);
|
||||
}
|
||||
[Fact]
|
||||
public void IntegerLessMax()
|
||||
{
|
||||
var result = 5.Max(3);
|
||||
|
||||
result.Should().Be(3);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user