mirror of
https://github.com/dnwSilver/tld.git
synced 2024-11-25 16:42:07 +00:00
♻️ Refactor naming component.
This commit is contained in:
parent
dfa9d9e665
commit
2eb8fee7d4
@ -18,7 +18,7 @@ public class CellsComponentBase : ComponentBase, IComponent
|
|||||||
_cells = cells;
|
_cells = cells;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(Horizontal horizontal, Size size)
|
public void Render(AlignmentHorizontal alignmentHorizontal, Size size)
|
||||||
{
|
{
|
||||||
var content = new StringBuilder();
|
var content = new StringBuilder();
|
||||||
foreach (var cell in _cells)
|
foreach (var cell in _cells)
|
||||||
@ -30,7 +30,7 @@ public class CellsComponentBase : ComponentBase, IComponent
|
|||||||
// base.Render(content, position, size);
|
// base.Render(content, position, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Content Render()
|
public override Sketch Draw()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public class Dashboard : ComponentBase, IComponent
|
|||||||
_title = title;
|
_title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(Horizontal horizontal, Size size)
|
public void Render(AlignmentHorizontal alignmentHorizontal, Size size)
|
||||||
{
|
{
|
||||||
var dashboardBuilder = new StringBuilder();
|
var dashboardBuilder = new StringBuilder();
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ public class Dashboard : ComponentBase, IComponent
|
|||||||
dashboardBuilder.Append(Symbols.Angles.RightBottom);
|
dashboardBuilder.Append(Symbols.Angles.RightBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Content Render()
|
public override Sketch Draw()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,48 @@
|
|||||||
using TUI.Components.Controls.Statics;
|
using TUI.Components.Controls.Statics;
|
||||||
using TUI.Components.Controls.Statics.Hints;
|
using TUI.Components.Controls.Statics.Hints;
|
||||||
using TUI.Engine.Nodes;
|
using TUI.Engine.Nodes;
|
||||||
|
using TUI.Engine.Nodes.Attributes;
|
||||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Resizings;
|
||||||
using TUI.Engine.Nodes.Containers;
|
using TUI.Engine.Nodes.Containers;
|
||||||
using TUI.Engine.Theme;
|
using TUI.Engine.Theme;
|
||||||
|
|
||||||
namespace TUI.Components.Controls;
|
namespace TUI.Components.Controls;
|
||||||
|
|
||||||
public class HeaderContainer : IContainer
|
public abstract class ContainerBase : IContainer
|
||||||
{
|
{
|
||||||
public Orientation Orientation => Orientation.Horizontal;
|
public Orientation Orientation => Orientation.Horizontal;
|
||||||
|
|
||||||
public Nodes Nodes
|
public Resizing ResizingHorizontal => Resizing.Adaptive;
|
||||||
|
|
||||||
|
public Resizing ResizingVertical => Resizing.Hug;
|
||||||
|
|
||||||
|
public Size Fixed { get; }
|
||||||
|
|
||||||
|
public abstract Nodes GetNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HeaderContainer : ContainerBase, IContainer
|
||||||
|
{
|
||||||
|
public override Nodes GetNodes()
|
||||||
{
|
{
|
||||||
get
|
var versionHints = new VersionHints()
|
||||||
{
|
.Set(Indentation.Default);
|
||||||
var versionHints = new VersionHints()
|
|
||||||
.Set(Indentation.Default);
|
|
||||||
|
|
||||||
var tagsHints = new TagHints()
|
var tagsHints = new TagHints()
|
||||||
.Set(Indentation.Default);
|
.Set(Indentation.Default);
|
||||||
|
|
||||||
var appTypeHints = new AppTypeHints()
|
var appTypeHints = new AppTypeHints()
|
||||||
.Set(Indentation.Default);
|
.Set(Indentation.Default);
|
||||||
|
|
||||||
var hotkeysHints = new HotkeysHint()
|
var hotkeysHints = new HotkeysHint()
|
||||||
.Set(Indentation.Default);
|
.Set(Indentation.Default);
|
||||||
|
|
||||||
var logo = new Logo()
|
var logo = new Logo()
|
||||||
.Set(Horizontal.Right)
|
.Set(AlignmentHorizontal.Right)
|
||||||
.Set(left: Indentation.Default, bottom: Indentation.Default, right: Indentation.Default);
|
.Set(left: Indentation.Default, bottom: Indentation.Default, right: Indentation.Default);
|
||||||
|
|
||||||
return new Nodes { versionHints, tagsHints, appTypeHints, hotkeysHints, logo };
|
return new Nodes { versionHints, tagsHints, appTypeHints, hotkeysHints, logo };
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ public class Tag : ComponentBase
|
|||||||
private IEnumerable<string> _tags;
|
private IEnumerable<string> _tags;
|
||||||
private string _gitType;
|
private string _gitType;
|
||||||
|
|
||||||
public Tag(IRenderingEngine renderingEngine)
|
public Tag(NodeCraftsman drawEngine)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ public class Tag : ComponentBase
|
|||||||
_gitType = gitType;
|
_gitType = gitType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(Horizontal horizontal, Size size)
|
public void Render(AlignmentHorizontal alignmentHorizontal, Size size)
|
||||||
{
|
{
|
||||||
var tagBuilder = new StringBuilder();
|
var tagBuilder = new StringBuilder();
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ public class Tag : ComponentBase
|
|||||||
_ => Symbols.Git
|
_ => Symbols.Git
|
||||||
};
|
};
|
||||||
|
|
||||||
public override Content Render()
|
public override Sketch Draw()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
|
using TUI.Components.Controls;
|
||||||
using TUI.Engine.Nodes;
|
using TUI.Engine.Nodes;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Resizings;
|
||||||
using TUI.Engine.Nodes.Components;
|
using TUI.Engine.Nodes.Components;
|
||||||
using TUI.Engine.Nodes.Containers;
|
using TUI.Engine.Nodes.Containers;
|
||||||
|
|
||||||
namespace TUI.Components.Layouts;
|
namespace TUI.Components.Layouts;
|
||||||
|
|
||||||
public class DashboardLayout : IContainer
|
public class DashboardLayout : ContainerBase, IContainer
|
||||||
{
|
{
|
||||||
public Orientation Orientation { get; } = Orientation.Vertical;
|
public new Orientation Orientation => Orientation.Vertical;
|
||||||
|
|
||||||
private INode _header;
|
private INode _header;
|
||||||
private INode _footer;
|
private INode _footer;
|
||||||
|
|
||||||
public Nodes Nodes =>
|
public override Nodes GetNodes() =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
_header, _footer
|
_header, _footer
|
||||||
@ -33,4 +36,8 @@ public class DashboardLayout : IContainer
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Resizing ResizingHorizontal => Resizing.Adaptive;
|
||||||
|
|
||||||
|
public Resizing ResizingVertical => Resizing.Adaptive;
|
||||||
}
|
}
|
@ -18,7 +18,7 @@ public class DependenciesView : ComponentBase, IComponent
|
|||||||
_developmentStack = developmentStack;
|
_developmentStack = developmentStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(Horizontal horizontal, Size size)
|
public void Render(AlignmentHorizontal alignmentHorizontal, Size size)
|
||||||
{
|
{
|
||||||
var dashboardTitle = _developmentStack.Icon + Symbols.Space + ViewName;
|
var dashboardTitle = _developmentStack.Icon + Symbols.Space + ViewName;
|
||||||
var dashboard = new Dashboard(dashboardTitle);
|
var dashboard = new Dashboard(dashboardTitle);
|
||||||
@ -153,7 +153,7 @@ public class DependenciesView : ComponentBase, IComponent
|
|||||||
// {
|
// {
|
||||||
// _table.Previous();
|
// _table.Previous();
|
||||||
// }
|
// }
|
||||||
public override Content Render()
|
public override Sketch Draw()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,11 @@ public static class Helper
|
|||||||
Colors.Enqueue(ConsoleColor.Yellow);
|
Colors.Enqueue(ConsoleColor.Yellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowBackground(NodePosition position, Size size)
|
public static void ShowBackground(Position position, Size size)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
var color = Colors.Dequeue();
|
var color = Colors.Dequeue();
|
||||||
|
|
||||||
var top = position.Top;
|
var top = position.Top;
|
||||||
var height = 0;
|
var height = 0;
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
||||||
|
|
||||||
public record Alignment(Horizontal Horizontal, Vertical Vertical);
|
public record Alignment(AlignmentHorizontal AlignmentHorizontal, Vertical Vertical);
|
@ -1,6 +1,6 @@
|
|||||||
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
namespace TUI.Engine.Nodes.Attributes.Alignments;
|
||||||
|
|
||||||
public enum Horizontal
|
public enum AlignmentHorizontal
|
||||||
{
|
{
|
||||||
Left = 0,
|
Left = 0,
|
||||||
Center = 1,
|
Center = 1,
|
@ -4,5 +4,5 @@ public interface IWithAlignment<out TNode> where TNode : INode
|
|||||||
{
|
{
|
||||||
public Alignment Alignment { get; }
|
public Alignment Alignment { get; }
|
||||||
|
|
||||||
public TNode Set(Horizontal horizontal = Horizontal.Left, Vertical vertical = Vertical.Top);
|
public TNode Set(AlignmentHorizontal alignmentHorizontal = AlignmentHorizontal.Left, Vertical vertical = Vertical.Top);
|
||||||
}
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
|
||||||
|
public interface IWithOrientation
|
||||||
|
{
|
||||||
|
public Orientation Orientation { get; }
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
namespace TUI.Engine.Nodes.Containers;
|
namespace TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
|
||||||
public enum Orientation
|
public enum Orientation
|
||||||
{
|
{
|
10
src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs
Normal file
10
src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace TUI.Engine.Nodes.Attributes.Resizings;
|
||||||
|
|
||||||
|
public interface IWithResizing
|
||||||
|
{
|
||||||
|
Resizing ResizingHorizontal { get; }
|
||||||
|
|
||||||
|
Resizing ResizingVertical { get; }
|
||||||
|
|
||||||
|
Size Fixed { get; }
|
||||||
|
}
|
8
src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs
Normal file
8
src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace TUI.Engine.Nodes.Attributes.Resizings;
|
||||||
|
|
||||||
|
public enum Resizing
|
||||||
|
{
|
||||||
|
Adaptive,
|
||||||
|
Fixed,
|
||||||
|
Hug,
|
||||||
|
}
|
@ -6,15 +6,15 @@ namespace TUI.Engine.Nodes.Components;
|
|||||||
|
|
||||||
public abstract class ComponentBase : List<IComponent>, IComponent
|
public abstract class ComponentBase : List<IComponent>, IComponent
|
||||||
{
|
{
|
||||||
public abstract Content Render();
|
public abstract Sketch Draw();
|
||||||
|
|
||||||
#region Alignments
|
#region Alignments
|
||||||
|
|
||||||
public Alignment Alignment { get; private set; } = new(Horizontal.Center, Vertical.Top);
|
public Alignment Alignment { get; private set; } = new(AlignmentHorizontal.Center, Vertical.Top);
|
||||||
|
|
||||||
public IComponent Set(Horizontal horizontal = Horizontal.Left, Vertical vertical = Vertical.Top)
|
public IComponent Set(AlignmentHorizontal alignmentHorizontal = AlignmentHorizontal.Left, Vertical vertical = Vertical.Top)
|
||||||
{
|
{
|
||||||
Alignment = new Alignment(horizontal, vertical);
|
Alignment = new Alignment(alignmentHorizontal, vertical);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@ namespace TUI.Engine.Nodes.Components;
|
|||||||
|
|
||||||
public abstract class ComponentStaticBase : ComponentBase
|
public abstract class ComponentStaticBase : ComponentBase
|
||||||
{
|
{
|
||||||
private Content? _cache;
|
private Sketch? _cache;
|
||||||
|
|
||||||
protected abstract void RenderWithCache(StringBuilder builder);
|
protected abstract void RenderWithCache(StringBuilder builder);
|
||||||
|
|
||||||
public override Content Render()
|
public override Sketch Draw()
|
||||||
{
|
{
|
||||||
if (_cache is not null)
|
if (_cache is not null)
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ public abstract class ComponentStaticBase : ComponentBase
|
|||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
RenderWithCache(builder);
|
RenderWithCache(builder);
|
||||||
_cache = new Content(builder.ToString());
|
_cache = new Sketch(builder.ToString());
|
||||||
|
|
||||||
return _cache;
|
return _cache;
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,5 @@ public interface IComponent : INode,
|
|||||||
IWithAlignment<IComponent>,
|
IWithAlignment<IComponent>,
|
||||||
IWithPadding<IComponent>
|
IWithPadding<IComponent>
|
||||||
{
|
{
|
||||||
Content Render();
|
Sketch Draw();
|
||||||
}
|
}
|
@ -2,11 +2,11 @@ using TUI.Engine.Nodes.Attributes;
|
|||||||
|
|
||||||
namespace TUI.Engine.Nodes.Components;
|
namespace TUI.Engine.Nodes.Components;
|
||||||
|
|
||||||
public sealed class Content : IEnumerable<string>
|
public sealed class Sketch : IEnumerable<string>
|
||||||
{
|
{
|
||||||
private IEnumerable<string> ContentRows { get; }
|
private IEnumerable<string> ContentRows { get; }
|
||||||
|
|
||||||
public Content(string content) => ContentRows = content.Split(Symbols.LineBreak);
|
public Sketch(string content) => ContentRows = content.Split(Symbols.LineBreak);
|
||||||
|
|
||||||
public IEnumerator<string> GetEnumerator() => ContentRows.GetEnumerator();
|
public IEnumerator<string> GetEnumerator() => ContentRows.GetEnumerator();
|
||||||
|
|
55
src/TUI/Engine/Nodes/Containers/ContainerExtension.cs
Normal file
55
src/TUI/Engine/Nodes/Containers/ContainerExtension.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using TUI.Engine.Nodes.Attributes;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
using TUI.Engine.Nodes.Components;
|
||||||
|
|
||||||
|
namespace TUI.Engine.Nodes.Containers;
|
||||||
|
|
||||||
|
public static class ContainerExtension
|
||||||
|
{
|
||||||
|
public static Size GetSize(this IContainer container, Size allowableSize)
|
||||||
|
{
|
||||||
|
var nodeCount = container.GetNodes().Count;
|
||||||
|
var width = container.Orientation == Orientation.Horizontal
|
||||||
|
? allowableSize.Width / nodeCount
|
||||||
|
: allowableSize.Width;
|
||||||
|
var height = container.Orientation == Orientation.Vertical
|
||||||
|
? allowableSize.Height / nodeCount
|
||||||
|
: allowableSize.Height;
|
||||||
|
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ComponentExtensions
|
||||||
|
{
|
||||||
|
public static Position GetPosition(this IComponent component, Position sketchPosition, Size allowableSize,
|
||||||
|
Size actualSize)
|
||||||
|
{
|
||||||
|
var left = sketchPosition.Left + (int)(component.Padding?.Left ?? 0) +
|
||||||
|
CompensationLeft(component.Alignment.AlignmentHorizontal, allowableSize, actualSize);
|
||||||
|
var top = sketchPosition.Top + (int)(component.Padding?.Top ?? 0) +
|
||||||
|
CompensationTop(component.Alignment.Vertical, allowableSize, actualSize);
|
||||||
|
return new Position(left, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int CompensationLeft(AlignmentHorizontal componentAlignmentHorizontal, Size defaultSize,
|
||||||
|
Size realSize) =>
|
||||||
|
componentAlignmentHorizontal switch
|
||||||
|
{
|
||||||
|
AlignmentHorizontal.Left => 0,
|
||||||
|
AlignmentHorizontal.Center => (defaultSize.Width - realSize.Width) / 2,
|
||||||
|
AlignmentHorizontal.Right => defaultSize.Width - realSize.Width,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
|
||||||
|
private static int CompensationTop(Vertical componentVertical, Size defaultSize, Size realSize)
|
||||||
|
=>
|
||||||
|
componentVertical switch
|
||||||
|
{
|
||||||
|
Vertical.Top => 0,
|
||||||
|
Vertical.Center => (defaultSize.Height - realSize.Height) / 2,
|
||||||
|
Vertical.Bottom => defaultSize.Height - realSize.Height,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
|
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Resizings;
|
||||||
|
|
||||||
namespace TUI.Engine.Nodes.Containers;
|
namespace TUI.Engine.Nodes.Containers;
|
||||||
|
|
||||||
public interface IContainer : INode
|
public interface IContainer : INode,
|
||||||
|
IWithOrientation,
|
||||||
|
IWithResizing
|
||||||
{
|
{
|
||||||
public Orientation Orientation { get; }
|
public Nodes GetNodes();
|
||||||
|
|
||||||
public Nodes Nodes { get; }
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
namespace TUI.Engine.Nodes;
|
namespace TUI.Engine.Nodes;
|
||||||
|
|
||||||
public record NodePosition(int Left, int Top)
|
public record Position(int Left, int Top)
|
||||||
{
|
{
|
||||||
public override string ToString() => $"L[{Left}] T[{Top}]";
|
public override string ToString() => $"L[{Left}] T[{Top}]";
|
||||||
}
|
}
|
41
src/TUI/Engine/Rendering/ComponentCraftsman.cs
Normal file
41
src/TUI/Engine/Rendering/ComponentCraftsman.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using TUI.Engine.Nodes;
|
||||||
|
using TUI.Engine.Nodes.Attributes;
|
||||||
|
using TUI.Engine.Nodes.Components;
|
||||||
|
using TUI.Engine.Nodes.Containers;
|
||||||
|
|
||||||
|
namespace TUI.Engine.Rendering;
|
||||||
|
|
||||||
|
public sealed class ComponentCraftsman : IDrawable<IComponent>
|
||||||
|
{
|
||||||
|
private readonly ICanvas _canvas;
|
||||||
|
|
||||||
|
public ComponentCraftsman(ICanvas canvas)
|
||||||
|
{
|
||||||
|
_canvas = canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size Draw(IComponent component, Position sketchPosition, Size allowableSize)
|
||||||
|
{
|
||||||
|
var sketch = component.Draw();
|
||||||
|
var actualSize = sketch.GetSize();
|
||||||
|
|
||||||
|
var maxWidth = _canvas.Width - sketchPosition.Left;
|
||||||
|
var maxHeight = _canvas.Height - sketchPosition.Top;
|
||||||
|
|
||||||
|
var pencilPosition = component.GetPosition(sketchPosition, allowableSize, actualSize);
|
||||||
|
|
||||||
|
Debugger.Log(0, "Render", $"{pencilPosition}{component.GetType().Name}.\n");
|
||||||
|
Helper.ShowBackground(sketchPosition, allowableSize);
|
||||||
|
|
||||||
|
foreach (var row in sketch.Rows(maxWidth, maxHeight))
|
||||||
|
{
|
||||||
|
_canvas.SetPencil(pencilPosition.Left, pencilPosition.Top);
|
||||||
|
_canvas.Paint(row);
|
||||||
|
|
||||||
|
pencilPosition = pencilPosition with { Top = pencilPosition.Top + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualSize;
|
||||||
|
}
|
||||||
|
}
|
9
src/TUI/Engine/Rendering/ConsoleCanvas.cs
Normal file
9
src/TUI/Engine/Rendering/ConsoleCanvas.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
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);
|
||||||
|
}
|
76
src/TUI/Engine/Rendering/ConsoleDrawNode.cs
Normal file
76
src/TUI/Engine/Rendering/ConsoleDrawNode.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using TUI.Engine.Nodes;
|
||||||
|
using TUI.Engine.Nodes.Attributes;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
using TUI.Engine.Nodes.Components;
|
||||||
|
using TUI.Engine.Nodes.Containers;
|
||||||
|
|
||||||
|
namespace TUI.Engine.Rendering;
|
||||||
|
|
||||||
|
public sealed class ContainerCraftsman : IDrawable<IContainer>
|
||||||
|
{
|
||||||
|
private readonly ICanvas _canvas;
|
||||||
|
private readonly IDrawable<IComponent> _componentCraftsman;
|
||||||
|
|
||||||
|
public ContainerCraftsman(
|
||||||
|
ICanvas canvas,
|
||||||
|
IDrawable<IComponent> componentCraftsman)
|
||||||
|
{
|
||||||
|
_canvas = canvas;
|
||||||
|
_componentCraftsman = componentCraftsman;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Size Draw(IContainer container, Position sketchPosition, Size allowableSize)
|
||||||
|
{
|
||||||
|
var sketchSize = container.GetSize(allowableSize);
|
||||||
|
|
||||||
|
Debugger.Log(0, "Render", $"{sketchPosition} {allowableSize} {container.GetType().Name}\n");
|
||||||
|
Helper.ShowBackground(sketchPosition, allowableSize);
|
||||||
|
|
||||||
|
var controlNumber = 0;
|
||||||
|
|
||||||
|
while (controlNumber < container.GetNodes().Count)
|
||||||
|
{
|
||||||
|
var node = container.GetNodes()[controlNumber];
|
||||||
|
|
||||||
|
sketchPosition = RenderNode(node, container.Orientation, sketchSize, sketchPosition);
|
||||||
|
controlNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sketchSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Position RenderNode(INode node, Orientation orientation, Size defaultSize, Position position)
|
||||||
|
{
|
||||||
|
switch (node)
|
||||||
|
{
|
||||||
|
case IContainer container when orientation == Orientation.Horizontal:
|
||||||
|
Draw(container, position, defaultSize);
|
||||||
|
return position with
|
||||||
|
{
|
||||||
|
Left = position.Left + defaultSize.Width
|
||||||
|
};
|
||||||
|
case IContainer container when orientation == Orientation.Vertical:
|
||||||
|
Draw(container, position, defaultSize);
|
||||||
|
return position with
|
||||||
|
{
|
||||||
|
Top = position.Top + defaultSize.Height
|
||||||
|
};
|
||||||
|
case IComponent component when orientation == Orientation.Horizontal:
|
||||||
|
var componentWidth = _componentCraftsman.Draw(component, position, defaultSize).Width;
|
||||||
|
return position with
|
||||||
|
{
|
||||||
|
Left = position.Left + (defaultSize.Width <= componentWidth ? componentWidth : defaultSize.Width)
|
||||||
|
};
|
||||||
|
case IComponent component when orientation == Orientation.Vertical:
|
||||||
|
var componentHeight = _componentCraftsman.Draw(component, position, defaultSize).Height;
|
||||||
|
return position with
|
||||||
|
{
|
||||||
|
Top = position.Top + (defaultSize.Height <= componentHeight ? componentHeight : defaultSize.Height)
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
throw new InvalidCastException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,129 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using TUI.Engine.Nodes;
|
|
||||||
using TUI.Engine.Nodes.Attributes;
|
|
||||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
|
||||||
using TUI.Engine.Nodes.Components;
|
|
||||||
using TUI.Engine.Nodes.Containers;
|
|
||||||
|
|
||||||
namespace TUI.Engine.Rendering;
|
|
||||||
|
|
||||||
public class ConsoleRenderingEngine : IRenderingEngine
|
|
||||||
{
|
|
||||||
private readonly IWindow _window;
|
|
||||||
|
|
||||||
public ConsoleRenderingEngine(IWindow window)
|
|
||||||
{
|
|
||||||
_window = window;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Render(IContainer container, Size? defaultSize = null)
|
|
||||||
{
|
|
||||||
defaultSize ??= new Size(_window.Width, _window.Height);
|
|
||||||
|
|
||||||
var defaultChildrenSize = new Size(
|
|
||||||
Width: container.Orientation == Orientation.Horizontal
|
|
||||||
? defaultSize.Width / container.Nodes.Count
|
|
||||||
: defaultSize.Width,
|
|
||||||
Height: container.Orientation == Orientation.Vertical
|
|
||||||
? defaultSize.Height / container.Nodes.Count
|
|
||||||
: defaultSize.Height
|
|
||||||
);
|
|
||||||
|
|
||||||
var controlNumber = 0;
|
|
||||||
var nodePosition = new NodePosition(Left: 0, Top: 0);
|
|
||||||
|
|
||||||
Debugger.Log(0, "Render", $"{nodePosition} {defaultSize} {container.GetType().Name}\n");
|
|
||||||
Helper.ShowBackground(nodePosition, defaultSize);
|
|
||||||
|
|
||||||
while (controlNumber < container.Nodes.Count)
|
|
||||||
{
|
|
||||||
var node = container.Nodes[controlNumber];
|
|
||||||
|
|
||||||
nodePosition = RenderNode(node, container.Orientation, defaultChildrenSize, nodePosition);
|
|
||||||
controlNumber++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private NodePosition RenderNode(INode node, Orientation orientation, Size defaultSize, NodePosition position)
|
|
||||||
{
|
|
||||||
switch (node)
|
|
||||||
{
|
|
||||||
case IContainer container when orientation == Orientation.Horizontal:
|
|
||||||
Render(container, defaultSize);
|
|
||||||
return position with
|
|
||||||
{
|
|
||||||
Left = position.Left + defaultSize.Width
|
|
||||||
};
|
|
||||||
case IContainer container when orientation == Orientation.Vertical:
|
|
||||||
Render(container, defaultSize);
|
|
||||||
return position with
|
|
||||||
{
|
|
||||||
Top = position.Top + defaultSize.Height
|
|
||||||
};
|
|
||||||
case IComponent component when orientation == Orientation.Horizontal:
|
|
||||||
var componentWidth = RenderComponent(component, position, defaultSize).Width;
|
|
||||||
return position with
|
|
||||||
{
|
|
||||||
Left = position.Left + (defaultSize.Width <= componentWidth ? componentWidth : defaultSize.Width)
|
|
||||||
};
|
|
||||||
case IComponent component when orientation == Orientation.Vertical:
|
|
||||||
var componentHeight = RenderComponent(component, position, defaultSize).Height;
|
|
||||||
return position with
|
|
||||||
{
|
|
||||||
Top = position.Top + (defaultSize.Height <= componentHeight ? componentHeight : defaultSize.Height)
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
throw new InvalidCastException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Size RenderComponent(IComponent component, NodePosition defaultPosition, Size defaultSize)
|
|
||||||
{
|
|
||||||
var content = component.Render();
|
|
||||||
|
|
||||||
var maxWidth = _window.Width - defaultPosition.Left;
|
|
||||||
var maxHeight = _window.Height - defaultPosition.Top;
|
|
||||||
|
|
||||||
var leftPosition = defaultPosition.Left + (int)(component.Padding?.Left ?? 0) +
|
|
||||||
CompensationLeft(component.Alignment.Horizontal, defaultSize, content.GetSize());
|
|
||||||
var topPosition = defaultPosition.Top + (int)(component.Padding?.Top ?? 0) +
|
|
||||||
CompensationTop(component.Alignment.Vertical, defaultSize, content.GetSize());
|
|
||||||
|
|
||||||
|
|
||||||
Debugger.Log(0, "Render", $"{component.GetType().Name} with position [{leftPosition},{topPosition}]\n");
|
|
||||||
|
|
||||||
var rows = content.Rows(maxWidth, maxHeight);
|
|
||||||
|
|
||||||
Helper.ShowBackground(defaultPosition, defaultSize);
|
|
||||||
|
|
||||||
foreach (var row in rows)
|
|
||||||
{
|
|
||||||
_window.SetCursorPosition(leftPosition, topPosition);
|
|
||||||
_window.Write(row);
|
|
||||||
|
|
||||||
topPosition++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return content.GetSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int CompensationLeft(Horizontal componentHorizontal, Size defaultSize, Size realSize) =>
|
|
||||||
componentHorizontal switch
|
|
||||||
{
|
|
||||||
Horizontal.Left => 0,
|
|
||||||
Horizontal.Center => (defaultSize.Width - realSize.Width) / 2,
|
|
||||||
Horizontal.Right => defaultSize.Width - realSize.Width,
|
|
||||||
_ => 0
|
|
||||||
};
|
|
||||||
|
|
||||||
private static int CompensationTop(Vertical componentVertical, Size defaultSize, Size realSize)
|
|
||||||
=>
|
|
||||||
componentVertical switch
|
|
||||||
{
|
|
||||||
Vertical.Top => 0,
|
|
||||||
Vertical.Center => (defaultSize.Height - realSize.Height) / 2,
|
|
||||||
Vertical.Bottom => defaultSize.Height - realSize.Height,
|
|
||||||
_ => 0
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace TUI.Engine.Rendering;
|
|
||||||
|
|
||||||
public class ConsoleWindow : IWindow
|
|
||||||
{
|
|
||||||
public int Width => Console.WindowWidth;
|
|
||||||
public int Height => Console.WindowHeight;
|
|
||||||
public void SetCursorPosition(int left, int top) => Console.SetCursorPosition(left, top);
|
|
||||||
public void Write(string value) => Console.Write(value);
|
|
||||||
}
|
|
9
src/TUI/Engine/Rendering/ICanvas.cs
Normal file
9
src/TUI/Engine/Rendering/ICanvas.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace TUI.Engine.Rendering;
|
||||||
|
|
||||||
|
public interface ICanvas
|
||||||
|
{
|
||||||
|
int Width { get; }
|
||||||
|
int Height { get; }
|
||||||
|
void SetPencil(int left, int top);
|
||||||
|
void Paint(string value);
|
||||||
|
}
|
9
src/TUI/Engine/Rendering/IDrawable.cs
Normal file
9
src/TUI/Engine/Rendering/IDrawable.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using TUI.Engine.Nodes;
|
||||||
|
using TUI.Engine.Nodes.Attributes;
|
||||||
|
|
||||||
|
namespace TUI.Engine.Rendering;
|
||||||
|
|
||||||
|
public interface IDrawable<in TItem> where TItem : INode
|
||||||
|
{
|
||||||
|
Size Draw(TItem item, Position sketchPosition, Size allowableSize);
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
using TUI.Engine.Nodes.Attributes;
|
|
||||||
using TUI.Engine.Nodes.Containers;
|
|
||||||
|
|
||||||
namespace TUI.Engine.Rendering;
|
|
||||||
|
|
||||||
public interface IRenderingEngine
|
|
||||||
{
|
|
||||||
void Render(IContainer container, Size? defaultSize);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace TUI.Engine.Rendering;
|
|
||||||
|
|
||||||
public interface IWindow
|
|
||||||
{
|
|
||||||
int Width { get; }
|
|
||||||
int Height { get; }
|
|
||||||
void SetCursorPosition(int left, int top);
|
|
||||||
void Write(string value);
|
|
||||||
}
|
|
39
src/TUI/Engine/Rendering/NodeCraftsman.cs
Normal file
39
src/TUI/Engine/Rendering/NodeCraftsman.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using TUI.Engine.Nodes;
|
||||||
|
using TUI.Engine.Nodes.Attributes;
|
||||||
|
using TUI.Engine.Nodes.Components;
|
||||||
|
using TUI.Engine.Nodes.Containers;
|
||||||
|
|
||||||
|
namespace TUI.Engine.Rendering;
|
||||||
|
|
||||||
|
public sealed class NodeCraftsman
|
||||||
|
{
|
||||||
|
private readonly ICanvas _canvas;
|
||||||
|
private readonly IDrawable<IComponent> _componentCraftsman;
|
||||||
|
private readonly IDrawable<IContainer> _containerCraftsman;
|
||||||
|
|
||||||
|
public NodeCraftsman(
|
||||||
|
ICanvas canvas,
|
||||||
|
IDrawable<IComponent> componentCraftsman,
|
||||||
|
IDrawable<IContainer> containerCraftsman)
|
||||||
|
{
|
||||||
|
_canvas = canvas;
|
||||||
|
_componentCraftsman = componentCraftsman;
|
||||||
|
_containerCraftsman = containerCraftsman;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(INode node)
|
||||||
|
{
|
||||||
|
var windowSize = new Size(_canvas.Width, _canvas.Height);
|
||||||
|
var defaultPosition = new Position(0, 0);
|
||||||
|
|
||||||
|
switch (node)
|
||||||
|
{
|
||||||
|
case IContainer container:
|
||||||
|
_containerCraftsman.Draw(container, defaultPosition, windowSize);
|
||||||
|
break;
|
||||||
|
case IComponent component:
|
||||||
|
_componentCraftsman.Draw(component, defaultPosition, windowSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,17 +13,21 @@ public class DependenciesPage
|
|||||||
{
|
{
|
||||||
Debugger.Log(0, "Event", "Open page dependencies\n");
|
Debugger.Log(0, "Event", "Open page dependencies\n");
|
||||||
|
|
||||||
var window = new ConsoleWindow();
|
var canvas = new ConsoleCanvas();
|
||||||
var renderEngine = new ConsoleRenderingEngine(window);
|
|
||||||
|
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||||
|
var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman);
|
||||||
|
var nodeCraftsman = new NodeCraftsman(canvas, componentCraftsman, containerCraftsman);
|
||||||
|
|
||||||
var header = new HeaderContainer();
|
var header = new HeaderContainer();
|
||||||
var copyright = new Copyright()
|
var copyright = new Copyright()
|
||||||
.Set(right: Level.Normal)
|
.Set(right: Level.Normal)
|
||||||
.Set(Horizontal.Right, Vertical.Bottom);
|
.Set(AlignmentHorizontal.Right, Vertical.Bottom);
|
||||||
|
|
||||||
var layout = new DashboardLayout().AddHeader(header).AddFooter(copyright);
|
var layout = new DashboardLayout().AddHeader(header).AddFooter(copyright);
|
||||||
// CommandLine = new CommandLine();
|
// CommandLine = new CommandLine();
|
||||||
// DependenciesView = new DependenciesView();
|
// DependenciesView = new DependenciesView();
|
||||||
renderEngine.Render(layout);
|
nodeCraftsman.Draw(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private bool _commandLineInDisplay;
|
// private bool _commandLineInDisplay;
|
||||||
|
@ -12,13 +12,13 @@ public class ComponentBaseTests
|
|||||||
{
|
{
|
||||||
var component = new Logo()
|
var component = new Logo()
|
||||||
.Set(Level.Normal)
|
.Set(Level.Normal)
|
||||||
.Set(vertical: Vertical.Center, horizontal: Horizontal.Center);
|
.Set(vertical: Vertical.Center, alignmentHorizontal: AlignmentHorizontal.Center);
|
||||||
|
|
||||||
component.Padding.Top.Should().Be(Level.Normal);
|
component.Padding.Top.Should().Be(Level.Normal);
|
||||||
component.Padding.Left.Should().Be(Level.Normal);
|
component.Padding.Left.Should().Be(Level.Normal);
|
||||||
component.Padding.Bottom.Should().Be(Level.Normal);
|
component.Padding.Bottom.Should().Be(Level.Normal);
|
||||||
component.Padding.Right.Should().Be(Level.Normal);
|
component.Padding.Right.Should().Be(Level.Normal);
|
||||||
component.Alignment.Horizontal.Should().Be(Horizontal.Center);
|
component.Alignment.AlignmentHorizontal.Should().Be(AlignmentHorizontal.Center);
|
||||||
component.Alignment.Vertical.Should().Be(Vertical.Center);
|
component.Alignment.Vertical.Should().Be(Vertical.Center);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,15 +49,16 @@ public class ComponentBaseTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(Horizontal.Left)]
|
[InlineData(AlignmentHorizontal.Left)]
|
||||||
[InlineData(Horizontal.Center)]
|
[InlineData(AlignmentHorizontal.Center)]
|
||||||
[InlineData(Horizontal.Right)]
|
[InlineData(AlignmentHorizontal.Right)]
|
||||||
public void WhenSetHorizontalAlignSaveAllChange(Horizontal alignment)
|
public void WhenSetHorizontalAlignSaveAllChange(AlignmentHorizontal alignment)
|
||||||
{
|
{
|
||||||
var component = new Logo();
|
var component = new Logo();
|
||||||
|
|
||||||
component.Set(horizontal: alignment);
|
component.Set(alignmentHorizontal: alignment);
|
||||||
|
|
||||||
component.Alignment.Horizontal.Should().Be(alignment);
|
component.Alignment.AlignmentHorizontal.Should().Be(alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
226
tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs
Normal file
226
tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
using Moq;
|
||||||
|
using TUI.Engine.Nodes;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Alignments;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Orientations;
|
||||||
|
using TUI.Engine.Nodes.Attributes.Resizings;
|
||||||
|
using TUI.Engine.Nodes.Components;
|
||||||
|
using TUI.Engine.Nodes.Containers;
|
||||||
|
using TUI.Engine.Rendering;
|
||||||
|
|
||||||
|
namespace Widgets.Tests;
|
||||||
|
|
||||||
|
public class NodeCraftsmanTests
|
||||||
|
{
|
||||||
|
private readonly IComponent _component;
|
||||||
|
|
||||||
|
public NodeCraftsmanTests()
|
||||||
|
{
|
||||||
|
_component = Mock.Of<IComponent>(c =>
|
||||||
|
c.Draw() == new Sketch("Lorem") &&
|
||||||
|
c.Alignment == new Alignment(AlignmentHorizontal.Left, Vertical.Top));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DrawSimple()
|
||||||
|
{
|
||||||
|
var canvas = Mock.Of<ICanvas>(w => w.Width == 9 && w.Height == 1);
|
||||||
|
var nodes = new Nodes { _component };
|
||||||
|
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes);
|
||||||
|
|
||||||
|
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||||
|
var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Once());
|
||||||
|
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(AlignmentHorizontal.Left, "Lorem", 10, 0)]
|
||||||
|
[InlineData(AlignmentHorizontal.Center, "Lorem", 10, 2)]
|
||||||
|
[InlineData(AlignmentHorizontal.Center, "Lo", 10, 4)]
|
||||||
|
[InlineData(AlignmentHorizontal.Center, "Lorem", 9, 2)]
|
||||||
|
[InlineData(AlignmentHorizontal.Center, "Lorem", 11, 3)]
|
||||||
|
[InlineData(AlignmentHorizontal.Right, "Lorem", 10, 5)]
|
||||||
|
[InlineData(AlignmentHorizontal.Right, "Lo", 10, 8)]
|
||||||
|
public void DrawWithHorizontalAlignment(AlignmentHorizontal alignment, string content, int canvasSize,
|
||||||
|
int expectedPosition)
|
||||||
|
{
|
||||||
|
var canvas = Mock.Of<ICanvas>(w => w.Width == canvasSize && w.Height == canvasSize);
|
||||||
|
var component = Mock.Of<IComponent>(c => c.Draw() == new Sketch(content) &&
|
||||||
|
c.Alignment == new Alignment(alignment, Vertical.Top));
|
||||||
|
var nodes = new Nodes { component };
|
||||||
|
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes);
|
||||||
|
|
||||||
|
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||||
|
var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
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);
|
||||||
|
var component = Mock.Of<IComponent>(c => c.Draw() == new Sketch(content) &&
|
||||||
|
c.Alignment == new Alignment(AlignmentHorizontal.Left, alignment));
|
||||||
|
var nodes = new Nodes { component };
|
||||||
|
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes);
|
||||||
|
|
||||||
|
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||||
|
var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
foreach (var expectedCursorPosition in expectedPositions)
|
||||||
|
{
|
||||||
|
Mock.Get(canvas).Verify(w => w.SetPencil(0, expectedCursorPosition), Times.Once());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(AlignmentHorizontal.Left, Vertical.Top, 0, 0)]
|
||||||
|
[InlineData(AlignmentHorizontal.Left, Vertical.Center, 0, 2)]
|
||||||
|
[InlineData(AlignmentHorizontal.Left, Vertical.Bottom, 0, 4)]
|
||||||
|
[InlineData(AlignmentHorizontal.Center, Vertical.Top, 2, 0)]
|
||||||
|
[InlineData(AlignmentHorizontal.Center, Vertical.Center, 2, 2)]
|
||||||
|
[InlineData(AlignmentHorizontal.Center, Vertical.Bottom, 2, 4)]
|
||||||
|
[InlineData(AlignmentHorizontal.Right, Vertical.Top, 4, 0)]
|
||||||
|
[InlineData(AlignmentHorizontal.Right, Vertical.Center, 4, 2)]
|
||||||
|
[InlineData(AlignmentHorizontal.Right, Vertical.Bottom, 4, 4)]
|
||||||
|
public void DrawWithAlignment(AlignmentHorizontal alignmentHorizontal, Vertical vertical, int expectedLeft,
|
||||||
|
int expectedTop)
|
||||||
|
{
|
||||||
|
var canvas = Mock.Of<ICanvas>(w => w.Width == 6 && w.Height == 5);
|
||||||
|
var component = Mock.Of<IComponent>(c => c.Draw() == new Sketch("VV") &&
|
||||||
|
c.Alignment == new Alignment(alignmentHorizontal, vertical));
|
||||||
|
var nodes = new Nodes { component };
|
||||||
|
var root = Mock.Of<IContainer>(r => r.GetNodes() == nodes);
|
||||||
|
|
||||||
|
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||||
|
var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
Mock.Get(canvas).Verify(w => w.SetPencil(expectedLeft, expectedTop), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(Orientation.Horizontal, 9, 1)]
|
||||||
|
[InlineData(Orientation.Vertical, 5, 1)]
|
||||||
|
public void DrawWithOverload(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(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Once());
|
||||||
|
Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[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(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
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<IContainer>(g => g.GetNodes() == nodes);
|
||||||
|
|
||||||
|
var componentCraftsman = new ComponentCraftsman(canvas);
|
||||||
|
var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(container);
|
||||||
|
|
||||||
|
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(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
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(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
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.Hug, 5)]
|
||||||
|
[InlineData(Resizing.Fixed, 3)]
|
||||||
|
[InlineData(Resizing.Adaptive, 10)]
|
||||||
|
public void DrawWithResizeContainer(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);
|
||||||
|
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(canvas, componentCraftsman);
|
||||||
|
new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root);
|
||||||
|
|
||||||
|
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,184 +0,0 @@
|
|||||||
using Moq;
|
|
||||||
using TUI.Engine.Nodes;
|
|
||||||
using TUI.Engine.Nodes.Attributes.Alignments;
|
|
||||||
using TUI.Engine.Nodes.Components;
|
|
||||||
using TUI.Engine.Nodes.Containers;
|
|
||||||
using TUI.Engine.Rendering;
|
|
||||||
|
|
||||||
namespace Widgets.Tests;
|
|
||||||
|
|
||||||
public class ConsoleRenderingEngineTests
|
|
||||||
{
|
|
||||||
private readonly IComponent _component;
|
|
||||||
|
|
||||||
public ConsoleRenderingEngineTests()
|
|
||||||
{
|
|
||||||
_component = Mock.Of<IComponent>(c =>
|
|
||||||
c.Render() == new Content("Lorem") &&
|
|
||||||
c.Alignment == new Alignment(Horizontal.Left, Vertical.Top));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void RenderSimple()
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == 9 && w.Height == 1);
|
|
||||||
var nodes = new Nodes { _component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 0), Times.Once());
|
|
||||||
Mock.Get(window).Verify(w => w.Write("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 RenderWithHorizontalAlignment(Horizontal alignment, string content, int windowSize,
|
|
||||||
int expectedPosition)
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == windowSize && w.Height == windowSize);
|
|
||||||
var component = Mock.Of<IComponent>(c => c.Render() == new Content(content) &&
|
|
||||||
c.Alignment == new Alignment(alignment, Vertical.Top));
|
|
||||||
var nodes = new Nodes { component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.Write(content), Times.Once());
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(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 RenderWithVerticalAlignment(Vertical alignment, string content, int windowSize, int[] expectedPositions)
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == windowSize && w.Height == windowSize);
|
|
||||||
var component = Mock.Of<IComponent>(c => c.Render() == new Content(content) &&
|
|
||||||
c.Alignment == new Alignment(Horizontal.Left, alignment));
|
|
||||||
var nodes = new Nodes { component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
foreach (var expectedCursorPosition in expectedPositions)
|
|
||||||
{
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(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 RenderWithAlignment(Horizontal horizontal, Vertical vertical, int expectedLeft, int expectedTop)
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == 6 && w.Height == 5);
|
|
||||||
var component = Mock.Of<IComponent>(c => c.Render() == new Content("VV") &&
|
|
||||||
c.Alignment == new Alignment(horizontal, vertical));
|
|
||||||
var nodes = new Nodes { component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(expectedLeft, expectedTop), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(Orientation.Horizontal, 9, 1)]
|
|
||||||
[InlineData(Orientation.Vertical, 5, 1)]
|
|
||||||
public void RenderWithOverload(Orientation orientation, int rootWidth, int rootHeight)
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == rootWidth && w.Height == rootHeight);
|
|
||||||
var nodes = new Nodes { _component, _component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes && r.Orientation == orientation);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 0), Times.Once());
|
|
||||||
Mock.Get(window).Verify(w => w.Write("Lorem"), Times.Once());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void RenderVerticalWithDoubleComponent()
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Height == 2 && w.Width == 10);
|
|
||||||
var nodes = new Nodes { _component, _component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes && r.Orientation == Orientation.Vertical);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 0), Times.Once());
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 1), Times.Once());
|
|
||||||
Mock.Get(window).Verify(w => w.Write("Lorem"), Times.Exactly(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void RenderHorizontalWithDoubleComponent()
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == 10 && w.Height == 1);
|
|
||||||
var nodes = new Nodes { _component, _component };
|
|
||||||
var container = Mock.Of<IContainer>(g => g.Nodes == nodes);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(container);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 0), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(5, 0), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.Write("Lorem"), Times.Exactly(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void RenderWithMultipleComponent()
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == 24 && w.Height == 1);
|
|
||||||
var nodes = new Nodes { _component, _component, _component, _component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 0), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(6, 0), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(12, 0), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(18, 0), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.Write("Lorem"), Times.Exactly(4));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void RenderWithContainerAndComponent()
|
|
||||||
{
|
|
||||||
var window = Mock.Of<IWindow>(w => w.Width == 10 && w.Height == 2);
|
|
||||||
var container = Mock.Of<IContainer>(c => c.Nodes == new Nodes { _component });
|
|
||||||
var nodes = new Nodes { container, _component };
|
|
||||||
var root = Mock.Of<IContainer>(r => r.Nodes == nodes && r.Orientation == Orientation.Vertical);
|
|
||||||
|
|
||||||
new ConsoleRenderingEngine(window).Render(root);
|
|
||||||
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 0), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.SetCursorPosition(0, 1), Times.Exactly(1));
|
|
||||||
Mock.Get(window).Verify(w => w.Write("Lorem"), Times.Exactly(2));
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,7 @@ public class LogoTests
|
|||||||
{
|
{
|
||||||
var logo = new Logo();
|
var logo = new Logo();
|
||||||
|
|
||||||
var render = logo.Render().ToString();
|
var render = logo.Draw().ToString();
|
||||||
|
|
||||||
Assert.Equal(
|
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",
|
" \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",
|
||||||
|
Loading…
Reference in New Issue
Block a user